spec.vue 9.3 KB

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