u-ordinary-list.vue 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  1. <template>
  2. <view class="u-list" v-show="is_show_off">
  3. <!--分类-->
  4. <template v-if="showCat && catList.length > 1">
  5. <scroll-view scroll-x :style="{backgroundColor: catBgColor}"
  6. v-bind:class="[theme, 'u-scroll-view', 'dir-left-nowrap']">
  7. <text
  8. v-for="(item, index) in catList"
  9. v-bind:key="index"
  10. v-bind:class="[
  11. catStyle === 2 && activeCurrent === index ?
  12. 'u-active-current-round' :
  13. catStyle === 1 && activeCurrent === index ?
  14. 'u-active-current': 'u-default-text',
  15. catStyle === 2 ? 'u-current-round' : '',
  16. 'u-nav-item'
  17. ]"
  18. v-bind:style="catStyle === 2 && activeCurrent === index ? `background-color: ${tagColor ? tagColor : theme.background};color: ${catSelectedColor};`
  19. : catStyle === 1 && activeCurrent === index ? `color: ${catSelectedColor ? catSelectedColor : theme.color};border-color: ${tagColor ? tagColor : theme.border}`
  20. : catStyle === 1 ? `color: ${catUnselectedColor}`: `color: ${catUnselectedColor}`"
  21. v-on:click="changeNav(index)"
  22. >
  23. {{ item.menuName }}
  24. </text>
  25. </scroll-view>
  26. </template>
  27. <!--商品列表-->
  28. <view v-bind:class="goodsListClass">
  29. <!--列表模式-->
  30. <template v-if="listStyle === -1 || (!listStyle && listStyle !== 0)">
  31. <block v-for="(goods, index) in goodsList" v-bind:key="index">
  32. <view
  33. v-bind:class="[goodsStyleObject, 'main-between', 'u-list-mode', 'dir-left-nowrap']"
  34. hover-class="goods-hover-class"
  35. v-on:click.stop="router(goods)"
  36. >
  37. <view class="box-grow-0 u-left">
  38. <!-- 售罄 -->
  39. <view
  40. v-if="isShowStock(goods)"
  41. class="u-out-dialog"
  42. >
  43. <image
  44. class="u-dialog-img"
  45. v-bind:src="sellOutPic"
  46. ></image>
  47. </view>
  48. <!-- 角标 -->
  49. <image
  50. v-if="showGoodsTag == 1"
  51. v-bind:class="[tagLeftTop, 'u-goods-tag']"
  52. v-bind:src="goodsTagPicUrl"
  53. ></image>
  54. <!-- 商品封面图 -->
  55. <app-image
  56. borderRadius="16rpx"
  57. width="220rpx"
  58. height="220rpx"
  59. v-bind:img-src="goods.cover_pic"
  60. v-bind:mode="mode"
  61. ></app-image>
  62. </view>
  63. <view class="box-grow-1 u-right dir-top-nowrap main-between">
  64. <view
  65. v-if="(isDIY && showGoodsName) || isShowGoodsName"
  66. v-bind:class="[
  67. (goods.vip_card_appoint && goods.vip_card_appoint.discount) || ((goods.level_show === 1 || goods.level_show === 2) && goods.is_negotiable !== 1) ? 't-omit' : 't-omit-two',
  68. 'box-grow-0', 'u-goods-name'
  69. ]"
  70. >
  71. {{goods.name}}
  72. </view>
  73. <view class="box-grow-1 dir-left-nowrap cross-bottom">
  74. <view class="box-grow-1">
  75. <view v-if="isShowMemPrice(goods)" class="u-price-margin">
  76. <app-member-price
  77. v-bind:price="goods.level_price"
  78. :theme="theme"
  79. ></app-member-price>
  80. </view>
  81. <view v-if="isShowVip(goods)" class="u-price-margin">
  82. <app-sup-vip
  83. v-bind:is_vip_card_user="goods.vip_card_appoint.is_vip_card_user"
  84. v-bind:discount="goods.vip_card_appoint.discount"
  85. ></app-sup-vip>
  86. </view>
  87. <view
  88. v-if="showGoodsPrice || isShowOriginalPrice(goods)"
  89. v-bind:class="goods.is_sales === 1 ? 'dir-left-nowrap main-left cross-center' : 'dir-top-nowrap'"
  90. >
  91. <text v-if="showGoodsPrice" class="u-goods-price" :style="{'color': theme.color}">{{goods.price_content}}</text>
  92. <text
  93. v-if="isShowOriginalPrice(goods)"
  94. v-bind:class="[goods.is_sales === 1 ? 'u-original-margin' : '', 'u-original-price']"
  95. >{{goods.original_price}}</text>
  96. </view>
  97. <view v-if="goods.is_sales === 1 && goods.is_negotiable !== 1" class="u-goods-sales">{{goods.sales}}</view>
  98. </view>
  99. <template v-if="isShowCart && goods.goods_stock !== 0 && goods.is_negotiable !== 1 || (isDIY && isShowBuyBtn(goods))">
  100. <view
  101. v-if="buyBtn === 'text'"
  102. v-on:click.stop="buyProduct(goods)"
  103. v-bind:style="goods.buy_goods_auth ? btnStyle : disabledBtn"
  104. v-bind:class="[buyBtnClass, 'u-text-btn']"
  105. >{{buyBtnText}}</view>
  106. <view
  107. v-else
  108. v-on:click.stop="buyProduct(goods)"
  109. :style="{'background-color': goods.buy_goods_auth ? theme.background: '#999999'}"
  110. v-bind:class="['u-cart-btn-icon', 'box-grow-0', 'u-cart-btn-icon-' + buyBtn]"
  111. ></view>
  112. </template>
  113. </view>
  114. </view>
  115. </view>
  116. </block>
  117. </template>
  118. <!--左右滑动-->
  119. <template v-else-if="listStyle === 0">
  120. <scroll-view scroll-x class="u-swipe-left-right box-grow-0">
  121. <view class="dir-left-nowrap" id="swipe-left-right">
  122. <block v-for="(goods, index) in goodsList" v-bind:key="index">
  123. <view v-bind:class="goodsStyleObject" hover-class="goods-hover-class" v-on:click.stop="router(goods)" class="u-goods" >
  124. <view class="u-top">
  125. <!-- 售罄 -->
  126. <view
  127. v-if="isShowStock(goods)"
  128. class="u-out-dialog"
  129. >
  130. <image
  131. class="u-dialog-img"
  132. v-bind:src="sellOutPic"
  133. ></image>
  134. </view>
  135. <!-- 角标 -->
  136. <image
  137. v-if="showGoodsTag == 1"
  138. v-bind:class="[tagLeftTop, 'u-goods-tag']"
  139. v-bind:src="goodsTagPicUrl"
  140. ></image>
  141. <!-- 商品封面图 -->
  142. <app-image
  143. borderRadius="16rpx 16rpx 0 0"
  144. width="200rpx"
  145. height="200rpx"
  146. v-bind:img-src="goods.cover_pic"
  147. v-bind:mode="mode"
  148. ></app-image>
  149. </view>
  150. <view class="u-content-height dir-top-nowrap main-between">
  151. <view
  152. v-if="showGoodsName"
  153. v-bind:class="[textAlign, 'u-goods-name', 't-omit-two']"
  154. >
  155. {{goods.name}}
  156. </view>
  157. <view class="u-bottom">
  158. <view v-if="isShowMemPrice(goods)" v-bind:class="[pluginAlign, 'u-member-margin']">
  159. <app-member-price
  160. :theme="theme"
  161. v-bind:price="goods.level_price"
  162. ></app-member-price>
  163. </view>
  164. <view v-if="isShowVip(goods)" v-bind:class="[pluginAlign, 'u-member-margin']">
  165. <app-sup-vip
  166. v-bind:is_vip_card_user="goods.vip_card_appoint.is_vip_card_user"
  167. v-bind:discount="goods.vip_card_appoint.discount"
  168. ></app-sup-vip>
  169. </view>
  170. <view
  171. v-if="showGoodsPrice || isShowOriginalPrice(goods)"
  172. v-bind:class="[textAlign, 'dir-top-nowrap']"
  173. >
  174. <text v-if="showGoodsPrice" class="u-goods-price" :style="{'color': theme.color}">{{goods.price_content}}</text>
  175. <text
  176. v-if="isShowOriginalPrice(goods)"
  177. class="u-original-price"
  178. >{{goods.original_price}}</text>
  179. </view>
  180. </view>
  181. </view>
  182. </view>
  183. </block>
  184. </view>
  185. </scroll-view>
  186. </template>
  187. <!--一行一个-->
  188. <template v-else-if="listStyle === 1">
  189. <block v-for="(goods, index) in goodsList" v-bind:key="index">
  190. <view hover-class="goods-hover-class" v-bind:class="goodsStyleObject" v-on:click.stop="router(goods)" class="u-one-per-line" >
  191. <view class="u-top">
  192. <!-- 售罄 -->
  193. <view v-if="isShowStock(goods)" class="u-out-dialog">
  194. <image class="u-dialog-img" v-bind:src="sellOutPic"></image>
  195. </view>
  196. <!-- 角标 -->
  197. <image
  198. v-if="showGoodsTag == 1"
  199. v-bind:class="[tagLeftTop, 'u-goods-tag']"
  200. v-bind:src="goodsTagPicUrl"
  201. ></image>
  202. <!-- 商品封面图 -->
  203. <app-image
  204. width="100%"
  205. v-bind:img-src="goods.cover_pic"
  206. v-bind:height="coverPicHeight"
  207. v-bind:mode="mode"
  208. ></app-image>
  209. </view>
  210. <view v-if="showGoodsName" v-bind:class="[textAlign, 'u-goods-name', 't-omit-two']" >
  211. {{goods.name}}
  212. </view>
  213. <view class="u-bottom dir-left-nowrap cross-center">
  214. <view :style="{'color': theme.color}" class="box-grow-1 u-price">
  215. <view v-bind:class="[textStyle === 2 ? 'main-center' : '', 'dir-left-nowrap', 'cross-center']">
  216. <view v-if="showGoodsPrice" class="u-goods-price">
  217. {{goods.price_content}}
  218. </view>
  219. <view v-if="isShowMemPrice(goods)" class="u-member-margin">
  220. <app-member-price
  221. :theme="theme"
  222. v-bind:price="goods.level_price"
  223. ></app-member-price>
  224. </view>
  225. <view v-if="isShowVip(goods)" class="u-member-margin">
  226. <app-sup-vip
  227. v-bind:is_vip_card_user="goods.vip_card_appoint.is_vip_card_user"
  228. v-bind:discount="goods.vip_card_appoint.discount"
  229. ></app-sup-vip>
  230. </view>
  231. </view>
  232. <view v-bind:class="[textAlign, 'u-original-price']" v-if="isShowOriginalPrice(goods)">
  233. ¥{{goods.original_price}}
  234. </view>
  235. </view>
  236. <template v-if="isShowBuyBtn(goods) === 1 && textStyle !== 2">
  237. <view
  238. v-if="buyBtn === 'text'"
  239. v-on:click.stop="buyProduct(goods)"
  240. v-bind:class="[buyBtnClass, 'u-text-btn', 'box-grow-0']"
  241. v-bind:style="goods.buy_goods_auth ? btnStyle : disabledBtn"
  242. >{{buyBtnText}}</view>
  243. <view
  244. v-else
  245. v-on:click.stop="buyProduct(goods)"
  246. :style="{'background-color': goods.buy_goods_auth ? theme.background: '#999999'}"
  247. v-bind:class="['u-cart-btn-icon', 'box-grow-0', 'u-cart-btn-icon-' + buyBtn]"
  248. ></view>
  249. </template>
  250. </view>
  251. </view>
  252. </block>
  253. </template>
  254. <!--一行两个-->
  255. <template v-else-if="listStyle === 2">
  256. <block v-for="(goods, index) in goodsList" v-bind:key="index">
  257. <view
  258. hover-class="goods-hover-class"
  259. v-on:click.stop="router(goods)"
  260. v-bind:class="[goodsStyleObject, 'u-one-line-two', 'dir-top-nowrap']"
  261. >
  262. <view class="u-top box-grow-0" :style="{width: goodsStyle === 2 ? '344rpx': '346rpx'}">
  263. <!-- 售罄 -->
  264. <view
  265. v-if="isShowStock(goods)"
  266. :class="goodsStyle !== 2 ? 'u-out-dialog' : 'u-border-out-dialog'"
  267. >
  268. <image
  269. :class="goodsStyle !== 2 ? 'u-dialog-img' : 'u-border-dialog-img'"
  270. v-bind:src="sellOutPic"
  271. ></image>
  272. </view>
  273. <!-- 角标 -->
  274. <image
  275. v-if="showGoodsTag == 1"
  276. v-bind:class="[tagLeftTop, 'u-goods-tag']"
  277. v-bind:src="goodsTagPicUrl"
  278. ></image>
  279. <!-- 商品封面图 -->
  280. <app-image
  281. borderRadius="16rpx 16rpx 0 0"
  282. :width="goodsStyle === 2 ? '342rpx': '346rpx'"
  283. height="346rpx"
  284. v-bind:img-src="goods.cover_pic"
  285. v-bind:mode="mode"
  286. ></app-image>
  287. </view>
  288. <view v-bind:class="['u-bottom', 'box-grow-1', 'dir-top-nowrap', showGoodsName ? 'main-between' : 'main-right']">
  289. <view v-if="(isDIY && showGoodsName) || isShowGoodsName" v-bind:class="[textAlign, 'u-goods-name', 't-omit-two']">
  290. {{goods.name}}
  291. </view>
  292. <view class="box-grow-0 u-price dir-left-nowrap cross-bottom main-between" >
  293. <view class="box-grow-1">
  294. <view v-if="goods.sign == 'pick' && activity" class="u-margin dir-left-nowrap cross-bottom">
  295. <text :style="{'background-color': theme.background}" class="u-des-price">
  296. {{activity.rule_price}}元任选{{activity.rule_num}}件
  297. </text>
  298. </view>
  299. <view v-if="goods.sign === 'advance'" class="u-margin dir-left-nowrap cross-bottom">
  300. <text :style="{'background-color': theme.background}" class="u-des-price">
  301. 定金¥{{goods.deposit}}抵¥{{goods.swell_deposit}}
  302. </text>
  303. </view>
  304. <view v-if="goods.sign === 'flash_sale'" class="u-margin dir-left-nowrap cross-bottom">
  305. <text v-if="goods.discount_type === 1" :style="{'background-color': theme.background}" class="u-des-price">{{goods.min_discount}}折
  306. </text>
  307. <text v-if="goods.discount_type === 2" :style="{'background-color': theme.background}" class="u-des-price">减{{goods.min_discount}}元
  308. </text>
  309. </view>
  310. <view
  311. v-if="isShowMemPrice(goods)"
  312. v-bind:class="[pluginAlign, 'u-price-margin']"
  313. >
  314. <app-member-price :theme="theme" v-bind:price="goods.level_price"></app-member-price>
  315. </view>
  316. <view
  317. v-if="isShowVip(goods)"
  318. v-bind:class="[pluginAlign, 'u-price-margin']"
  319. >
  320. <app-sup-vip
  321. v-bind:is_vip_card_user="goods.vip_card_appoint.is_vip_card_user"
  322. v-bind:discount="goods.vip_card_appoint.discount"
  323. ></app-sup-vip>
  324. </view>
  325. <view v-if="showGoodsPrice || isShowOriginalPrice(goods)"
  326. v-bind:class="[goods.is_sales === 1 ? 'dir-left-nowrap main-left cross-center' : 'dir-top-nowrap', 'u-price-margin' , goods.is_sales === 1 ? pluginAlign : null]">
  327. <text v-if="showGoodsPrice" :style="{'color': theme.color}" v-bind:class="['u-goods-price', textAlign]">
  328. {{goods.price_content}}
  329. </text>
  330. <text v-if="isShowOriginalPrice(goods)" v-bind:class="[goods.is_sales === 1 ? 'u-original-margin' : '', 't-omit', 'u-original-price', textAlign]">
  331. ¥{{goods.original_price}}
  332. </text>
  333. </view>
  334. <view v-if="goods.is_sales === 1 && goods.is_negotiable !== 1" v-bind:class="[textAlign, 'u-goods-sales', !showGoodsPrice ? 'u-price-margin' : '']">{{goods.sales}}</view>
  335. </view>
  336. <template v-if="isShowCart && goods.goods_stock !== 0 && goods.is_negotiable !== 1 || (isDIY && isShowBuyBtn(goods) === 1 && textStyle !== 2)">
  337. <view
  338. v-if="buyBtn === 'text'"
  339. v-bind:class="[buyBtnClass, 'u-text-btn', 'box-grow-0']"
  340. v-bind:style="goods.buy_goods_auth ? btnStyle : disabledBtn"
  341. v-on:click.stop="buyProduct(goods)"
  342. >{{buyBtnText}}</view>
  343. <view
  344. v-else
  345. :style="{'background-color': goods.buy_goods_auth ? theme.background: '#999999'}"
  346. v-bind:class="['u-cart-btn-icon', 'box-grow-0', 'u-cart-btn-icon-' + buyBtn]"
  347. v-on:click.stop="buyProduct(goods)"
  348. ></view>
  349. </template>
  350. </view>
  351. </view>
  352. </view>
  353. </block>
  354. </template>
  355. <!--一行三个-->
  356. <template v-else-if="listStyle === 3">
  357. <block v-for="(goods, index) in goodsList" v-bind:key="index">
  358. <view
  359. hover-class="goods-hover-class"
  360. v-on:click.stop="router(goods)"
  361. v-bind:class="[goodsStyleObject, 'u-one-line-three', 'dir-top-nowrap', 'box-grow-0']"
  362. >
  363. <view class="u-top box-grow-0">
  364. <!-- 售罄 -->
  365. <view
  366. v-if="isShowStock(goods)"
  367. class="u-out-dialog"
  368. >
  369. <image
  370. class="u-dialog-img"
  371. v-bind:src="sellOutPic"
  372. ></image>
  373. </view>
  374. <!-- 角标 -->
  375. <image
  376. v-if="showGoodsTag == 1"
  377. v-bind:class="[tagLeftTop, 'u-goods-tag']"
  378. v-bind:src="goodsTagPicUrl"
  379. ></image>
  380. <!-- 商品封面图 -->
  381. <app-image
  382. borderRadius="16rpx 16rpx 0 0"
  383. :width="goodsStyle === 2 ? '222rpx' : '224rpx'"
  384. height="224rpx"
  385. v-bind:img-src="goods.cover_pic"
  386. v-bind:mode="mode"
  387. ></app-image>
  388. </view>
  389. <view class="u-bottom box-grow-1 dir-top-nowrap main-between">
  390. <view v-if="(isDIY && showGoodsName) || isShowGoodsName" v-bind:class="[textAlign, 'box-grow-0', 'u-goods-name', 't-omit-two']">
  391. {{goods.name}}
  392. </view>
  393. <view class="box-grow-1 dir-top-nowrap main-right">
  394. <view
  395. v-if="isShowMemPrice(goods)"
  396. v-bind:class="[pluginAlign, 'u-price-margin']"
  397. >
  398. <app-member-price :theme="theme" v-bind:price="goods.level_price"></app-member-price>
  399. </view>
  400. <view
  401. v-if="isShowVip(goods)"
  402. v-bind:class="[pluginAlign, 'u-price-margin']"
  403. >
  404. <app-sup-vip
  405. v-bind:is_vip_card_user="goods.vip_card_appoint.is_vip_card_user"
  406. v-bind:discount="goods.vip_card_appoint.discount"
  407. ></app-sup-vip>
  408. </view>
  409. <view class="box-grow-0 u-price-margin dir-left-nowrap cross-center" v-bind:class="[!showGoodsPrice && textStyle !== 2 ? 'main-right' : 'main-between', textStyle === 2 ? 'main-center' : '']">
  410. <view v-if="showGoodsPrice || isShowOriginalPrice(goods)" :style="{'color': theme.color}" class="u-goods-price">
  411. <view v-if="showGoodsPrice" v-bind:class="textAlign">{{goods.price_content}}</view>
  412. <view v-if="isShowOriginalPrice(goods)" v-bind:class="[textAlign, 'u-original-price']">¥{{goods.original_price}}</view>
  413. <view v-if="!isDIY && goods.is_sales === 1 && goods.is_negotiable !== 1" v-bind:class="['u-goods-sales']">{{goods.sales}}</view>
  414. </view>
  415. <view
  416. v-if="isShowCart && goods.goods_stock !== 0 && goods.is_negotiable !== 1 || (isDIY && isShowBuyBtn(goods) && textStyle !== 2)"
  417. v-on:click.stop="buyProduct(goods)"
  418. :style="{'background-color': goods.buy_goods_auth ? theme.background: '#999999'}"
  419. v-bind:class="['u-cart-btn-icon', 'box-grow-0', 'u-cart-btn-icon-' + buyBtn]"
  420. >
  421. </view>
  422. <view v-if="isDIY && isShowBuyBtn(goods) === 0 && textStyle !== 2 && showBuyBtn" class="u-cart-btn-icon"></view>
  423. </view>
  424. </view>
  425. </view>
  426. </view>
  427. </block>
  428. </template>
  429. </view>
  430. <!--购物车-->
  431. <template v-if="isShowAttr">
  432. <app-attr
  433. :goods="attrGoods.goods"
  434. :previewUrl="previewUrl"
  435. :submitUrl="submitUrl"
  436. :attrGroupList="attrGoods.goods.attr_groups"
  437. :theme="theme"
  438. :show="attrGoods.attrShow"
  439. ></app-attr>
  440. </template>
  441. </view>
  442. </template>
  443. <script>
  444. import { mapGetters, mapState } from "vuex";
  445. import appAttr from "../../../components/page-component/app-attr/app-attr.vue";
  446. import gConfig from "@/store/modules/globalConfiguration";
  447. export default {
  448. name: "u-goods-list",
  449. props: {
  450. // 活动信息
  451. activity: {
  452. type: Object
  453. },
  454. // 是否为DIY
  455. isDIY: {
  456. type: Boolean,
  457. default: false
  458. },
  459. // 是否显示分类
  460. showCat: {
  461. type: Boolean
  462. },
  463. // 分裂列表
  464. catList: {
  465. type: Array
  466. },
  467. // 分类样式
  468. catStyle: {
  469. type: Number
  470. },
  471. // 主题色
  472. theme: {
  473. type: Object
  474. },
  475. // 商品列表
  476. list: {
  477. type: Array
  478. },
  479. // 列表样式 -1 列表模式 0 左右滑动 1 一行一个 2 一行两个 3 一行三个
  480. listStyle: {
  481. type: [Number , Boolean]
  482. },
  483. // 列表模式显示分割线 1 显示 0 不显示
  484. borderShow: {
  485. type: Number
  486. },
  487. // 商品样式 1 白底无边框 2 白底有边框 3 无底无边框
  488. goodsStyle: {
  489. type: Number
  490. },
  491. // 商品封面图是否填充 0 留白 1 填充
  492. fill: {
  493. type: Number,
  494. default: 1
  495. },
  496. // 商品右上角角标 url
  497. goodsTagPicUrl: {
  498. type: String
  499. },
  500. // 是否展示角标 0 不展示 1 展示
  501. showGoodsTag: {
  502. type: Number
  503. },
  504. // 是否展示商品名称 0 不展示 1 展示
  505. showGoodsName: {
  506. type: [Number, Boolean],
  507. default: 1
  508. },
  509. // 是否展示商品价格 0 不展示 1 展示
  510. showGoodsPrice: {
  511. type: [Number, Boolean],
  512. default: 1
  513. },
  514. // 显示购买按钮 0 不展示 1 展示
  515. showBuyBtn: {
  516. type: [Number, Boolean],
  517. default: 1
  518. },
  519. // 购买按钮样式 cart 购物车 add 加号 text 文字
  520. buyBtn: {
  521. type: String,
  522. default: 'cart'
  523. },
  524. // 按钮样式
  525. buyBtnStyle: {
  526. type: Number
  527. },
  528. // 按钮文案
  529. buyBtnText: {
  530. type: String
  531. },
  532. // text按钮颜色
  533. buttonColor: {
  534. type: String
  535. },
  536. // 文本对齐方式 1 左对齐 2 居中
  537. textStyle: {
  538. type: Number
  539. },
  540. // 商品封面图宽高比例 1-1 3-2
  541. goodsCoverProportion: {
  542. type: String
  543. },
  544. // 原价显示
  545. isUnderLinePrice: {
  546. type: Boolean,
  547. default: true
  548. },
  549. // 是否显示规格
  550. isShowAttr: {
  551. type: Boolean,
  552. default: false
  553. },
  554. isBuy: {
  555. type: Boolean,
  556. default: true
  557. },
  558. // 预览接口
  559. previewUrl: {
  560. type: String
  561. },
  562. // 支付接口
  563. submitUrl: {
  564. type: String
  565. },
  566. // 载入间隔
  567. addTime: {
  568. type: Number,
  569. default: 0
  570. },
  571. // 分页加载
  572. pagination: {
  573. type: Boolean,
  574. default: false
  575. },
  576. reset: {
  577. type: Boolean,
  578. default: false
  579. },
  580. //标签颜色
  581. tagColor: {
  582. type: String
  583. },
  584. //选中颜色
  585. catSelectedColor: {
  586. type: String
  587. },
  588. //未选中颜色
  589. catUnselectedColor: {
  590. type: String
  591. },
  592. //背景色
  593. catBgColor: {
  594. type: String
  595. },
  596. },
  597. computed: {
  598. ...mapState({
  599. // 全局设置
  600. appSetting: function(state) {
  601. return state.mallConfig.mall.setting
  602. },
  603. // 小程序图片
  604. appImg: function(state) {
  605. return state.mallConfig.__wxapp_img.mall;
  606. },
  607. // 全局显示购物车
  608. isShowCart: function(state) {
  609. return !this.isDIY && state.mallConfig.mall.setting.is_show_cart && this.showBuyBtn;
  610. },
  611. // 全局显示商品名称
  612. isShowGoodsName: function(state) {
  613. return !this.isDIY && state.mallConfig.mall.setting.is_show_goods_name;
  614. },
  615. platform: function(state) {
  616. return state.gConfig.systemInfo.platform;
  617. }
  618. }),
  619. ...mapGetters('mallConfig',{
  620. getVideo: 'getVideo'
  621. }),
  622. // 获取商品数组
  623. copyList() {
  624. if (!this.is_show_off) return [];
  625. if (this.showCat) {
  626. return this.catList[this.activeCurrent].goodsList;
  627. } else {
  628. return this.list;
  629. }
  630. },
  631. // 商品样式
  632. goodsStyleObject: function() {
  633. let str = '';
  634. this.goodsStyle === 2 ? str += 'u-is-border ' : '';
  635. this.goodsStyle !== 3 ? str += 'u-white-back': '';
  636. return str;
  637. },
  638. // 商品封面图是否填充
  639. mode: function() {
  640. let str = '';
  641. this.fill === 1 ? str = 'aspectFill' : str = 'aspectFit';
  642. return str;
  643. },
  644. // 售罄图片
  645. sellOutPic: function() {
  646. return this.appSetting.is_use_stock === '1' ? this.appImg.plugins_out : this.appSetting.sell_out_pic;
  647. },
  648. // 角标弧度
  649. tagLeftTop: function() {
  650. return this.listStyle === -1 || this.listStyle === 0 || this.listStyle === 2 || this.listStyle === 3 ? 'u-goods-tag-radius' : '';
  651. },
  652. // 文字按钮样式
  653. buyBtnClass: function() {
  654. let buyBtnClass = ``;
  655. if (this.buyBtnStyle == 2 || this.buyBtnStyle == 4) {
  656. buyBtnClass += `u-text-btn-border `;
  657. }
  658. if (this.buyBtnStyle == 4 || this.buyBtnStyle == 3) {
  659. buyBtnClass += `u-text-btn-radius`;
  660. }
  661. return buyBtnClass;
  662. },
  663. // 按钮样式
  664. btnStyle: function() {
  665. let btnStyle = ``;
  666. if (this.buyBtnStyle == 1 || this.buyBtnStyle == 3) {
  667. btnStyle += `background-color: ${this.buttonColor ? this.buttonColor : this.theme.background};color: #ffffff;`;
  668. } else {
  669. btnStyle += `border-color: ${this.buttonColor ? this.buttonColor : this.theme.background};color: ${this.buttonColor};`;
  670. }
  671. return btnStyle;
  672. },
  673. disabledBtn: function() {
  674. let btnStyle = ``;
  675. if (this.buyBtnStyle == 1 || this.buyBtnStyle == 3) {
  676. btnStyle += `background-color: ${this.disabledColor};color: #ffffff;`;
  677. } else {
  678. btnStyle += `border-color: ${this.disabledColor};color: ${this.disabledColor};`;
  679. }
  680. return btnStyle;
  681. },
  682. // 文本对齐方式
  683. textAlign: function() {
  684. return this.textStyle === 2 ? 'u-text-align' : null;
  685. },
  686. // 插件对齐方式
  687. pluginAlign: function() {
  688. return this.textStyle === 2 ? 'dir-left-nowrap main-center' : null;
  689. },
  690. // 一行一个图片高度
  691. coverPicHeight: function() {
  692. return this.goodsCoverProportion === '1-1' ? '702rpx' : '468rpx';
  693. },
  694. // 商品列表样式
  695. goodsListClass: function() {
  696. if (this.listStyle === 2) {
  697. return 'dir-left-wrap main-between u-goods-list';
  698. } else if (this.listStyle === 3) {
  699. return 'dir-left-wrap main-left u-one-line-three-list';
  700. } else if (this.listStyle === 0) {
  701. return 'u-swipe-left-right-list';
  702. } else if (this.borderShow === 1) {
  703. return 'u-goods-list u-bottom-border';
  704. } else {
  705. return 'u-goods-list';
  706. }
  707. }
  708. },
  709. data() {
  710. return {
  711. // 当前选中分类
  712. activeCurrent: 0,
  713. // 是否展示
  714. is_show_off: true,
  715. // 规格商品
  716. attrGoods: {
  717. goods: {},
  718. attrShow: 0
  719. },
  720. // 临时列表
  721. tempList: [],
  722. // 商品数组
  723. goodsList: [],
  724. disabledColor: '#999999',
  725. disable: 'disable',
  726. }
  727. },
  728. methods: {
  729. // 复制而不是引用对象和数组
  730. cloneData(data) {
  731. return JSON.parse(JSON.stringify(data));
  732. },
  733. // 循环载入
  734. splitData() {
  735. if (!this.tempList.length) return;
  736. let item = this.tempList[0];
  737. this.goodsList.push(item);
  738. this.tempList.splice(0, 1);
  739. if (this.tempList.length) {
  740. setTimeout(() => {
  741. this.splitData();
  742. }, this.addTime);
  743. }
  744. },
  745. // 切换分类
  746. changeNav(index) {
  747. this.goodsList = [];
  748. this.activeCurrent = index;
  749. this.tempList = this.cloneData(this.copyList);
  750. this.splitData();
  751. },
  752. // 是否展示售罄
  753. isShowStock(goods) {
  754. return this.appSetting.is_show_stock === 1 && goods.goods_stock === 0 ? 1: 0;
  755. },
  756. // 是否展示购物按钮
  757. isShowBuyBtn(goods) {
  758. return this.showBuyBtn && goods.goods_stock !== 0 && goods.is_negotiable !== 1 ? 1 : 0;
  759. },
  760. // 是否展示会员价
  761. isShowMemPrice(goods) {
  762. return (goods.level_show === 1 || goods.level_show === 2) && goods.is_negotiable !== 1 ? 1 : 0;
  763. },
  764. // 是否展示超级会员价
  765. isShowVip(goods) {
  766. return goods.vip_card_appoint && goods.vip_card_appoint.discount && goods.is_negotiable !== 1 ? 1 : 0;
  767. },
  768. // 是否显示原价
  769. isShowOriginalPrice(goods) {
  770. return this.isUnderLinePrice && goods.is_negotiable !== 1 ? 1 : 0;
  771. },
  772. // 购买按钮点击事件
  773. buyProduct(goods) {
  774. if(this.isBuy) {
  775. if (this.isShowAttr) {
  776. this.attrGoods.goods = goods;
  777. this.attrGoods.attrShow = Math.random();
  778. } else {
  779. uni.showLoading({
  780. text: '',
  781. mask: true
  782. });
  783. this.$request({
  784. url: this.$api.goods.attr,
  785. data: {
  786. id: goods.id,
  787. mch_id: goods.mch_id
  788. }
  789. }).then(e => {
  790. uni.hideLoading();
  791. if (e.code === 0) {
  792. let data = Object.assign(goods, e.data);
  793. this.$emit('buyProduct', {
  794. goods: data,
  795. attrShow: Math.random()
  796. });
  797. } else {
  798. uni.showToast({
  799. title: e.msg,
  800. icon: 'none'
  801. })
  802. }
  803. })
  804. }
  805. }else {
  806. this.router(goods);
  807. }
  808. },
  809. // 路由跳转
  810. router(goods) {
  811. // #ifdef MP-BAIDU
  812. uni.navigateTo({
  813. url: goods.page_url
  814. });
  815. // #endif
  816. // #ifndef MP-BAIDU
  817. if (goods.video_url && this.getVideo == 1 && !(goods.sign === 'lottery' || goods.sign === 'bargain' || goods.sign === 'wholesale')) {
  818. let id = goods.id;
  819. if (goods.sign === 'advance') {
  820. id = goods.id ? goods.id : goods.goods_id;
  821. } else if (goods.sign === 'gift') {
  822. id = id + '&is_share=1';
  823. }
  824. // #ifdef MP
  825. uni.navigateTo({
  826. url: `/pages/goods/video?goods_id=${id}&sign=${goods.sign}`
  827. });
  828. // #endif
  829. // #ifdef H5
  830. uni.navigateTo({
  831. url: goods.page_url
  832. });
  833. // #endif
  834. } else {
  835. uni.navigateTo({
  836. url: goods.page_url
  837. });
  838. }
  839. // #endif
  840. },
  841. empty() {
  842. this.goodsList = [];
  843. }
  844. },
  845. watch: {
  846. catList: {
  847. handler(newValue) {
  848. if (!this.showCat) return;
  849. !this.$validation.array(newValue) || this.$validation.isEmpty(newValue) ? this.is_show_off = false : this.is_show_off = true;
  850. },
  851. deep: true,
  852. immediate: true
  853. },
  854. copyList: {
  855. handler(nVal, oVal) {
  856. if (nVal) {
  857. if (this.pagination && !this.reset) {
  858. let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0;
  859. this.tempList = this.tempList.concat(this.cloneData(nVal.slice(startIndex)));
  860. } else {
  861. this.goodsList = [];
  862. this.tempList = this.cloneData(nVal);
  863. }
  864. this.splitData();
  865. }
  866. this.tempList && this.splitData();
  867. },
  868. deep: true,
  869. immediate: true
  870. }
  871. },
  872. components: {
  873. appAttr
  874. }
  875. }
  876. </script>
  877. <style scoped lang="scss">
  878. .u-des-price {
  879. display: inline-block;
  880. font-size: 19upx;
  881. color: #ffffff;
  882. border-radius: 7upx;
  883. padding: 0upx 5upx;
  884. }
  885. .u-list {
  886. width: 750upx;
  887. overflow: hidden;
  888. }
  889. .u-scroll-view {
  890. white-space: nowrap;
  891. width: 750upx;
  892. height: 99upx;
  893. padding: 0 5upx;
  894. .u-current-round {
  895. height: 56upx;
  896. padding-left: 24upx;
  897. padding-right: 24upx;
  898. border-radius: 30upx;
  899. line-height: 56upx;
  900. margin: 21.5upx 24upx;
  901. }
  902. }
  903. .u-nav-item {
  904. display: inline-block;
  905. height: 97upx;
  906. line-height: 97upx;
  907. font-size: 26upx;
  908. margin: 0 44upx;
  909. white-space: nowrap;
  910. border-bottom: 1upx solid transparent;
  911. }
  912. .u-active-current-round {
  913. color: white;
  914. }
  915. .u-default-text {
  916. color: #666666;
  917. }
  918. .u-goods-list {
  919. padding: 24upx 24upx 0 24upx;
  920. &.u-bottom-border {
  921. padding: 0;
  922. padding-top: 24upx;
  923. >.u-list-mode {
  924. padding: 16upx 24upx;
  925. margin-bottom: 0;
  926. border-radius: 0;
  927. border-bottom: 1upx solid #e2e2e2;
  928. &:last-of-type {
  929. border-bottom: 0;
  930. }
  931. }
  932. }
  933. }
  934. .u-swipe-left-right-list {
  935. // #ifdef MP-BAIDU
  936. width: 750upx;
  937. height: 424upx;
  938. // #endif
  939. padding: 24upx 0 0 24upx;
  940. }
  941. .u-is-border {
  942. border: 1upx solid #e2e2e2;
  943. }
  944. .u-white-back {
  945. background-color: #ffffff;
  946. }
  947. %background-image {
  948. background-repeat: no-repeat;
  949. background-size: cover;
  950. background-position: center;
  951. }
  952. .u-text-btn {
  953. height: 48upx;
  954. line-height: 48upx;
  955. padding: 0 20upx;
  956. font-size: 28upx;
  957. }
  958. .u-text-btn-radius {
  959. border-radius: 24upx;
  960. }
  961. .u-text-btn-border {
  962. border: 1upx solid;
  963. }
  964. .u-out-dialog {
  965. position: absolute;
  966. height: 100%;
  967. z-index: 11;
  968. top: 0;
  969. left: 0;
  970. background-color: rgba(0,0,0,.5);
  971. }
  972. .u-border-out-dialog {
  973. position: absolute;
  974. height: 100%;
  975. z-index: 11;
  976. top: 0;
  977. left: 0;
  978. background-color: rgba(0,0,0,.5);
  979. }
  980. .u-text-align {
  981. text-align: center;
  982. }
  983. .u-goods-tag {
  984. position: absolute;
  985. left: 0;
  986. top: 0;
  987. z-index: 10;
  988. width: 64upx;
  989. height: 64upx;
  990. }
  991. .u-goods-tag-radius {
  992. border-top-left-radius: 16upx;
  993. }
  994. .u-original-price {
  995. color: #999999;
  996. font-size: 22upx;
  997. text-decoration: line-through;
  998. }
  999. .u-goods-sales {
  1000. color: #b5b5b5;
  1001. font-size: 24upx;
  1002. }
  1003. .u-cart-btn-icon {
  1004. width: 50upx;
  1005. height: 50upx;
  1006. @extend %background-image;
  1007. }
  1008. .u-cart-btn-icon-cart {
  1009. background-image: url('../../../static/image/icon/cats.png');
  1010. }
  1011. .u-cart-btn-icon-add {
  1012. background-image: url('../../../static/image/icon/add-to.png');
  1013. }
  1014. .u-goods-name {
  1015. color: #353535;
  1016. }
  1017. .u-original-margin {
  1018. margin-left: 10upx;
  1019. }
  1020. .u-price-margin {
  1021. margin-top: 5upx;
  1022. }
  1023. .u-list-mode {
  1024. margin-bottom: 32upx;
  1025. border-radius: 16upx;
  1026. .u-right {
  1027. height: 220upx;
  1028. padding: 28upx 24upx 15upx 20upx;
  1029. }
  1030. .u-left {
  1031. position: relative;
  1032. }
  1033. .u-out-dialog {
  1034. width: 220upx;
  1035. border-radius: 16upx;
  1036. }
  1037. .u-dialog-img {
  1038. border-radius: 16upx;
  1039. width: 220upx;
  1040. height: 220upx;
  1041. }
  1042. .u-goods-name {
  1043. font-size: 28upx;
  1044. line-height: 38upx;
  1045. }
  1046. .u-goods-price {
  1047. font-size: 30upx;
  1048. }
  1049. }
  1050. .u-swipe-left-right {
  1051. // #ifdef MP-BAIDU
  1052. height: 424upx;
  1053. // #endif
  1054. padding-bottom: 24upx;
  1055. white-space: nowrap;
  1056. .u-goods {
  1057. display: inline-block;
  1058. border-radius: 16upx;
  1059. padding-bottom: 16upx;
  1060. margin-right: 16upx;
  1061. }
  1062. .u-top {
  1063. position: relative;
  1064. margin-bottom: 8upx;
  1065. }
  1066. .u-out-dialog {
  1067. width: 200upx;
  1068. border-radius: 16upx 16upx 0 0;
  1069. overflow: hidden;
  1070. }
  1071. .u-dialog-img {
  1072. width: 200upx;
  1073. height: 200upx;
  1074. }
  1075. .u-bottom {
  1076. padding: 0 10upx;
  1077. }
  1078. .u-goods-name {
  1079. font-size: 23upx;
  1080. line-height: 33upx;
  1081. margin-bottom: 8upx;
  1082. padding: 0 10upx 0 10upx;
  1083. }
  1084. .u-goods-price {
  1085. font-size: 23upx;
  1086. }
  1087. .u-member-margin {
  1088. margin-bottom: 8upx;
  1089. }
  1090. .u-content-height {
  1091. width: 200upx;
  1092. height: calc(100% - 208upx);
  1093. }
  1094. }
  1095. .u-one-per-line {
  1096. margin-bottom: 24upx;
  1097. border-radius: 16upx;
  1098. overflow: hidden;
  1099. .u-top {
  1100. position: relative;
  1101. width: 100%;
  1102. }
  1103. .u-out-dialog {
  1104. width: 100%;
  1105. }
  1106. .u-dialog-img {
  1107. width: 100%;
  1108. height: 100%;
  1109. }
  1110. .u-bottom {
  1111. padding: 0 24upx 21upx 24upx;
  1112. margin-top: 16upx;
  1113. }
  1114. .u-goods-name {
  1115. padding: 30upx 24upx 0 24upx;
  1116. font-size: 28upx;
  1117. line-height: 38upx;
  1118. }
  1119. .u-goods-price {
  1120. font-size: 28upx;
  1121. }
  1122. .u-member-margin {
  1123. margin-left: 10upx;
  1124. }
  1125. }
  1126. .u-one-line-two {
  1127. width: 346upx;
  1128. margin-bottom: 25upx;
  1129. border-radius: 16upx;
  1130. .u-top {
  1131. width: 346upx;
  1132. height: 346upx;
  1133. position: relative;
  1134. }
  1135. .u-out-dialog, .u-dialog-img {
  1136. width: 346upx;
  1137. height: 346upx;
  1138. border-radius: 16upx 16upx 0 0;
  1139. }
  1140. .u-border-out-dialog, .u-border-dialog-img {
  1141. width: 344upx;
  1142. height: 346upx;
  1143. border-radius: 16upx 16upx 0 0;
  1144. }
  1145. .u-bottom {
  1146. padding-bottom: 15upx;
  1147. }
  1148. .u-goods-name {
  1149. margin-top: 20upx;
  1150. font-size: 28upx;
  1151. padding: 0 24upx;
  1152. line-height: 38upx;
  1153. }
  1154. .u-price {
  1155. padding: 0 24upx;
  1156. }
  1157. .u-goods-price {
  1158. font-size: 28upx;
  1159. }
  1160. }
  1161. .u-one-line-three-list {
  1162. padding: 24upx 9upx 0 24upx;
  1163. }
  1164. .u-one-line-three {
  1165. width: 224upx;
  1166. margin:0 15upx 16upx 0;
  1167. border-radius: 16upx;
  1168. overflow: hidden;
  1169. .u-top {
  1170. position: relative;
  1171. }
  1172. .u-top, .u-out-dialog, .u-dialog-img {
  1173. width: 224upx;
  1174. height: 224upx;
  1175. border-right: 16upx 16upx 0 0;
  1176. }
  1177. .u-goods-name {
  1178. font-size: 26upx;
  1179. margin-top: 10upx;
  1180. line-height: 36upx;
  1181. }
  1182. .u-bottom {
  1183. padding: 0 10upx 15upx 10upx;
  1184. }
  1185. .u-goods-price {
  1186. font-size: 25upx;
  1187. }
  1188. .u-cart-btn-icon {
  1189. width: 45upx;
  1190. height: 45upx;
  1191. }
  1192. .u-goods-sales {
  1193. font-size: 22upx;
  1194. }
  1195. }
  1196. // #ifdef MP-BAIDU
  1197. #swipe-left-right {
  1198. width: 750upx;
  1199. height :400upx;
  1200. }
  1201. // #endif
  1202. </style>