goodsGroupDetail.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <view :class="['qn-page-' + theme]">
  3. <view class="goods-ul">
  4. <view class="goods-li clearfix" v-for="(item, index) in group_detail.goodsData" :key="index">
  5. <view class="float_left goods-img">
  6. <block v-if="item.isDistribution === 4">
  7. <view v-if="!(item.inventorTotal - 0) || item.inventorTotal - 0 <= 0" class="sale-end"><text class="ibonfont ibonbuhuozhong"></text></view>
  8. </block>
  9. <image :src="item.images[0]" mode="aspectFill"></image>
  10. </view>
  11. <view class="float_left goods-info">
  12. <view class="goods-name ellipsis">{{ item.title }}</view>
  13. <view class="goods-sku" @click="skuOpen(item, index)">
  14. <block v-if="item.nowSkuData">
  15. <text>{{ item.nowSkuData.unitName }};</text>
  16. <text v-for="(spec, specI) in item.nowSkuData.specGroup" :key="specI">{{ spec.specValueName }};</text>
  17. </block>
  18. <text v-else>请选择商品规格</text>
  19. <text class="ibonfont iboncollpse"></text>
  20. </view>
  21. <view class="num-view clearfix">
  22. <view class="godos-price float_left">原价 ¥{{ item.maxMarketPrice }}</view>
  23. <view class="goods-num float_right">
  24. <text class="ibonfont ibonguanbi1"></text>
  25. <text>1</text>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. <view class="bottom-view clearfix">
  32. <view class="price-main float_left">
  33. <view class="total">
  34. <text>总价:</text>
  35. <text class="primary-color">¥{{ group_detail.price || '0.00' }}</text>
  36. </view>
  37. <view class="desc">已省¥{{ group_detail.originPrice - group_detail.price }}</view>
  38. </view>
  39. <view class="confirm-btn float_right" @click="buyNow">立即购买</view>
  40. </view>
  41. <u-popup :mask-close-able="false" border-radius="16" mode="bottom" v-model="sku_show">
  42. <view class="sku-sel-pop" v-if="goods_detail.id">
  43. <text class="ibonfont ibonguanbi1" @click="skuCancel"></text>
  44. <view class="goods-view clearfix">
  45. <view class="float_left goods-img"><image :src="goods_detail.images[0]" mode="aspectFill"></image></view>
  46. <view class="float_right goods-info">
  47. <view class="goods-name ellipsis">{{ goods_detail.title }}</view>
  48. <block v-if="now_sku_data.id">
  49. <view class="goods-stock">库存:{{ Number(now_sku_data.inventory) || 0 }}</view>
  50. <view class="goods-price">原价:¥{{ now_sku_data.salePrice || 0 }}</view>
  51. </block>
  52. <block v-else>
  53. <view class="goods-stock">库存:{{ Number(goods_detail.inventory) || 0 }}</view>
  54. <view class="goods-price">原价:¥{{ goods_detail.maxSalePrice || 0 }}</view>
  55. </block>
  56. </view>
  57. </view>
  58. <scroll-view scroll-y="true" style="max-height: 700upx;overflow-y: auto;">
  59. <view class="sku-ul">
  60. <view class="sku-li">
  61. <view class="sku-name">单位</view>
  62. <view class="sku-val-ul">
  63. <view
  64. class="sku-val-li"
  65. v-for="(unit, uniti) in goods_detail.unitData"
  66. :key="uniti"
  67. :class="[parseInt(spec_id_group[1]) === parseInt(unit.unitId) ? 'primary-btn-pain' : '']"
  68. @click="changeSku(unit.unitId, 1, '', unit)"
  69. >
  70. <text :style="{ color: !unit.isdisabled ? '#999' : '' }">{{ unit.unitName }}</text>
  71. </view>
  72. </view>
  73. </view>
  74. <view class="sku-li" v-for="(item, index) in goods_detail.specGroup" :key="index">
  75. <view class="sku-name">{{ item.groupSpec.specName }}</view>
  76. <view class="sku-val-ul">
  77. <view
  78. v-for="(sku, skuI) in item.params"
  79. :key="skuI"
  80. class="sku-val-li"
  81. :class="[parseInt(spec_id_group[index + 2]) === parseInt(sku.specValueId) ? 'primary-btn-pain' : '']"
  82. @click="changeSku(sku.specValueId, index + 2, item.groupSpec.specId, sku)"
  83. >
  84. <text :style="{ color: !sku.isdisabled ? '#999' : '' }">{{ sku.specValueName }}</text>
  85. </view>
  86. </view>
  87. </view>
  88. </view>
  89. </scroll-view>
  90. <view class="confirm-btn primary-btn" @click="skuConfirm">确定</view>
  91. </view>
  92. </u-popup>
  93. </view>
  94. </template>
  95. <script>
  96. export default {
  97. data() {
  98. return {
  99. sku_show: false,
  100. group_id: '',
  101. group_detail: {},
  102. goods_detail: {},
  103. now_sku_data: {},
  104. spec_id_group: [],
  105. goods_index: ''
  106. };
  107. },
  108. computed: {
  109. baseSet() {
  110. return this.$store.state.baseSet;
  111. }
  112. },
  113. onLoad(options) {
  114. this.group_id = options.id;
  115. this.detailsApiComBinPackage();
  116. },
  117. onShow() {},
  118. methods: {
  119. skuConfirm() {
  120. if (!this.now_sku_data.id) {
  121. this.$u.toast('请选择要购买的规格');
  122. return;
  123. }
  124. if (this.goods_detail.joinSku && this.goods_detail.joinSku.length) {
  125. if (this.goods_detail.joinSku.indexOf(this.now_sku_data.id) === -1) {
  126. this.$u.toast('抱歉该规格没有参与组合套餐活动');
  127. return;
  128. }
  129. }
  130. this.skuCancel();
  131. },
  132. skuCancel() {
  133. this.sku_show = false;
  134. },
  135. skuOpen(goods, index) {
  136. this.sku_show = true;
  137. this.spec_id_group = [goods.id];
  138. this.now_sku_data = {};
  139. this.goods_index = index;
  140. // 过滤出没有参与活动的规格
  141. if (goods.joinSku && goods.joinSku.length) {
  142. goods.specMultiple = goods.specMultiple.filter(item => goods.joinSku.includes(item.id));
  143. }
  144. // 多规格时处理属性禁用标示
  145. if (goods.specType === 2) {
  146. goods.specGroup = goods.specGroup.map(item => {
  147. return {
  148. ...item,
  149. params: item.params.map(itemP => {
  150. return {
  151. ...itemP,
  152. isdisabled: true
  153. };
  154. })
  155. };
  156. });
  157. goods.unitData.forEach(item => {
  158. item.isdisabled = true;
  159. });
  160. } else {
  161. //单规格 添加当前单位没有库存的标记
  162. const arr = goods.specMultiple.filter(item => item.inventory <= 0);
  163. goods.unitData.forEach(item => {
  164. // 没有开启预售判断库存
  165. if (goods.isDistribution === 4) {
  166. item.isdisabled = !arr.find(itemF => itemF.unitId === item.unitId);
  167. } else {
  168. item.isdisabled = true;
  169. }
  170. });
  171. }
  172. this.goods_detail = goods;
  173. },
  174. async detailsApiComBinPackage() {
  175. this.$u.api.detailsApiComBinPackage(this.group_id).then(res => {
  176. this.group_detail = res.data;
  177. });
  178. },
  179. changeSku(id, index, specId, row) {
  180. if (row && !row.isdisabled) {
  181. return;
  182. }
  183. this.$set(this.spec_id_group, index, parseInt(id));
  184. if (this.spec_id_group.every(item => !!item)) {
  185. const indexGroup = this.spec_id_group.join(':');
  186. const nowSkuData = this.goods_detail.specMultiple.find(item => item.index === indexGroup);
  187. if (nowSkuData) {
  188. this.now_sku_data = nowSkuData;
  189. let target = this.$u.deepClone(this.group_detail);
  190. target.goodsData[this.goods_index].nowSkuData = nowSkuData;
  191. this.group_detail = target;
  192. }
  193. }
  194. // 判断当前规格是否要禁用,规格组不存在或者库存为0的时候,当前规格禁用
  195. if (index) {
  196. // 过滤出包含当前规格的规格组
  197. const containSpecMultiple = this.goods_detail.specMultiple.filter(item => item.indexGroup.includes(id + ''));
  198. const target = this.$u.deepClone(this.goods_detail.specGroup);
  199. target.forEach(item => {
  200. if (item.groupSpec.specId !== specId) {
  201. item.params.forEach(itemP => {
  202. // 没有开启预售判断库存
  203. if (this.baseSet.preSale === 4) {
  204. const isObj = containSpecMultiple.find(itemF => {
  205. return itemF.indexGroup.includes(itemP.specValueId + '');
  206. });
  207. itemP.isdisabled = !!isObj && isObj.inventory > 0;
  208. } else {
  209. itemP.isdisabled = true;
  210. }
  211. });
  212. }
  213. });
  214. // console.log(target);
  215. this.goods_detail.specGroup = target;
  216. }
  217. },
  218. buyNow() {
  219. const isBuy = this.group_detail.goodsData.find(item => {
  220. return !item.nowSkuData;
  221. });
  222. if (isBuy) {
  223. this.$u.toast('请选择规格');
  224. return;
  225. }
  226. const lists = this.group_detail.goodsData.map(item => {
  227. return {
  228. goodsId: item.id,
  229. skuId: item.nowSkuData.id,
  230. buyNum: 1
  231. };
  232. });
  233. const params = {
  234. sourceType: 1, //组合套餐固定传1
  235. comBinId: this.group_id, //组合套餐id
  236. lists: lists
  237. };
  238. this.goPage('/pageT/order/createOrder?params=' + JSON.stringify(params));
  239. }
  240. }
  241. };
  242. </script>
  243. <style lang="scss" scoped>
  244. .goods-ul {
  245. padding: 0 36rpx;
  246. background-color: #ffffff;
  247. .goods-li {
  248. padding: 30rpx 0;
  249. border-bottom: 1px solid #f5f5f5;
  250. &:last-child {
  251. border-bottom: 0 none;
  252. }
  253. .goods-img {
  254. padding-right: 20rpx;
  255. position: relative;
  256. image {
  257. display: block;
  258. width: 210rpx;
  259. height: 210rpx;
  260. border-radius: 10rpx;
  261. }
  262. .sale-end {
  263. position: absolute;
  264. width: 210rpx;
  265. height: 210rpx;
  266. border-radius: 10upx;
  267. display: block;
  268. left: 0;
  269. top: 0;
  270. z-index: 1;
  271. text-align: center;
  272. line-height: 210rpx;
  273. background-color: rgba($color: #000000, $alpha: 0.3);
  274. .ibonfont {
  275. font-size: 120rpx;
  276. color: #ffffff;
  277. }
  278. }
  279. }
  280. .goods-info {
  281. width: 444rpx;
  282. .goods-sku {
  283. margin-top: 12rpx;
  284. line-height: 46rpx;
  285. padding-left: 10rpx;
  286. padding-right: 46rpx;
  287. font-size: 24rpx;
  288. color: #999999;
  289. background-color: #fafafa;
  290. border-radius: 8rpx;
  291. position: relative;
  292. display: inline-block;
  293. .iboncollpse {
  294. font-size: 24rpx;
  295. color: #999999;
  296. position: absolute;
  297. right: 10rpx;
  298. top: 50%;
  299. transform: translateY(-50%);
  300. }
  301. }
  302. .num-view {
  303. font-size: 24rpx;
  304. color: #999999;
  305. padding-top: 30rpx;
  306. .goods-num {
  307. .ibonguanbi1 {
  308. font-size: 16rpx;
  309. color: #999999;
  310. width: 38rpx;
  311. display: inline-block;
  312. }
  313. }
  314. }
  315. }
  316. }
  317. }
  318. .sku-sel-pop {
  319. padding: 30rpx;
  320. padding-top: 50rpx;
  321. position: relative;
  322. .ibonguanbi1 {
  323. color: #999999;
  324. font-size: 26rpx;
  325. position: absolute;
  326. top: 20rpx;
  327. right: 24rpx;
  328. display: inline-block;
  329. width: 50rpx;
  330. }
  331. .goods-view {
  332. .goods-img {
  333. image {
  334. display: block;
  335. width: 200rpx;
  336. height: 200rpx;
  337. border-radius: 10rpx;
  338. }
  339. }
  340. .goods-info {
  341. width: 450rpx;
  342. padding-top: 10rpx;
  343. .goods-stock {
  344. font-size: 24rpx;
  345. color: #999999;
  346. padding: 10rpx 0;
  347. }
  348. .goods-price {
  349. font-size: 24rpx;
  350. }
  351. }
  352. }
  353. .sku-ul {
  354. padding-top: 30rpx;
  355. .sku-li {
  356. padding-bottom: 20rpx;
  357. .sku-name {
  358. line-height: 70rpx;
  359. }
  360. .sku-val-ul {
  361. .sku-val-li {
  362. display: inline-block;
  363. line-height: 60rpx;
  364. min-width: 80rpx;
  365. font-size: 26rpx;
  366. border: 1px solid #eeedf2;
  367. margin-right: 20rpx;
  368. border-radius: 6rpx;
  369. text-align: center;
  370. &:last-child {
  371. margin-right: 0;
  372. }
  373. }
  374. }
  375. }
  376. }
  377. .confirm-btn {
  378. width: 680rpx;
  379. line-height: 70rpx;
  380. text-align: center;
  381. border-radius: 10rpx;
  382. color: #ffffff;
  383. margin: 30rpx auto 0;
  384. }
  385. }
  386. .bottom-view {
  387. background-color: #ffffff;
  388. padding: 20rpx 0;
  389. position: fixed;
  390. left: 0;
  391. bottom: 0;
  392. z-index: 95;
  393. width: 100%;
  394. .price-main {
  395. width: 490rpx;
  396. text-align: right;
  397. .desc {
  398. color: #999999;
  399. font-size: 24rpx;
  400. }
  401. }
  402. .confirm-btn {
  403. height: 74upx;
  404. line-height: 74upx;
  405. color: #ffffff;
  406. background-color: #f63434;
  407. width: 206upx;
  408. text-align: center;
  409. border-radius: 10upx;
  410. margin-right: 20rpx;
  411. }
  412. }
  413. </style>