spec.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. <template>
  2. <view :class="Visible?'product-popup open':'product-popup close'" @touchmove.stop.prevent="" @click="closePopup">
  3. <view class="popup-bg"></view>
  4. <view class="main" v-on:click.stop>
  5. <view class="header">
  6. <image :src="form.show_sku.sku_image" mode="aspectFit" class="avt"></image>
  7. <view class="">{{ selectSpec }}</view>
  8. <view class="close-btn" @click="closePopup">
  9. <text class="icon iconfont icon-guanbi"></text>
  10. </view>
  11. </view>
  12. <view class="body">
  13. <!--规格-->
  14. <view>
  15. <scroll-view scroll-y="true" class="specs mt20" style="max-height: 600rpx;"
  16. v-if="form.specData !=null">
  17. <view class="specs mt20" v-for="(item_attr,attr_index) in form.specData.spec_attr"
  18. :key="attr_index">
  19. <view class="specs-hd p-20-0">
  20. <text class="f24 gray9">{{item_attr.group_name}}</text>
  21. <text class="ml10 red" v-if="form.productSpecArr[attr_index]==null">
  22. 请选择{{item_attr.group_name}}
  23. </text>
  24. </view>
  25. <view class="specs-list">
  26. <button type="primary" :class="item.checked ? 'btn-red' : 'btn-gray-border'"
  27. v-for="(item,item_index) in item_attr.spec_items" :key="item_index"
  28. @click="selectAttr(attr_index, item_index)">{{item.spec_value}}
  29. </button>
  30. </view>
  31. </view>
  32. </scroll-view>
  33. </view>
  34. </view>
  35. <view class="btns">
  36. <button type="primary" class="confirm-btn" @click="closePopup()">选好了</button>
  37. </view>
  38. </view>
  39. </view>
  40. </template>
  41. <script>
  42. export default {
  43. data() {
  44. return {
  45. /*是否可见*/
  46. Visible: false,
  47. /*表单对象*/
  48. form: {
  49. detail: {
  50. },
  51. show_sku: {
  52. sku_image: ''
  53. }
  54. },
  55. /*当前商品总库存*/
  56. stock: 0,
  57. /*选择提示*/
  58. selectSpec: '',
  59. /*是否打开过多规格选择框*/
  60. isOpenSpec: false,
  61. type: ''
  62. }
  63. },
  64. props: ['isPopup', 'productModel'],
  65. onLoad() {
  66. },
  67. mounted() {
  68. },
  69. computed: {
  70. /*判断增加数量*/
  71. isadd: function() {
  72. return this.form.show_sku.sum >= this.stock || this.form.show_sku.sum >= this.form.detail.limit_num;
  73. },
  74. /*判断减少数量*/
  75. issub: function() {
  76. return this.form.show_sku.sum <= 1;
  77. }
  78. },
  79. watch: {
  80. 'isPopup': function(n, o) {
  81. if (n != o) {
  82. this.Visible = n;
  83. this.form = this.productModel;
  84. this.initShowSku();
  85. this.form.type = this.productModel.type;
  86. }
  87. },
  88. 'form.specData': {
  89. handler(n, o) {
  90. let str = '',
  91. select = '';
  92. this.isAll = true;
  93. if (n) {
  94. for (let i = 0; i < n.spec_attr.length; i++) {
  95. if (this.form.productSpecArr[i] == null) {
  96. this.isAll = false;
  97. str += n.spec_attr[i].group_name + ' ';
  98. } else {
  99. n.spec_attr[i].spec_items.forEach(item => {
  100. if (this.form.productSpecArr[i] == item.item_id) {
  101. select += '\"' + item.spec_value + '\" ';
  102. }
  103. });
  104. }
  105. }
  106. if (!this.isAll) {
  107. str = '请选择: ' + str;
  108. } else {
  109. select = '已选: ' + select;
  110. }
  111. }
  112. this.selectSpec = this.isAll ? select : str;
  113. },
  114. deep: true,
  115. immediate: true
  116. }
  117. },
  118. methods: {
  119. /*初始化*/
  120. initShowSku() {
  121. this.form.show_sku.sku_image = this.form.detail.image[0].file_path;
  122. this.form.show_sku.product_price = this.form.detail.product_price;
  123. this.form.show_sku.product_sku_id = 0;
  124. this.form.show_sku.line_price = this.form.detail.line_price;
  125. this.form.show_sku.stock_num = this.form.detail.product_stock;
  126. this.form.show_sku.sum = 1;
  127. this.stock = this.form.detail.product_stock;
  128. },
  129. /*选择属性*/
  130. selectAttr(attr_index, item_index) {
  131. let self = this;
  132. let items = self.form.specData.spec_attr[attr_index].spec_items;
  133. let curItem = items[item_index];
  134. if (curItem.checked) {
  135. // curItem.checked = false;
  136. self.$set(self.form.specData.spec_attr[attr_index].spec_items[item_index],'checked',false);
  137. self.form.productSpecArr[attr_index] = null;
  138. } else {
  139. for (let i = 0; i < items.length; i++) {
  140. self.$set(self.form.specData.spec_attr[attr_index].spec_items[i],'checked',false);
  141. }
  142. self.$set(self.form.specData.spec_attr[attr_index].spec_items[item_index],'checked',true);
  143. self.form.productSpecArr[attr_index] = curItem.item_id;
  144. }
  145. for (let i = 0; i < self.form.productSpecArr.length; i++) {
  146. if (self.form.productSpecArr[i] == null) {
  147. self.initShowSku();
  148. return;
  149. }
  150. }
  151. // 更新商品规格信息
  152. self.updateSpecProduct();
  153. },
  154. /*更新商品规格信息*/
  155. updateSpecProduct() {
  156. let self = this;
  157. let specSkuId = self.form.productSpecArr.join('_');
  158. // 查找skuItem
  159. let spec_list = self.form.specData.spec_list,
  160. skuItem = spec_list.find((val) => {
  161. return val.spec_sku_id == specSkuId;
  162. });
  163. // 记录product_sku_id
  164. // 更新商品价格、划线价、库存
  165. if (typeof skuItem === 'object') {
  166. self.stock = skuItem.spec_form.stock_num;
  167. if (self.form.show_sku.sum > self.stock) {
  168. self.form.show_sku.sum = self.stock > 0 ? self.stock : 1;
  169. }
  170. self.form.show_sku.product_sku_id = specSkuId;
  171. self.form.show_sku.product_price = skuItem.spec_form.product_price;
  172. self.form.show_sku.line_price = skuItem.spec_form.line_price;
  173. self.form.show_sku.stock_num = skuItem.spec_form.stock_num;
  174. if (skuItem.spec_form.image_id > 0) {
  175. self.form.show_sku.sku_image = skuItem.spec_form.image_path;
  176. } else {
  177. self.form.show_sku.sku_image = self.form.detail.image[0].file_path;
  178. }
  179. }
  180. },
  181. /*关闭弹窗*/
  182. closePopup() {
  183. if (this.form.specData != null) {
  184. for (let i = 0; i < this.form.productSpecArr.length; i++) {
  185. if (this.form.productSpecArr[i] == null) {
  186. uni.showToast({
  187. title: '请选择规格',
  188. icon: 'none',
  189. duration: 2000
  190. });
  191. return;
  192. }
  193. }
  194. }
  195. let product_num = this.form.show_sku.sum;
  196. let params = {
  197. product_id: this.form.detail.product_id,
  198. product_sku_id: this.form.show_sku.product_sku_id
  199. }
  200. this.$emit('close', this.form.specData, params);
  201. },
  202. /*商品增加*/
  203. add() {
  204. if (this.stock <= 0) {
  205. return;
  206. }
  207. if (this.form.show_sku.sum >= this.stock) {
  208. uni.showToast({
  209. title: '数量超过了库存',
  210. icon: 'none',
  211. duration: 2000
  212. });
  213. return false;
  214. }
  215. if (this.form.show_sku.sum >= this.form.detail.limit_num) {
  216. uni.showToast({
  217. title: '数量超过了限购数量',
  218. icon: 'none',
  219. duration: 2000
  220. });
  221. return false;
  222. }
  223. this.form.show_sku.sum++;
  224. },
  225. /*商品减少*/
  226. sub() {
  227. if (this.stock <= 0) {
  228. return;
  229. }
  230. if (this.form.show_sku.sum < 2) {
  231. uni.showToast({
  232. title: '商品数量至少为1',
  233. icon: 'none',
  234. duration: 2000
  235. });
  236. return false;
  237. }
  238. this.form.show_sku.sum--;
  239. }
  240. }
  241. }
  242. </script>
  243. <style lang="scss">
  244. .product-popup {}
  245. .product-popup .popup-bg {
  246. position: fixed;
  247. top: 0;
  248. right: 0;
  249. bottom: 0;
  250. left: 0;
  251. background: rgba(0, 0, 0, .6);
  252. z-index: 99;
  253. }
  254. .product-popup .main {
  255. position: fixed;
  256. width: 100%;
  257. min-height: 200rpx;
  258. background-color: #fff;
  259. transform: translate3d(0, 980rpx, 0);
  260. transition: transform .2s cubic-bezier(0, 0, .25, 1);
  261. bottom: env(safe-area-inset-bottom);
  262. }
  263. .product-popup.open .main {
  264. transform: translate3d(0, 0, 0);
  265. z-index: 99;
  266. }
  267. .product-popup.close .popup-bg {
  268. display: none;
  269. }
  270. .product-popup.close .main {
  271. display: none;
  272. z-index: -1;
  273. }
  274. .product-popup .header {
  275. height: 120rpx;
  276. padding: 10rpx 0 10rpx 250rpx;
  277. position: relative;
  278. border-bottom: 1px solid #EEEEEE;
  279. }
  280. .product-popup .header .avt {
  281. position: absolute;
  282. top: -80rpx;
  283. left: 30rpx;
  284. width: 200rpx;
  285. height: 200rpx;
  286. border: 2px solid #FFFFFF;
  287. background: #FFFFFF;
  288. }
  289. .product-popup .header .stock {
  290. font-size: 24rpx;
  291. color: #999999;
  292. }
  293. .product-popup .close-btn {
  294. position: absolute;
  295. width: 40rpx;
  296. height: 40rpx;
  297. top: 10rpx;
  298. right: 10rpx;
  299. }
  300. .product-popup .price {
  301. color: $dominant-color;
  302. font-size: 30rpx;
  303. }
  304. .product-popup .price .num {
  305. padding: 0 4rpx;
  306. font-size: 50rpx;
  307. }
  308. .product-popup .old-price {
  309. margin-left: 10rpx;
  310. font-size: 30rpx;
  311. color: #999999;
  312. text-decoration: line-through;
  313. }
  314. .product-popup .body {
  315. padding: 20rpx 30rpx 100rpx 30rpx;
  316. max-height: 600rpx;
  317. overflow-y: auto;
  318. }
  319. .product-popup .level-box {
  320. display: flex;
  321. justify-content: space-between;
  322. align-items: center;
  323. }
  324. .product-popup .level-box .key {
  325. font-size: 24rpx;
  326. color: #999999;
  327. }
  328. .product-popup .level-box .icon-box {
  329. width: 60rpx;
  330. height: 60rpx;
  331. border: 1px solid #DDDDDD;
  332. background: #f7f7f7;
  333. }
  334. .product-popup .num-wrap .iconfont {
  335. color: #666;
  336. }
  337. .product-popup .num-wrap.no-stock .iconfont {
  338. color: #CCCCCC;
  339. }
  340. .product-popup .level-box .text-wrap {
  341. margin: 0 4rpx;
  342. height: 60rpx;
  343. border: 1px solid #DDDDDD;
  344. background: #f7f7f7;
  345. }
  346. .product-popup .level-box .text-wrap input {
  347. padding: 0 10rpx;
  348. height: 60rpx;
  349. line-height: 60rpx;
  350. width: 80rpx;
  351. text-align: center;
  352. }
  353. .specs .specs-list {
  354. display: flex;
  355. justify-content: flex-start;
  356. align-items: center;
  357. flex-wrap: wrap;
  358. }
  359. .specs .specs-list button {
  360. margin-right: 10rpx;
  361. margin-bottom: 10rpx;
  362. font-size: 24rpx;
  363. }
  364. .specs .specs-list button:after,
  365. .product-popup .btns button,
  366. .product-popup .btns button:after {
  367. height: 88rpx;
  368. line-height: 88rpx;
  369. border: 0;
  370. border-radius: 0;
  371. }
  372. .product-popup .btns .confirm-btn {
  373. margin: 0 auto;
  374. width: 500rpx;
  375. height: 70rpx;
  376. line-height: 70rpx;
  377. border-radius: 35rpx;
  378. background: $dominant-color;
  379. }
  380. </style>