app-attr.vue 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. <template>
  2. <view class="app-attr">
  3. <view @click="alert">
  4. <slot name="button"></slot>
  5. </view>
  6. <view class="modal" v-if="display === 'block'" @click="close" >
  7. <view class="safe-area-inset-bottom u-attr-fixed" >
  8. <view class="content" @click.native.stop="preventD">
  9. <image src="/static/image/icon/close.png" class="close" @click="close"></image>
  10. <view class="first dir-left-nowrap" :class="sign =='wholesale' ? 'no-border' : ''">
  11. <view class="box-grow-0 img" @click.stop="clickImg(attrPic)">
  12. <app-image :img-src="attrPic" width="100%" height="100%"></app-image>
  13. </view>
  14. <view class="info">
  15. <view class="dir-left-nowrap cross-center" :class="priceColor">
  16. <view class="dir-left-nowrap cross-center">
  17. <view class="dir-left-nowrap cross-center" :style="{'color': theme.color}" v-if="(selectAttr && selectAttr.extra) || goods.extra">
  18. <view>{{selectAttr.extra ? selectAttr.extra.value + selectAttr.extra.name :
  19. goods.extra.value + goods.extra.name}}
  20. </view>
  21. <view v-if="!(goods.sign === 'integral_mall' && attrPrice == 0)">+</view>
  22. </view>
  23. <app-price :theme="theme" type="text-price-all" :price="attrPrice" :max="goods.level_show == 1 ? goods.price_member_max : goods.price_max" :min="goods.level_show == 1 ? goods.price_member_min : goods.price_min"></app-price>
  24. </view>
  25. <view v-if="goods.level_show === 1 && selectAttr">
  26. <app-member-mark :theme="theme"></app-member-mark>
  27. </view>
  28. </view>
  29. <view class="stock">库存:{{attrNum}}</view>
  30. </view>
  31. </view>
  32. <view class="secon no-padding">
  33. <slot name="extra"></slot>
  34. <view class="wholesale">
  35. <view class="wholesale-attr-list dir-left-nowrap cross-center" v-if="index != goods.attr_groups.length -1" v-for="(item, index) in goods.attr_groups" :key="index">
  36. <view class="position cross-center">
  37. <view class="wholesale-attr-group t-omit-two">{{item.attr_group_name}}</view>
  38. </view>
  39. <scroll-view @scroll="scrollGet($event,index)" :scroll-left="item.scrollLeft" class="wholesale-attr-item" scroll-x="true">
  40. <view class="scroll-attr-group cross-center">
  41. <view class="wholesale-attr-group t-omit">{{item.attr_group_name.length > 10 ? item.less_attr_group_name : item.attr_group_name}}</view>
  42. </view>
  43. <view class="attr-name attr-background" v-for="(attr, key) in item.attr_list" :key="key"
  44. :style="{'background-color': attr.active ? theme.background : '','color': attr.active ? '#ffffff' : ''}"
  45. @click.stop="chooseAttr(index,attr)">{{attr.attr_name}}
  46. <view class="attr-number" :style="{'right':`${attr.length + 'rpx'}`,'background-color': theme.background}" v-if="index == 0 && attr.number > 0">{{attr.number}}</view>
  47. </view>
  48. <view class="attr-name attr-background" style="visibility: hidden">
  49. </view>
  50. </scroll-view>
  51. <view @click.stop="toBottom(index)" class="right-icon">
  52. <view></view>
  53. <image src="/static/image/icon/right.png"></image>
  54. </view>
  55. </view>
  56. <view class="wholesale-attr-group-list">
  57. <view class="wholesale-attr-group" v-for="(item, index) in goodsAttr" :key="index">
  58. <view class="dir-left-nowrap">
  59. <view class="wholesale-attr-item main-between">
  60. <view class="dir-top-nowrap main-center attr-name t-omit">
  61. <view class="t-omit">{{item.attr_list[item.attr_list.length - 1].attr_name}}</view>
  62. <view class="attr-price">¥{{goods.level_show === 1 ? item.price_member : item.price}}</view>
  63. </view>
  64. <view class="dir-left-nowrap wholesale-number-box cross-center">
  65. <image :src="item.number <= 0 ? '/static/image/plugins/un-low.png' : '/static/image/plugins/low.png'" class="block box-grow-0 cross-center main-center" @click.stop="wholesaleNumberSub(index)">
  66. </image>
  67. <view class="wholesale-number-input box-grow-0 cross-center main-center">
  68. <app-input height="60" type="number" v-model="item.number" defaultValue="0" paddingLeft="0" :center="true" @blur="wholesaleNumberBlur(index)" :focus="false" width="88"></app-input>
  69. </view>
  70. <image :src="item.number >= item.stock? '/static/image/plugins/un-add.png' : '/static/image/plugins/add.png'" class="block box-grow-0 cross-center main-center" @click.stop="wholesaleNumberAdd(index)"></image>
  71. </view>
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. </view>
  77. <view v-if="chooseNumber" class="dir-left-nowrap number-box cross-center">
  78. <view class="box-grow-1">数量</view>
  79. <image :src="number <= 1 ? '/static/image/icon/can-be-reduced.png' : '/static/image/cart/can-be-reduced.png'" class="block box-grow-0 cross-center main-center" @click.stop="numberSub">
  80. </image>
  81. <view class="number-input box-grow-0 cross-center main-center">
  82. <app-input type="number" v-model="number" paddingLeft="0" :center="true" @blur="numberBlur"
  83. :focus="false" width="88"></app-input>
  84. </view>
  85. <image src="/static/image/cart/can-be-added.png" class="block box-grow-0 cross-center main-center" @click.stop="numberAdd"></image>
  86. </view>
  87. </view>
  88. <view v-if="sign ==='wholesale'" class="total">已选<text>{{totalNumber}}</text>件 总计<text>¥{{totalPrice > 0? totalPrice : '0.00'}}</text></view>
  89. <view v-if="goods.sell_time > 0">
  90. <app-sell-tip :time="goods.sell_time"></app-sell-tip>
  91. </view>
  92. <app-jump-button form>
  93. <view class="three dir-left-nowrap">
  94. <view class="bd-btn box-grow-1" v-if="cartShow"
  95. :style="{'background': theme.background_s_gradient_btn,'color': theme.secondary_text}"
  96. @click="cart">{{addText}}
  97. </view>
  98. <view v-if="is_show_buy" class="bd-btn box-grow-1 buy" :style="{'background-color': theme.background,'color': theme.main_text}" @click="buy">
  99. {{buyText}}
  100. </view>
  101. </view>
  102. </app-jump-button>
  103. </view>
  104. </view>
  105. </view>
  106. </view>
  107. </template>
  108. <script>
  109. import { mapState, mapGetters } from "vuex";
  110. import appPrice from "@/components/page-component/goods/app-price.vue";
  111. import appMemberMark from '@/components/page-component/app-member-mark/app-member-mark.vue';
  112. import appSellTip from '@/components/page-component/goods/app-sell-tip.vue';
  113. export default {
  114. name: "app-attr",
  115. components: {
  116. appPrice,
  117. appMemberMark,
  118. appSellTip
  119. },
  120. props: {
  121. goods: Object,
  122. attrGroupList: Array,
  123. attrCart: {
  124. type: Array,
  125. default() {
  126. return [];
  127. }
  128. },
  129. cartShow: {
  130. type: [Boolean, Number],
  131. default() {
  132. return true
  133. }
  134. },
  135. previewUrl: String,
  136. submitUrl: String,
  137. goodsId: {
  138. type:Number,
  139. default() {
  140. return 0
  141. }
  142. },
  143. show: Number,
  144. buyText: {
  145. type: String,
  146. default() {
  147. return '立即购买';
  148. }
  149. },
  150. plugin: {
  151. default: '',
  152. },
  153. theme: {
  154. type: Object,
  155. },
  156. chooseNumber: {
  157. type: Boolean,
  158. default: true,
  159. },
  160. noPay: {
  161. type: Boolean,
  162. default: false,
  163. },
  164. buyClick: {
  165. type: Boolean,
  166. default: false,
  167. },
  168. addText: {
  169. type: String,
  170. default: '加入购物车',
  171. },
  172. is_show_buy: {
  173. type: Boolean,
  174. default: true,
  175. },
  176. sign: {
  177. type: String
  178. },
  179. totalPrice: {
  180. type: String,
  181. default: '0.00',
  182. },
  183. totalNumber: {
  184. type: Number,
  185. default: 0,
  186. },
  187. discount: {
  188. type: Number,
  189. default: 0,
  190. },
  191. wholesaleType: {
  192. type: Number,
  193. default: 0,
  194. },
  195. attentionSign: {
  196. type: String
  197. }
  198. },
  199. data() {
  200. return {
  201. display: 'none',
  202. number: 1,
  203. selectAttr: null,
  204. newAttrGroupList: null,
  205. pic_url: null,
  206. // 商品批发
  207. activeAttr: [],
  208. goodsAttr: [],
  209. };
  210. },
  211. watch: {
  212. show() {
  213. if (this.display === 'block') {
  214. this.selectAttr = null;
  215. this.close();
  216. } else if (this.display === 'none') {
  217. this.alert();
  218. }
  219. },
  220. newData: {
  221. handler() {
  222. this.$emit('attr', this.newData)
  223. },
  224. immediate: true,
  225. },
  226. attrGroupList: {
  227. handler() {
  228. this.newAttrGroupList = this.attrGroupList;
  229. if (this.display == 'block') {
  230. this.alert();
  231. }
  232. },
  233. immediate: true
  234. },
  235. goods: {
  236. handler() {
  237. if (this.display == 'block') {
  238. this.alert();
  239. }
  240. },
  241. immediate: true
  242. }
  243. },
  244. mounted() {
  245. this.pic_url = this.goods.attr_groups[0].attr_list[0].pic_url
  246. if(this.goods.attr_groups.length == 1) {
  247. this.goodsAttr = this.goods.attr;
  248. }else {
  249. for(let item of this.goods.attr_groups) {
  250. let para = {
  251. attr_group_name: '',
  252. attr_group_id: '',
  253. attr_id: '',
  254. attr_name: ''
  255. };
  256. para.attr_group_name = item.attr_group_name
  257. para.attr_group_id = item.attr_group_id
  258. para.attr_id = item.attr_list[0].attr_id
  259. para.attr_name = item.attr_list[0].attr_name
  260. this.activeAttr.push(para)
  261. }
  262. for(let item of this.goods.attr) {
  263. let same = true;
  264. for(let i = 0;i < item.attr_list.length -1;i++) {
  265. let first = {
  266. attr_group_name: item.attr_list[i].attr_group_name,
  267. attr_group_id: item.attr_list[i].attr_group_id,
  268. attr_id: item.attr_list[i].attr_id,
  269. attr_name: item.attr_list[i].attr_name
  270. }
  271. if(JSON.stringify(first) != JSON.stringify(this.activeAttr[i])) {
  272. same = false;
  273. }
  274. }
  275. if(same) {
  276. this.goodsAttr.push(item)
  277. }
  278. }
  279. }
  280. },
  281. methods: {
  282. alert() {
  283. if (this.attrGroupList && this.attrGroupList.length === 0) {
  284. return;
  285. }
  286. this.display = 'block';
  287. },
  288. scrollGet(e,index) {
  289. this.goods.attr_groups[index].scrollLeft = e.detail.scrollLeft;
  290. this.$forceUpdate();
  291. },
  292. toBottom(index) {
  293. this.$nextTick().then(() => {
  294. this.goods.attr_groups[index].scrollLeft = 99999;
  295. this.$forceUpdate();
  296. })
  297. },
  298. chooseAttr(index,attrItem) {
  299. let that = this;
  300. for(let attr of that.goods.attr_groups[index].attr_list) {
  301. attr.active = false;
  302. if(attr.attr_id == attrItem.attr_id && attr.attr_name == attrItem.attr_name) {
  303. attr.active = true;
  304. }
  305. }
  306. if(index == 0) {
  307. that.pic_url = attrItem.pic_url;
  308. }
  309. that.activeAttr[index].attr_id = attrItem.attr_id
  310. that.activeAttr[index].attr_name = attrItem.attr_name
  311. that.goodsAttr = [];
  312. for(let item of that.goods.attr) {
  313. let same = true;
  314. for(let i = 0;i < item.attr_list.length -1;i++) {
  315. let first = {
  316. attr_group_name: item.attr_list[i].attr_group_name,
  317. attr_group_id: item.attr_list[i].attr_group_id,
  318. attr_id: item.attr_list[i].attr_id,
  319. attr_name: item.attr_list[i].attr_name
  320. }
  321. if(JSON.stringify(first) != JSON.stringify(this.activeAttr[i])) {
  322. same = false;
  323. }
  324. }
  325. if(same) {
  326. that.goodsAttr.push(item)
  327. }
  328. }
  329. that.$forceUpdate();
  330. that.count();
  331. },
  332. wholesaleNumberSub(index) {
  333. if(this.goodsAttr[index].number == 0) {
  334. return false;
  335. }
  336. this.goodsAttr[index].number--;
  337. if(this.goods.attr_groups.length == 1) {
  338. this.pic_url = this.goodsAttr[index].pic_url;
  339. }
  340. this.count(index);
  341. },
  342. wholesaleNumberAdd(index) {
  343. if(this.goodsAttr[index].number > this.goodsAttr[index].stock || this.goodsAttr[index].number == this.goodsAttr[index].stock) {
  344. return false
  345. }
  346. this.goodsAttr[index].number++;
  347. if(this.goods.attr_groups.length == 1) {
  348. this.pic_url = this.goodsAttr[index].pic_url;
  349. }
  350. this.count(index);
  351. },
  352. wholesaleNumberBlur(index) {
  353. console.log(this.goodsAttr[index].number,this.goodsAttr[index].stock)
  354. if(+this.goodsAttr[index].number > +this.goodsAttr[index].stock) {
  355. this.goodsAttr[index].number = +this.goodsAttr[index].stock
  356. uni.showToast({
  357. title: '数量不得大于库存',
  358. icon: 'none'
  359. });
  360. }
  361. if(this.goods.attr_groups.length == 1) {
  362. this.pic_url = this.goodsAttr[index].pic_url;
  363. }
  364. this.count(index);
  365. },
  366. count(index) {
  367. let that =this;
  368. this.$emit('attrtap', {goods: that.goods, goodsAttr:that.goodsAttr});
  369. setTimeout(()=>{
  370. that.selectAttr = that.goodsAttr[index];
  371. })
  372. },
  373. close() {
  374. this.display = 'none';
  375. this.$emit('close', false)
  376. },
  377. preventD() {
  378. },
  379. storeAttrClick(attr_id, attr_group_id) {
  380. let attr_group_list = JSON.parse(JSON.stringify(this.newAttrGroupList));
  381. let attrs = this.goods.attr;
  382. let checkedAttr = [];
  383. let attr_cart = this.attrCart;
  384. for (let i in attr_group_list) {
  385. for (let j in attr_group_list[i].attr_list) {
  386. let temp = attr_group_list[i].attr_list[j];
  387. if (parseInt(attr_group_list[i].attr_group_id) == parseInt(attr_group_id)) {
  388. if (parseInt(temp.attr_id) === parseInt(attr_id)) {
  389. if (temp.checked) {
  390. temp.checked = false;
  391. } else {
  392. temp.checked = true;
  393. }
  394. if (temp.attr_num_0) {
  395. return;
  396. }
  397. } else {
  398. temp.checked = false;
  399. }
  400. }
  401. if (temp.checked) {
  402. if (i == 0) {
  403. this.pic_url = attr_group_list[0].attr_list[j].pic_url;
  404. }
  405. checkedAttr.push(attr_group_list[i].attr_group_id + '-' + temp.attr_id);
  406. }
  407. }
  408. }
  409. function inArray(val, arr) {
  410. return arr.some(function (v) {
  411. return val == v;
  412. })
  413. }
  414. let attrNum_0 = [];
  415. let select_attr = null;
  416. let number = 1;
  417. for (let i in attrs) {
  418. let arr = [];
  419. let sign = 0;
  420. for (let j in attrs[i].attr_list) {
  421. let param = attrs[i].attr_list[j].attr_group_id + '-' + attrs[i].attr_list[j].attr_id;
  422. if (!inArray(param, checkedAttr)) {
  423. sign += 1;
  424. arr.push(param);
  425. }
  426. }
  427. if (attrs[i].stock == 0 && sign <= 1) {
  428. attrNum_0 = attrNum_0.concat(arr);
  429. }
  430. if (sign == 0) {
  431. if (!select_attr) {
  432. select_attr = {};
  433. }
  434. select_attr = attrs[i];
  435. attr_cart.forEach(item => {
  436. if (item.attr_id == select_attr.id) {
  437. number = item.num;
  438. }
  439. });
  440. if (select_attr.stock <= 0) {
  441. uni.showToast({
  442. title: '库存不足',
  443. icon: 'none'
  444. });
  445. return;
  446. }
  447. if (select_attr.stock <= number) {
  448. number = select_attr.stock;
  449. }
  450. }
  451. }
  452. if (checkedAttr.length == 0) {
  453. select_attr = null;
  454. }
  455. //库存为0的规格添加标识
  456. for (let i in attr_group_list) {
  457. for (let j in attr_group_list[i].attr_list) {
  458. let cAttr = attr_group_list[i].attr_list[j];
  459. let cParam = attr_group_list[i].attr_group_id + '-' + cAttr.attr_id;
  460. if (inArray(cParam, attrNum_0) && !inArray(cParam, checkedAttr)) {
  461. cAttr.attr_num_0 = true;
  462. } else {
  463. cAttr.attr_num_0 = false;
  464. }
  465. }
  466. }
  467. this.newAttrGroupList = attr_group_list;
  468. this.selectAttr = select_attr;
  469. this.number = number;
  470. this.$emit('attrtap', this.selectAttr);
  471. },
  472. numberBlur(number) {
  473. number = parseInt(number.value);
  474. if (number > this.attrNum) {
  475. uni.showToast({
  476. title: '库存不足',
  477. icon: 'none'
  478. });
  479. number = this.attrNum;
  480. }
  481. this.$emit('attrtap', this.selectAttr);
  482. return this.number = number;
  483. },
  484. numberSub() {
  485. let number = this.number;
  486. if (number <= 1) {
  487. return true;
  488. }
  489. number--;
  490. this.number = number;
  491. this.$emit('attrtap', this.selectAttr);
  492. },
  493. numberAdd() {
  494. let number = this.number;
  495. number++;
  496. if (number > this.attrNum) {
  497. uni.showToast({
  498. title: '库存不足',
  499. icon: 'none'
  500. });
  501. this.number = this.attrNum;
  502. return;
  503. }
  504. this.number = number;
  505. this.$emit('attrtap', this.selectAttr);
  506. },
  507. cart() {
  508. if (!this.submit()) {
  509. return false;
  510. }
  511. let select_attr = this.selectAttr;
  512. if(this.totalNumber < this.goods.wholesaleGoods.rise_num) {
  513. uni.showToast({
  514. title: '至少采购' + this.goods.wholesaleGoods.rise_num + this.goods.unit,
  515. image: '/static/image/plugins/tip.png',
  516. duration: 1000
  517. });
  518. return false
  519. }
  520. let para = [];
  521. for(let item of this.goods.attr) {
  522. if(item.number > 0) {
  523. para.push(item)
  524. }
  525. }
  526. this.$request({
  527. url: this.$api.wholesale.cart,
  528. data: {
  529. attr: JSON.stringify(para)
  530. },
  531. method:'post'
  532. }).then(response => {
  533. this.display = 'none';
  534. if (response.code === 0) {
  535. for(let item of this.goods.attr) {
  536. item.number = '0'
  537. }
  538. for(let item of this.goodsAttr) {
  539. item.number = '0'
  540. }
  541. this.count();
  542. uni.hideLoading();
  543. uni.showToast({
  544. title: '添加成功',
  545. duration: 1000
  546. });
  547. }
  548. }).catch(response => {
  549. this.display = 'none';
  550. })
  551. },
  552. buy() {
  553. // 判断登入
  554. if (!this.$user.isLogin()) {
  555. this.$user.getInfo();
  556. return;
  557. }
  558. if (this.goods.sell_time > 0) {
  559. this.rightTip();
  560. return ;
  561. }
  562. if (!this.submit()) return false;
  563. if (this.noPay) {
  564. this.$emit('pay', this.number);
  565. return;
  566. }
  567. if (this.buyClick) {
  568. this.display = 'none';
  569. this.selectAttr.number = this.number;
  570. this.$emit('buyClick', this.selectAttr);
  571. return false;
  572. }
  573. if(this.totalNumber < this.goods.wholesaleGoods.rise_num) {
  574. this.$tips.showToast({
  575. title: '至少采购' + this.goods.wholesaleGoods.rise_num + this.goods.unit,
  576. icon: 'none'
  577. });
  578. return false
  579. }
  580. let para = {};
  581. let mch_list = [{
  582. mch_id: 0,
  583. goods_list: []
  584. }];
  585. let value = 0;
  586. for(let item of this.goods.attr) {
  587. if(item.number > 0) {
  588. para = {
  589. id: item.goods_id,
  590. attr: [],
  591. num: item.number,
  592. cat_id: 0,
  593. goods_attr_id: item.id
  594. }
  595. for(let attr of item.attr_list) {
  596. let attrList = {
  597. attr_id: attr.attr_id,
  598. attr_group_id: attr.attr_group_id
  599. }
  600. para.attr.push(attrList)
  601. }
  602. mch_list[0].goods_list.push(para)
  603. value += item.number;
  604. }
  605. }
  606. if (typeof this.goods.limit_buy !== 'undefined' && this.goods.limit_buy.status == 1 && this.goods.limit_buy.rest_number < value) {
  607. this.$tips.showToast({
  608. title: this.goods.limit_buy.text,
  609. icon: 'none'
  610. });
  611. return false;
  612. }
  613. let url = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(mch_list)}`;
  614. if (this.submitUrl && this.previewUrl) {
  615. url += `&preview_url=${encodeURIComponent(this.previewUrl)}&submit_url=${encodeURIComponent(this.submitUrl)}&plugin=${this.plugin}`;
  616. }
  617. uni.navigateTo({
  618. url: url
  619. })
  620. },
  621. submit() {
  622. let select_attr = this.selectAttr;
  623. if(this.goods.sign === 'wholesale') {
  624. return true;
  625. }
  626. if (!select_attr) {
  627. uni.showToast({
  628. title: '请先选规格',
  629. icon: 'none'
  630. });
  631. return false;
  632. }
  633. if (select_attr.stock <= 0) {
  634. uni.showToast({
  635. title: '库存不足',
  636. icon: 'none'
  637. });
  638. return false;
  639. }
  640. if (this.number <= 0) {
  641. uni.showToast({
  642. title: '数量不能为0',
  643. icon: 'none'
  644. });
  645. return false;
  646. }
  647. if (!this.goods) {
  648. return false;
  649. }
  650. return true;
  651. },
  652. clickImg(src) {
  653. uni.previewImage({
  654. current: 0,
  655. urls: [src]
  656. });
  657. },
  658. rightTip() {
  659. this.$goodsRemind(this.goods.template_message_list, this.goods.id);
  660. }
  661. },
  662. computed: {
  663. ...mapState({
  664. gConfig: state => state.gConfig,
  665. }),
  666. attrPic() {
  667. if (this.pic_url) {
  668. return this.pic_url;
  669. } else if (this.goods) {
  670. return this.goods.cover_pic;
  671. } else {
  672. return ``;
  673. }
  674. },
  675. priceColor() {
  676. if (this.goods && this.goods.level_show === 1) {
  677. return `member`;
  678. }
  679. },
  680. attrNum() {
  681. if (this.selectAttr) {
  682. return this.selectAttr.stock;
  683. } else if (this.goods) {
  684. return this.goods.goods_num;
  685. } else {
  686. return 0;
  687. }
  688. },
  689. attrPrice() {
  690. if (this.selectAttr) {
  691. let price;
  692. if (this.goods.level_show === 1) {
  693. price = this.selectAttr.price_member
  694. } else {
  695. price = this.selectAttr.price;
  696. }
  697. if(this.selectAttr.number == 0) {
  698. return 'undefined'
  699. }
  700. if(this.wholesaleType == 0) {
  701. price = (price*(this.discount/10)).toFixed(2);
  702. return price
  703. }else {
  704. price = (price - this.discount).toFixed(2);
  705. return price
  706. }
  707. } else {
  708. return 'undefined';
  709. }
  710. },
  711. newData() {
  712. const { number, display, selectAttr } = this;
  713. return {
  714. number,
  715. display,
  716. selectAttr
  717. }
  718. },
  719. ...mapGetters('iPhoneX', {
  720. boolEmpty: 'getBoolEmpty'
  721. }),
  722. ...mapGetters({
  723. userInfo: 'user/info',
  724. })
  725. }
  726. }
  727. </script>
  728. <style scoped lang="scss">
  729. .app-attr {
  730. background-color: #ffffff;
  731. .modal {
  732. background-color: rgba(0, 0, 0, 0.5);
  733. position: fixed;
  734. top: 0;
  735. left: 0;
  736. width: 100%;
  737. height: 100%;
  738. z-index: 1603;
  739. }
  740. .content {
  741. width: 100%;
  742. background-color: #ffffff;
  743. border-radius: #{16rpx} #{16rpx} 0 0;
  744. .close {
  745. width: #{30rpx};
  746. height: #{30rpx};
  747. position: absolute;
  748. right: #{24rpx};
  749. top: #{24rpx};
  750. background-color: #ffffff;
  751. }
  752. .first {
  753. margin: 0 #{24rpx};
  754. border-bottom: #{1rpx} solid #e2e2e2;
  755. &.no-border {
  756. border-bottom: 0;
  757. }
  758. .img {
  759. width: #{200rpx};
  760. height: #{200rpx};
  761. border: #{4rpx} solid #ffffff;
  762. border-radius: #{8rpx};
  763. margin-top: #{-64rpx};
  764. display: block;
  765. }
  766. .info {
  767. margin: #{36rpx} 0 #{26rpx} #{24rpx};
  768. font-size: $uni-font-size-import-two;
  769. line-height: 1;
  770. .stock {
  771. font-size: $uni-font-size-weak-one;
  772. color: $uni-general-color-two;
  773. margin-top: #{18rpx};
  774. }
  775. view {
  776. &:first-child {
  777. margin-right: #{12rpx};
  778. }
  779. }
  780. >.member {
  781. color: #f39800;
  782. }
  783. }
  784. }
  785. .second {
  786. max-height: #{650rpx};
  787. overflow-y: auto;
  788. overflow-x: hidden;
  789. padding: #{4rpx} #{24rpx};
  790. font-size: $uni-font-size-general-two;
  791. &.no-padding {
  792. padding: 0;
  793. }
  794. .attr-group {
  795. padding: #{32rpx} 0;
  796. border-bottom: #{1rpx} solid #e2e2e2;
  797. .attr-group-name {
  798. color: $uni-general-color-one;
  799. margin-bottom: #{20rpx};
  800. }
  801. .attr-item {
  802. margin-right: #{20rpx};
  803. padding: #{15rpx 24rpx};
  804. border-radius: #{8rpx};
  805. margin-bottom: #{20rpx};
  806. &.attr-item-default {
  807. background-color: #f2f2f2;
  808. color: $uni-important-color-black;
  809. }
  810. &.active {
  811. color: #ffffff;
  812. }
  813. &.attr_num_0 {
  814. color: #cdcdcd;
  815. background-color: #f7f7f7;
  816. }
  817. }
  818. }
  819. .number-box {
  820. color: $uni-general-color-one;
  821. height: #{124rpx};
  822. .block {
  823. width: #{60rpx};
  824. height: #{60rpx};
  825. margin: 0 #{4rpx};
  826. &.disabled {
  827. background-color: #fbfbfb;
  828. color: $uni-general-color-two;
  829. }
  830. }
  831. .number-input {
  832. width: #{88rpx};
  833. height: #{60rpx};
  834. color: $uni-important-color-black;
  835. font-size: $uni-font-size-general-one;
  836. background-color: $uni-weak-color-two;
  837. }
  838. }
  839. }
  840. .three {
  841. height: #{110rpx};
  842. width: 100%;
  843. padding: 20upx 24upx;
  844. font-size: $uni-font-size-general-one;
  845. }
  846. }
  847. }
  848. .buy {
  849. color: #ffffff;
  850. margin-left: 20upx;
  851. }
  852. .wholesale {
  853. .wholesale-attr-list {
  854. height: #{88rpx};
  855. margin: 0 #{24rpx};
  856. border-bottom: #{1rpx} solid #e2e2e2;
  857. position: relative;
  858. &:first-of-type {
  859. border-top: #{1rpx} solid #e2e2e2;
  860. }
  861. .position {
  862. position: absolute;
  863. left: 0;
  864. top: #{2rpx};
  865. z-index: 10000;
  866. background-color: #fff;
  867. height: #{83rpx};
  868. }
  869. .wholesale-attr-group {
  870. max-width: #{200rpx};
  871. flex-shrink: 0;
  872. margin-right: #{4rpx};
  873. font-size: #{20rpx};
  874. color: #666666;
  875. background-color: #fff;
  876. }
  877. .right-icon {
  878. position: absolute;
  879. right: #{-24rpx};
  880. top: 0;
  881. height: #{84rpx};
  882. padding-left: #{10rpx};
  883. width: #{50rpx};
  884. z-index: 10000;
  885. background-color: #fff;
  886. view {
  887. height: #{40rpx};
  888. width: #{3rpx};
  889. background-color: #e2e2e2;
  890. position: absolute;
  891. left: 0;
  892. top: #{24rpx};
  893. }
  894. image {
  895. margin-top: #{33rpx};
  896. height: #{22rpx};
  897. width: #{16rpx};
  898. }
  899. }
  900. .wholesale-attr-item {
  901. height: 100%;
  902. width: 100%;
  903. white-space : nowrap;
  904. .scroll-attr-group {
  905. display: inline-block;
  906. visibility: hidden;
  907. .wholesale-attr-group {
  908. height: #{44rpx};
  909. }
  910. }
  911. .attr-name {
  912. color: #fff;
  913. padding: 0 #{22rpx};
  914. height: #{56rpx};
  915. line-height: #{56rpx};
  916. border-radius: #{8rpx};
  917. font-size: #{26rpx};
  918. margin-left: #{20rpx};
  919. display: inline-block;
  920. position: relative;
  921. min-width: #{10rpx};
  922. .attr-number {
  923. color: #fff;
  924. position: absolute;
  925. top: #{-15rpx};
  926. height: #{30rpx};
  927. line-height: #{26rpx};
  928. border: #{2rpx} solid #fff;
  929. padding: 0 #{10rpx};
  930. border-radius: #{15rpx};
  931. font-size: #{20rpx};
  932. z-index: 100;
  933. }
  934. &.attr-background {
  935. background-color: #f2f2f2;
  936. color: #353535;
  937. }
  938. }
  939. }
  940. }
  941. .wholesale-attr-group-list {
  942. margin-top: #{20rpx};
  943. .wholesale-attr-group {
  944. margin-bottom: #{20rpx};
  945. .wholesale-attr-item {
  946. padding: #{20rpx};
  947. background-color: #f7f7f7;
  948. width: 100%;
  949. .attr-name {
  950. width: 60%;
  951. .attr-price {
  952. color: #999999;
  953. font-size: #{24rpx};
  954. }
  955. }
  956. .wholesale-number-box {
  957. color: $uni-general-color-one;
  958. .block {
  959. width: #{60rpx};
  960. height: #{60rpx};
  961. margin: 0 #{4rpx};
  962. &.disabled {
  963. background-color: #fbfbfb;
  964. color: $uni-general-color-two;
  965. }
  966. }
  967. .wholesale-number-input {
  968. width: #{88rpx};
  969. height: #{60rpx};
  970. color: $uni-important-color-black;
  971. font-size: $uni-font-size-general-one;
  972. background-color: #fff;
  973. }
  974. }
  975. }
  976. }
  977. }
  978. }
  979. .total {
  980. width: 100%;
  981. height: #{80rpx};
  982. line-height: #{80rpx};
  983. text-align: right;
  984. padding: 0 24rpx;
  985. color: #353535;
  986. font-size: #{28rpx};
  987. border-top: #{1rpx} solid #e2e2e2;
  988. text {
  989. color: #ff4544;
  990. }
  991. }
  992. .u-attr-fixed {
  993. position: fixed;
  994. bottom: 0;
  995. left: 0;
  996. width: 100%;
  997. background-color: #ffffff;
  998. }
  999. .bd-btn {
  1000. line-height: 70upx;
  1001. text-align: center;
  1002. font-size: 26upx;
  1003. border-radius: 35upx;
  1004. }
  1005. </style>