app-attr.vue 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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" @tap.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="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" :class="theme+'-m-text ' + theme"
  18. v-if="selectAttr.extra || goods.extra">
  19. <view>{{selectAttr.extra ? selectAttr.extra.value + selectAttr.extra.name :
  20. goods.extra.value + goods.extra.name}}
  21. </view>
  22. <view v-if="!(goods.sign === 'integral_mall' && attrPrice == 0)">+</view>
  23. </view>
  24. <app-price :theme="theme"
  25. v-if="!(goods.sign === 'integral_mall' && attrPrice == 0) && sign != 'wholesale'"
  26. type="text-price-all" :price="attrPrice" :default-price="goods.price">
  27. </app-price>
  28. <app-price :theme="theme" v-if="sign == 'wholesale'" type="text-price-all"
  29. :price="attrPrice"
  30. :max="goods.level_show == 1 ? goods.price_member_max : goods.price_max"
  31. :min="goods.level_show == 1 ? goods.price_member_min : goods.price_min">
  32. </app-price>
  33. </view>
  34. <view v-if="goods.level_show === 1 && (selectAttr || sign == 'wholesale')">
  35. <app-member-mark :theme="themeObject"></app-member-mark>
  36. </view>
  37. </view>
  38. <view class="stock">库存:{{attrNum}}</view>
  39. </view>
  40. </view>
  41. <view class="second" :class="sign =='wholesale' ? 'no-padding' : ''">
  42. <slot name="extra"></slot>
  43. <view class="wholesale" v-if="sign =='wholesale'">
  44. <view class="wholesale-attr-list dir-left-nowrap cross-center"
  45. v-if="index != goods.attr_groups.length -1" v-for="(item, index) in goods.attr_groups"
  46. :key="index">
  47. <view class="wholesale-attr-group t-omit-two">{{item.attr_group_name}}</view>
  48. <scroll-view @scroll="scrollGet($event,index)" :scroll-left="item.scrollLeft"
  49. class="wholesale-attr-item" scroll-x="true">
  50. <view class="attr-name" v-for="(attr, key) in item.attr_list" :key="key"
  51. :class="attr.active ? theme + '-m-back ' + theme : 'attr-background'"
  52. @click="chooseAttr(index,attr)">{{attr.attr_name}}
  53. <view class="attr-number" :style="{'right':`${attr.length + 'rpx'}`}"
  54. :class="theme + '-m-back ' + theme" v-if="index == 0 && attr.number > 0">
  55. {{attr.number}}</view>
  56. </view>
  57. <view class="attr-name attr-background" style="visibility: hidden">占位
  58. </view>
  59. </scroll-view>
  60. <view @click.stop="toBottom(index)" class="right-icon">
  61. <view></view>
  62. <image src="/static/image/icon/right.png"></image>
  63. </view>
  64. </view>
  65. <view class="wholesale-attr-group-list">
  66. <view class="wholesale-attr-group" v-for="(item, index) in goodsAttr" :key="index">
  67. <view class="dir-left-nowrap">
  68. <view class="wholesale-attr-item main-between">
  69. <view class="dir-top-nowrap main-center attr-name t-omit">
  70. <view class="t-omit">
  71. {{item.attr_list[item.attr_list.length - 1].attr_name}}</view>
  72. <view class="attr-price">
  73. ¥{{goods.level_show === 1 ? item.price_member : item.price}}</view>
  74. </view>
  75. <view class="dir-left-nowrap wholesale-number-box cross-center">
  76. <image
  77. :src="item.number <= 0 ? '/static/image/plugins/un-low.png' : '/static/image/plugins/low.png'"
  78. class="block box-grow-0 cross-center main-center"
  79. @click="wholesaleNumberSub(index)">
  80. </image>
  81. <view
  82. class="wholesale-number-input box-grow-0 cross-center main-center">
  83. <app-input height="60" type="number" v-model="item.number"
  84. paddingLeft="0" :center="true" placeholder=" "
  85. @blur="wholesaleNumberBlur(index)" :focus="false" width="88">
  86. </app-input>
  87. </view>
  88. <image
  89. :src="item.number >= item.stock? '/static/image/plugins/un-add.png' : '/static/image/plugins/add.png'"
  90. class="block box-grow-0 cross-center main-center"
  91. @click="wholesaleNumberAdd(index)"></image>
  92. </view>
  93. </view>
  94. </view>
  95. </view>
  96. </view>
  97. </view>
  98. <view class="attr-group" v-if="goods.type === 'goods' && sign !='wholesale'"
  99. v-for="(item, index) in newAttrGroupList" :key="index">
  100. <view class="attr-group-name">{{item.attr_group_name}}</view>
  101. <view class="dir-left-wrap">
  102. <view v-for="(attr, key) in item.attr_list" :key="key" class="attr-item"
  103. :class="attr.checked && sign !== 'gift' ? theme + '-m-back active ' + theme : attr.checked && sign === 'gift' ? theme + '-background active' : 'attr-item-default' + (attr.attr_num_0 ? ' attr_num_0' : '')"
  104. @click="storeAttrClick(attr.attr_id, item.attr_group_id)">{{attr.attr_name}}
  105. </view>
  106. </view>
  107. </view>
  108. <view v-if="chooseNumber" class="dir-left-nowrap number-box cross-center">
  109. <view class="box-grow-1">数量</view>
  110. <image
  111. :src="number <= 1 ? '/static/image/icon/can-be-reduced.png' : '/static/image/cart/can-be-reduced.png'"
  112. class="block box-grow-0 cross-center main-center" @click="numberSub">
  113. </image>
  114. <view class="number-input box-grow-0 cross-center main-center">
  115. <app-input type="number" v-model="number" paddingLeft="0" :center="true" placeholder=" "
  116. @blur="numberBlur" :focus="false" width="88"></app-input>
  117. </view>
  118. <image src="/static/image/cart/can-be-added.png"
  119. class="block box-grow-0 cross-center main-center" @click="numberAdd"></image>
  120. </view>
  121. <view class="service"
  122. v-if="service_screen&&service_screen.screenList&&service_screen.screenList.length>0">
  123. <view class="service_title">全优汇服务</view>
  124. <view class="service_item" style="align-items: center;">
  125. <image style="width: 26upx;height:26upx;"
  126. src="https://t12.9026.com/web/statics/icon1/sp.png"> </image>
  127. <view style="flex: 1;">
  128. <view style="float: left;">碎屏险</view>
  129. <view class="slh">{{screenDescription}}</view>
  130. </view>
  131. <view style="color: red;" @click="gotoSpDetail">服务说明
  132. <image style="width: 26upx;height:26upx;"
  133. src="https://t12.9026.com/web/statics/icon1/问号.png"> </image>
  134. </view>
  135. <!-- <view>{{service_screen.screenList.intro}}</view> -->
  136. </view>
  137. <view class="service_value">
  138. <view class="service_block" v-for="(item,index) of service_screen.screenList"
  139. :key="index" :class="{service_block_active:index == serviceId}"
  140. @click="select_service(index)">
  141. {{item.name}} ¥{{item.price}}
  142. </view>
  143. </view>
  144. </view>
  145. </view>
  146. <view v-if="sign =='wholesale'" class="total">已选<text>{{totalNumber}}</text>件
  147. 总计<text>¥{{totalPrice > 0? totalPrice : '0.00'}}</text></view>
  148. <view class="three dir-left-nowrap">
  149. <view class="box-grow-1 main-center cross-center" v-if="cartShow"
  150. :class="sign === 'pick' ? theme + '-m-back ' + 'buy ' + theme : theme === 'b' || theme === 'f' || theme === 'a' ? theme + '-s-back ' + 'buy ' + theme : theme + '-s-back ' + theme+ '-m-text ' + theme"
  151. @click="cart">{{addText}}
  152. </view>
  153. <view v-if="is_show_buy" class="box-grow-1 main-center cross-center buy"
  154. :class="sign !== 'gift' ? theme + '-m-back '+ theme : theme + '-background'" @click="buy">
  155. {{buyText}}
  156. </view>
  157. </view>
  158. </view>
  159. </view>
  160. </view>
  161. </view>
  162. </template>
  163. <script>
  164. import {
  165. mapState,
  166. mapGetters
  167. } from "vuex";
  168. import appPrice from "../../page-component/goods/app-price.vue";
  169. import appImage from "../../basic-component/app-image/app-image.vue";
  170. import appMemberMark from '../../page-component/app-member-mark/app-member-mark.vue';
  171. export default {
  172. name: "app-attr",
  173. components: {
  174. appPrice,
  175. 'app-image': appImage,
  176. appMemberMark
  177. },
  178. props: {
  179. goods: Object,
  180. attrGroupList: Array,
  181. attrCart: {
  182. type: Array,
  183. default () {
  184. return [];
  185. }
  186. },
  187. cartShow: {
  188. type: Boolean,
  189. default () {
  190. return true
  191. }
  192. },
  193. previewUrl: String,
  194. submitUrl: String,
  195. goodsId: {
  196. type: Number,
  197. default () {
  198. return 0
  199. }
  200. },
  201. show: Number,
  202. buyText: {
  203. type: String,
  204. default () {
  205. return '立即购买';
  206. }
  207. },
  208. plugin: {
  209. default: '',
  210. },
  211. theme: {
  212. type: String,
  213. default: 'a',
  214. },
  215. chooseNumber: {
  216. type: Boolean,
  217. default: true,
  218. },
  219. noPay: {
  220. type: Boolean,
  221. default: false,
  222. },
  223. buyClick: {
  224. type: Boolean,
  225. default: false,
  226. },
  227. addText: {
  228. type: String,
  229. default: '加入购物车',
  230. },
  231. is_show_buy: {
  232. type: Boolean,
  233. default: true,
  234. },
  235. sign: {
  236. type: String
  237. },
  238. totalPrice: {
  239. type: String,
  240. default: '0.00',
  241. },
  242. totalNumber: {
  243. type: Number,
  244. default: 0,
  245. },
  246. discount: {
  247. type: Number,
  248. default: 0,
  249. },
  250. wholesaleType: {
  251. type: Number,
  252. default: 0,
  253. }
  254. },
  255. data() {
  256. return {
  257. display: 'none',
  258. number: 1,
  259. selectAttr: null,
  260. newAttrGroupList: null,
  261. pic_url: null,
  262. // 商品批发
  263. activeAttr: [],
  264. goodsAttr: [],
  265. service_screen: null, //碎屏险
  266. service_label: null, //当前对屏对象
  267. serviceId: null, //碎屏险ID
  268. card_id: null,
  269. screenDescription: '',
  270. };
  271. },
  272. watch: {
  273. show() {
  274. if (this.display === 'block') {
  275. this.selectAttr = null;
  276. this.close();
  277. } else if (this.display === 'none') {
  278. this.serviceId = null
  279. this.screenDescription = ""
  280. this.service_label = null
  281. this.card_id = null
  282. this.service_screen = null
  283. this.alert();
  284. }
  285. },
  286. newData: {
  287. handler() {
  288. this.$emit('attr', this.newData)
  289. },
  290. immediate: true,
  291. },
  292. attrGroupList: {
  293. handler() {
  294. this.newAttrGroupList = this.attrGroupList;
  295. if (this.display == 'block') {
  296. this.alert();
  297. }
  298. },
  299. immediate: true
  300. },
  301. goods: {
  302. handler() {
  303. if (this.display == 'block') {
  304. this.alert();
  305. }
  306. },
  307. immediate: true
  308. }
  309. },
  310. mounted() {
  311. if (this.sign == 'wholesale') {
  312. this.pic_url = this.goods.attr_groups[0].attr_list[0].pic_url
  313. if (this.goods.attr_groups.length == 1) {
  314. this.goodsAttr = this.goods.attr;
  315. } else {
  316. for (let item of this.goods.attr_groups) {
  317. let para = {
  318. attr_group_name: '',
  319. attr_group_id: '',
  320. attr_id: '',
  321. attr_name: ''
  322. };
  323. para.attr_group_name = item.attr_group_name
  324. para.attr_group_id = item.attr_group_id
  325. para.attr_id = item.attr_list[0].attr_id
  326. para.attr_name = item.attr_list[0].attr_name
  327. this.activeAttr.push(para)
  328. }
  329. for (let item of this.goods.attr) {
  330. let same = true;
  331. for (let i = 0; i < item.attr_list.length - 1; i++) {
  332. let first = {
  333. attr_group_name: item.attr_list[i].attr_group_name,
  334. attr_group_id: item.attr_list[i].attr_group_id,
  335. attr_id: item.attr_list[i].attr_id,
  336. attr_name: item.attr_list[i].attr_name
  337. }
  338. if (JSON.stringify(first) != JSON.stringify(this.activeAttr[i])) {
  339. same = false;
  340. }
  341. }
  342. if (same) {
  343. this.goodsAttr.push(item)
  344. }
  345. }
  346. }
  347. }
  348. },
  349. methods: {
  350. select_service(index) {
  351. if (this.serviceId == index) {
  352. this.serviceId = null
  353. this.screenDescription = ""
  354. this.service_label = null
  355. this.card_id = null
  356. } else {
  357. this.serviceId = index
  358. this.screenDescription = this.service_screen.screenList[index]['description'] || ''
  359. this.service_label = this.service_screen.screenList[index]
  360. this.card_id = this.service_screen.screenList['card_id']
  361. }
  362. },
  363. alert() {
  364. if (this.attrGroupList.length === 0) {
  365. return;
  366. }
  367. if (this.sign != 'wholesale') {
  368. let attr_group_list = this.attrGroupList;
  369. let attrs = this.goods.attr;
  370. let select_attr = null;
  371. this.number = 1;
  372. if (attr_group_list.length === 1) {
  373. for (let i in attrs) {
  374. for (let j in attr_group_list[0].attr_list) {
  375. if (attr_group_list[0].attr_list[j].attr_id == attrs[i].attr_list[0].attr_id) {
  376. if (attrs[i].stock > 0) {
  377. if (attrs.length === 1) {
  378. attr_group_list[0].attr_list[j].checked = true;
  379. }
  380. attr_group_list[0].attr_list[j].attr_num_0 = false;
  381. this.pic_url = attr_group_list[0].attr_list[j].pic_url;
  382. } else {
  383. this.number = 0;
  384. attr_group_list[0].attr_list[j].checked = false;
  385. attr_group_list[0].attr_list[j].attr_num_0 = true;
  386. }
  387. }
  388. }
  389. }
  390. if (attrs.length === 1) {
  391. select_attr = attrs[0];
  392. this.$emit('attrtap', select_attr);
  393. }
  394. }
  395. this.newAttrGroupList = attr_group_list;
  396. if (this.goods.selectAttr) {
  397. this.selectAttr = this.goods.selectAttr
  398. } else {
  399. this.selectAttr = select_attr;
  400. }
  401. }
  402. // this.getservice()
  403. this.display = 'block';
  404. },
  405. gotoSpDetail() {
  406. uni.navigateTo({
  407. url: "/pages/goods/spDetail"
  408. })
  409. },
  410. getservice(select_val) {
  411. if(select_val.length<=1) return false
  412. this.goods.attr.forEach((item, index) => {
  413. let select_item_list = []
  414. let select_item_value = ''
  415. let attrList = item.attr_list || [];
  416. attrList.forEach((value, key) => {
  417. select_item_value = value.attr_group_id + '-' + value.attr_id
  418. select_item_list.push(select_item_value)
  419. })
  420. if (JSON.stringify(select_val) == JSON.stringify(select_item_list)) {
  421. this.service_screen = item
  422. }
  423. console.log(this.service_screen, "oooooooooooooooo")
  424. })
  425. },
  426. scrollGet(e, index) {
  427. this.goods.attr_groups[index].scrollLeft = e.detail.scrollLeft;
  428. this.$forceUpdate();
  429. },
  430. toBottom(index) {
  431. this.$nextTick().then(() => {
  432. this.goods.attr_groups[index].scrollLeft = 99999;
  433. this.$forceUpdate();
  434. })
  435. },
  436. chooseAttr(index, attrItem) {
  437. let that = this;
  438. for (let attr of that.goods.attr_groups[index].attr_list) {
  439. attr.active = false;
  440. if (attr.attr_id == attrItem.attr_id && attr.attr_name == attrItem.attr_name) {
  441. attr.active = true;
  442. }
  443. }
  444. if (index == 0) {
  445. that.pic_url = attrItem.pic_url;
  446. }
  447. that.activeAttr[index].attr_id = attrItem.attr_id
  448. that.activeAttr[index].attr_name = attrItem.attr_name
  449. that.goodsAttr = [];
  450. for (let item of that.goods.attr) {
  451. let same = true;
  452. for (let i = 0; i < item.attr_list.length - 1; i++) {
  453. let first = {
  454. attr_group_name: item.attr_list[i].attr_group_name,
  455. attr_group_id: item.attr_list[i].attr_group_id,
  456. attr_id: item.attr_list[i].attr_id,
  457. attr_name: item.attr_list[i].attr_name
  458. }
  459. if (JSON.stringify(first) != JSON.stringify(this.activeAttr[i])) {
  460. same = false;
  461. }
  462. }
  463. if (same) {
  464. that.goodsAttr.push(item)
  465. }
  466. }
  467. that.$forceUpdate();
  468. that.count();
  469. },
  470. wholesaleNumberSub(index) {
  471. if (this.goodsAttr[index].number == 0) {
  472. return false;
  473. }
  474. this.goodsAttr[index].number--;
  475. if (this.goods.attr_groups.length == 1) {
  476. this.pic_url = this.goodsAttr[index].pic_url;
  477. }
  478. this.count(index);
  479. },
  480. wholesaleNumberAdd(index) {
  481. if (this.goodsAttr[index].number > this.goodsAttr[index].stock || this.goodsAttr[index].number == this
  482. .goodsAttr[index].stock) {
  483. return false
  484. }
  485. this.goodsAttr[index].number++;
  486. if (this.goods.attr_groups.length == 1) {
  487. this.pic_url = this.goodsAttr[index].pic_url;
  488. }
  489. this.count(index);
  490. },
  491. wholesaleNumberBlur(index) {
  492. if (+this.goodsAttr[index].number > +this.goodsAttr[index].stock) {
  493. this.goodsAttr[index].number = this.goodsAttr[index].stock
  494. }
  495. if (this.goods.attr_groups.length == 1) {
  496. this.pic_url = this.goodsAttr[index].pic_url;
  497. }
  498. this.count(index);
  499. },
  500. count(index) {
  501. let that = this;
  502. this.$emit('attrtap', that.goods, that.goodsAttr);
  503. setTimeout(() => {
  504. that.selectAttr = that.goodsAttr[index]
  505. })
  506. },
  507. close() {
  508. this.display = 'none';
  509. this.$emit('close', false)
  510. },
  511. preventD() {},
  512. storeAttrClick(attr_id, attr_group_id) {
  513. let select_num = []
  514. let attr_group_list = JSON.parse(JSON.stringify(this.newAttrGroupList));
  515. let attrs = this.goods.attr;
  516. let checkedAttr = [];
  517. let attr_cart = this.attrCart;
  518. for (let i in attr_group_list) {
  519. for (let j in attr_group_list[i].attr_list) {
  520. let temp = attr_group_list[i].attr_list[j];
  521. if (parseInt(attr_group_list[i].attr_group_id) == parseInt(attr_group_id)) {
  522. if (parseInt(temp.attr_id) === parseInt(attr_id)) {
  523. if (temp.checked) {
  524. temp.checked = false;
  525. } else {
  526. temp.checked = true;
  527. }
  528. if (temp.attr_num_0) {
  529. return;
  530. }
  531. } else {
  532. temp.checked = false;
  533. }
  534. }
  535. if (temp.checked) {
  536. if (i == 0) {
  537. this.pic_url = attr_group_list[0].attr_list[j].pic_url;
  538. }
  539. checkedAttr.push(attr_group_list[i].attr_group_id + '-' + temp.attr_id);
  540. }
  541. }
  542. }
  543. this.getservice(checkedAttr)
  544. function inArray(val, arr) {
  545. return arr.some(function(v) {
  546. return val == v;
  547. })
  548. }
  549. let attrNum_0 = [];
  550. let select_attr = null;
  551. let number = 1;
  552. for (let i in attrs) {
  553. let arr = [];
  554. let sign = 0;
  555. for (let j in attrs[i].attr_list) {
  556. let param = attrs[i].attr_list[j].attr_group_id + '-' + attrs[i].attr_list[j].attr_id;
  557. if (!inArray(param, checkedAttr)) {
  558. sign += 1;
  559. arr.push(param);
  560. }
  561. }
  562. if (attrs[i].stock == 0 && sign <= 1) {
  563. attrNum_0 = attrNum_0.concat(arr);
  564. }
  565. if (sign == 0) {
  566. if (!select_attr) {
  567. select_attr = {};
  568. }
  569. select_attr = attrs[i];
  570. attr_cart.forEach(item => {
  571. if (item.attr_id == select_attr.id) {
  572. number = item.num;
  573. }
  574. });
  575. if (select_attr.stock <= 0) {
  576. uni.showToast({
  577. title: '库存不足',
  578. icon: 'none'
  579. });
  580. return;
  581. }
  582. if (select_attr.stock <= number) {
  583. number = select_attr.stock;
  584. }
  585. }
  586. }
  587. if (checkedAttr.length == 0) {
  588. select_attr = null;
  589. }
  590. //库存为0的规格添加标识
  591. for (let i in attr_group_list) {
  592. for (let j in attr_group_list[i].attr_list) {
  593. let cAttr = attr_group_list[i].attr_list[j];
  594. let cParam = attr_group_list[i].attr_group_id + '-' + cAttr.attr_id;
  595. if (inArray(cParam, attrNum_0) && !inArray(cParam, checkedAttr)) {
  596. cAttr.attr_num_0 = true;
  597. } else {
  598. cAttr.attr_num_0 = false;
  599. }
  600. }
  601. }
  602. this.newAttrGroupList = attr_group_list;
  603. this.selectAttr = select_attr;
  604. this.number = number;
  605. this.$emit('attrtap', this.selectAttr);
  606. },
  607. numberBlur(number) {
  608. number = parseInt(number.value);
  609. if (number > this.attrNum) {
  610. uni.showToast({
  611. title: '库存不足',
  612. icon: 'none'
  613. });
  614. number = this.attrNum;
  615. }
  616. this.$emit('attrtap', this.selectAttr);
  617. return this.number = number;
  618. },
  619. numberSub() {
  620. let number = this.number;
  621. if (number <= 1) {
  622. return true;
  623. }
  624. number--;
  625. this.number = number;
  626. this.$emit('attrtap', this.selectAttr);
  627. },
  628. numberAdd() {
  629. let number = this.number;
  630. number++;
  631. if (number > this.attrNum) {
  632. uni.showToast({
  633. title: '库存不足',
  634. icon: 'none'
  635. });
  636. this.number = this.attrNum;
  637. return;
  638. }
  639. this.number = number;
  640. this.$emit('attrtap', this.selectAttr);
  641. },
  642. cart() {
  643. if (!this.submit()) {
  644. return false;
  645. }
  646. let select_attr = this.selectAttr;
  647. if (this.goods.sign === 'pick' || this.goods.sign === 'community') {
  648. this.$emit('add', select_attr, this.number);
  649. return;
  650. }
  651. // 普通商品
  652. if (this.goods.type === 'goods') {
  653. if (this.goods.sign === 'miaosha') {
  654. this.$request({
  655. url: this.$api.miaosha.add_cart,
  656. data: {
  657. miaosha_goods_id: select_attr.goods_id,
  658. attr_id: select_attr.id,
  659. num: this.number
  660. },
  661. method: 'post'
  662. }).then(e => {
  663. uni.showToast({
  664. title: e.msg,
  665. type: 'success'
  666. });
  667. this.display = 'none';
  668. this.selectAttr.number = this.number;
  669. this.$emit('selectNumber', this.selectAttr);
  670. }).catch(() => {
  671. this.display = 'none';
  672. });
  673. } else if (this.goods.sign === 'flash_sale') {
  674. this.$request({
  675. url: this.$api.flash_sale.add_cart,
  676. data: {
  677. flash_goods_id: select_attr.goods_id,
  678. attr_id: select_attr.id,
  679. num: this.number
  680. },
  681. method: 'post'
  682. }).then(e => {
  683. uni.showToast({
  684. title: e.msg,
  685. type: 'success'
  686. });
  687. this.display = 'none';
  688. this.selectAttr.number = this.number;
  689. this.$emit('selectNumber', this.selectAttr);
  690. }).catch(() => {
  691. this.display = 'none';
  692. });
  693. } else if (this.goods.sign == 'wholesale') {
  694. if (this.totalNumber < this.goods.wholesaleGoods.rise_num) {
  695. uni.showToast({
  696. title: '至少采购' + this.goods.wholesaleGoods.rise_num + this.goods.unit,
  697. image: '/static/image/plugins/tip.png',
  698. duration: 1000
  699. });
  700. return false
  701. }
  702. let para = [];
  703. for (let item of this.goods.attr) {
  704. if (item.number > 0) {
  705. para.push(item)
  706. }
  707. }
  708. this.$request({
  709. url: this.$api.wholesale.cart,
  710. data: {
  711. attr: JSON.stringify(para)
  712. },
  713. method: 'post'
  714. }).then(response => {
  715. this.display = 'none';
  716. if (response.code === 0) {
  717. for (let item of this.goods.attr) {
  718. item.number = '0'
  719. }
  720. for (let item of this.goodsAttr) {
  721. item.number = '0'
  722. }
  723. this.count();
  724. uni.hideLoading();
  725. uni.showToast({
  726. title: '添加成功',
  727. duration: 1000
  728. });
  729. }
  730. }).catch(response => {
  731. this.display = 'none';
  732. })
  733. } else {
  734. this.$request({
  735. url: this.$api.cart.add,
  736. data: {
  737. goods_id: select_attr.goods_id,
  738. attr: select_attr.id,
  739. num: this.number
  740. },
  741. method: 'post'
  742. }).then(e => {
  743. if (e.code === 0) {
  744. uni.showToast({
  745. title: e.msg,
  746. type: 'success'
  747. });
  748. this.display = 'none';
  749. this.selectAttr.number = this.number;
  750. this.$emit('selectNumber', this.selectAttr);
  751. } else {
  752. uni.showToast({
  753. title: e.msg,
  754. icon: "none",
  755. duration: 2500
  756. });
  757. this.display = 'none';
  758. }
  759. }).catch(() => {
  760. this.display = 'none';
  761. });
  762. }
  763. // 虚拟商品
  764. } else if (this.goods.type === 'ecard') {
  765. uni.showToast({
  766. title: '虚拟商品不允许加入购物车',
  767. icon: 'none'
  768. });
  769. }
  770. },
  771. buy() {
  772. if (this.$user.isLogin() && this.$store.state.user.info) {
  773. let member_level = this.$store.state.user.info.identity.member_level;
  774. if (member_level < this.goods.member_level) {
  775. uni.showModal({
  776. title: "提示",
  777. content: "需达到" + this.goods.member_name + "会员才可购买",
  778. showCancel: true,
  779. buttonText: '升级',
  780. success: (res) => {
  781. if (res.confirm) {
  782. uni.navigateTo({
  783. // url:"/pages/member/index/index",
  784. url: '/pages/member/upgrade/upgrade?level=' + member_level +
  785. '&other=' + this.goods.member_level
  786. })
  787. } else if (res.cancel) {
  788. console.log('用户点击取消');
  789. }
  790. }
  791. })
  792. return;
  793. }
  794. }
  795. if (!this.submit()) return false;
  796. if (this.noPay) {
  797. this.$emit('pay', this.number);
  798. return;
  799. }
  800. if (this.buyClick) {
  801. this.display = 'none';
  802. this.selectAttr.number = this.number;
  803. this.selectAttr.service_label = this.service_label
  804. this.$emit('buyClick', this.selectAttr);
  805. return false;
  806. }
  807. if (this.goods.sign == 'wholesale') {
  808. if (this.totalNumber < this.goods.wholesaleGoods.rise_num) {
  809. uni.showToast({
  810. title: '至少采购' + this.goods.wholesaleGoods.rise_num + this.goods.unit,
  811. image: '/static/image/plugins/tip.png',
  812. duration: 1000
  813. });
  814. return false
  815. }
  816. let para = {};
  817. let mch_list = [{
  818. mch_id: 0,
  819. goods_list: []
  820. }];
  821. for (let item of this.goods.attr) {
  822. if (item.number > 0) {
  823. para = {
  824. id: item.goods_id,
  825. attr: [],
  826. num: item.number,
  827. cat_id: 0,
  828. goods_attr_id: item.id
  829. }
  830. for (let attr of item.attr_list) {
  831. let attrList = {
  832. attr_id: attr.attr_id,
  833. attr_group_id: attr.attr_group_id
  834. }
  835. para.attr.push(attrList)
  836. }
  837. mch_list[0].goods_list.push(para)
  838. }
  839. }
  840. let url = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(mch_list)}`;
  841. if (this.submitUrl && this.previewUrl) {
  842. url +=
  843. `&preview_url=${encodeURIComponent(this.previewUrl)}&submit_url=${encodeURIComponent(this.submitUrl)}&plugin=${this.plugin}`;
  844. }
  845. uni.navigateTo({
  846. url: url
  847. })
  848. } else {
  849. let goods = this.goods;
  850. let number = this.number;
  851. let select_attr = this.selectAttr;
  852. let goods_attr_id = select_attr.id;
  853. let attr = [];
  854. for (let i in select_attr.attr_list) {
  855. attr.push({
  856. attr_id: select_attr.attr_list[i].attr_id,
  857. attr_group_id: select_attr.attr_list[i].attr_group_id
  858. });
  859. }
  860. let mch_list = [{
  861. mch_id: goods.mch_id ? goods.mch_id : 0,
  862. goods_list: [{
  863. id: this.goodsId ? this.goodsId : goods.id,
  864. attr: attr,
  865. num: number,
  866. cat_id: 0,
  867. goods_attr_id: goods_attr_id
  868. }]
  869. }];
  870. let url = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(mch_list)}`;
  871. if (this.submitUrl && this.previewUrl) {
  872. url +=
  873. `&preview_url=${encodeURIComponent(this.previewUrl)}&submit_url=${encodeURIComponent(this.submitUrl)}&plugin=${this.plugin}`;
  874. }
  875. uni.navigateTo({
  876. url: url
  877. })
  878. }
  879. },
  880. submit() {
  881. let select_attr = this.selectAttr;
  882. if (this.goods.sign === 'wholesale') {
  883. return true;
  884. }
  885. if (!select_attr) {
  886. uni.showToast({
  887. title: '请先选规格',
  888. icon: 'none'
  889. });
  890. return false;
  891. }
  892. if (select_attr.stock <= 0) {
  893. uni.showToast({
  894. title: '库存不足',
  895. icon: 'none'
  896. });
  897. return false;
  898. }
  899. if (this.number <= 0) {
  900. uni.showToast({
  901. title: '数量不能为0',
  902. icon: 'none'
  903. });
  904. return false;
  905. }
  906. if (!this.goods) {
  907. return false;
  908. }
  909. return true;
  910. },
  911. clickImg(src) {
  912. uni.previewImage({
  913. current: 0,
  914. urls: [src]
  915. });
  916. },
  917. },
  918. computed: {
  919. ...mapState({
  920. gConfig: state => state.gConfig,
  921. }),
  922. attrPic() {
  923. if (this.pic_url) {
  924. return this.pic_url;
  925. } else if (this.goods) {
  926. return this.goods.cover_pic;
  927. } else {
  928. return ``;
  929. }
  930. },
  931. priceColor() {
  932. if (this.goods && this.goods.level_show === 1) {
  933. return `member`;
  934. } else {
  935. return this.theme + '-color';
  936. }
  937. },
  938. attrNum() {
  939. if (this.selectAttr) {
  940. return this.selectAttr.stock;
  941. } else if (this.goods) {
  942. return this.goods.goods_num;
  943. } else {
  944. return 0;
  945. }
  946. },
  947. attrPrice() {
  948. if (this.selectAttr) {
  949. let price;
  950. if (this.goods.level_show === 1) {
  951. price = this.selectAttr.price_member
  952. } else {
  953. price = this.selectAttr.price;
  954. }
  955. if (this.sign == 'wholesale') {
  956. if (this.selectAttr.number == 0) {
  957. return 'undefined'
  958. }
  959. if (this.wholesaleType == 0) {
  960. price = (price * (this.discount / 10)).toFixed(2);
  961. return price
  962. } else {
  963. price = (price - this.discount).toFixed(2);
  964. return price
  965. }
  966. } else {
  967. return price
  968. }
  969. } else if (this.sign == 'wholesale') {
  970. return 'undefined';
  971. } else if (this.goods) {
  972. if (this.goods.hasOwnProperty('price_min')) {
  973. return this.goods.price_min;
  974. } else {
  975. return this.goods.price;
  976. }
  977. } else {
  978. return 0;
  979. }
  980. },
  981. newData() {
  982. const {
  983. number,
  984. display,
  985. selectAttr
  986. } = this;
  987. return {
  988. number,
  989. display,
  990. selectAttr
  991. }
  992. },
  993. themeObject: function() {
  994. return {
  995. back: this.theme + '-m-back ' + this.theme,
  996. theme: this.theme,
  997. color: this.theme + '-m-text ' + this.theme,
  998. sBack: this.theme + '-s-back ' + this.theme
  999. }
  1000. },
  1001. ...mapGetters('iPhoneX', {
  1002. boolEmpty: 'getBoolEmpty'
  1003. })
  1004. }
  1005. }
  1006. </script>
  1007. <style scoped lang="scss">
  1008. .app-attr {
  1009. background-color: #ffffff;
  1010. .modal {
  1011. background-color: rgba(0, 0, 0, 0.5);
  1012. position: fixed;
  1013. top: 0;
  1014. left: 0;
  1015. width: 100%;
  1016. height: 100%;
  1017. z-index: 1603;
  1018. }
  1019. .content {
  1020. width: 100%;
  1021. background-color: #ffffff;
  1022. border-radius: #{16rpx} #{16rpx} 0 0;
  1023. .close {
  1024. width: #{30rpx};
  1025. height: #{30rpx};
  1026. position: absolute;
  1027. right: #{24rpx};
  1028. top: #{24rpx};
  1029. background-color: #ffffff;
  1030. }
  1031. .first {
  1032. margin: 0 #{24rpx};
  1033. border-bottom: #{1rpx} solid #e2e2e2;
  1034. &.no-border {
  1035. border-bottom: 0;
  1036. }
  1037. .img {
  1038. width: #{200rpx};
  1039. height: #{200rpx};
  1040. border: #{4rpx} solid #ffffff;
  1041. border-radius: #{8rpx};
  1042. margin-top: #{-64rpx};
  1043. display: block;
  1044. }
  1045. .info {
  1046. margin: #{36rpx} 0 #{26rpx} #{24rpx};
  1047. font-size: $uni-font-size-import-two;
  1048. line-height: 1;
  1049. .stock {
  1050. font-size: $uni-font-size-weak-one;
  1051. color: $uni-general-color-two;
  1052. margin-top: #{18rpx};
  1053. }
  1054. view {
  1055. &:first-child {
  1056. margin-right: #{12rpx};
  1057. }
  1058. }
  1059. .member {
  1060. color: #f39800;
  1061. }
  1062. }
  1063. }
  1064. .second {
  1065. max-height: #{650rpx};
  1066. overflow-y: auto;
  1067. overflow-x: hidden;
  1068. padding: #{4rpx} #{24rpx};
  1069. font-size: $uni-font-size-general-two;
  1070. &.no-padding {
  1071. padding: 0;
  1072. }
  1073. .attr-group {
  1074. padding: #{32rpx} 0;
  1075. border-bottom: #{1rpx} solid #e2e2e2;
  1076. .attr-group-name {
  1077. color: $uni-general-color-one;
  1078. margin-bottom: #{20rpx};
  1079. }
  1080. .attr-item {
  1081. margin-right: #{20rpx};
  1082. padding: #{15rpx 24rpx};
  1083. border-radius: #{8rpx};
  1084. margin-bottom: #{20rpx};
  1085. &.attr-item-default {
  1086. background-color: #f2f2f2;
  1087. color: $uni-important-color-black;
  1088. }
  1089. &.active {
  1090. color: #ffffff;
  1091. }
  1092. &.attr_num_0 {
  1093. color: #cdcdcd;
  1094. background-color: #f7f7f7;
  1095. }
  1096. }
  1097. }
  1098. .number-box {
  1099. color: $uni-general-color-one;
  1100. height: #{124rpx};
  1101. .block {
  1102. width: #{60rpx};
  1103. height: #{60rpx};
  1104. margin: 0 #{4rpx};
  1105. &.disabled {
  1106. background-color: #fbfbfb;
  1107. color: $uni-general-color-two;
  1108. }
  1109. }
  1110. .number-input {
  1111. width: #{88rpx};
  1112. height: #{60rpx};
  1113. color: $uni-important-color-black;
  1114. font-size: $uni-font-size-general-one;
  1115. background-color: $uni-weak-color-two;
  1116. }
  1117. }
  1118. }
  1119. .three {
  1120. height: #{110rpx};
  1121. width: 100%;
  1122. font-size: $uni-font-size-general-one;
  1123. }
  1124. }
  1125. }
  1126. .buy {
  1127. color: #ffffff;
  1128. }
  1129. .wholesale {
  1130. .wholesale-attr-list {
  1131. height: 88rpx;
  1132. margin: 0 24rpx;
  1133. border-bottom: 1rpx solid #e2e2e2;
  1134. position: relative;
  1135. &:first-of-type {
  1136. border-top: 1rpx solid #e2e2e2;
  1137. }
  1138. .wholesale-attr-group {
  1139. max-width: 200rpx;
  1140. flex-shrink: 0;
  1141. margin-right: 4rpx;
  1142. font-size: 20rpx;
  1143. color: #666666;
  1144. }
  1145. .right-icon {
  1146. position: absolute;
  1147. right: -24rpx;
  1148. top: 0;
  1149. height: 84rpx;
  1150. padding-left: 10rpx;
  1151. width: 50rpx;
  1152. z-index: 10000;
  1153. background-color: #fff;
  1154. view {
  1155. height: 40rpx;
  1156. width: 3rpx;
  1157. background-color: #e2e2e2;
  1158. position: absolute;
  1159. left: 0;
  1160. top: 24rpx;
  1161. }
  1162. image {
  1163. margin-top: 33rpx;
  1164. height: 22rpx;
  1165. width: 16rpx;
  1166. }
  1167. }
  1168. .wholesale-attr-item {
  1169. height: 100%;
  1170. white-space: nowrap;
  1171. .attr-name {
  1172. margin-top: 16rpx;
  1173. color: #fff;
  1174. padding: 0 22rpx;
  1175. height: 56rpx;
  1176. line-height: 56rpx;
  1177. border-radius: 8rpx;
  1178. font-size: 26rpx;
  1179. margin-left: 20rpx;
  1180. display: inline-block;
  1181. position: relative;
  1182. .attr-number {
  1183. color: #fff;
  1184. position: absolute;
  1185. top: -15rpx;
  1186. height: 30rpx;
  1187. line-height: 26rpx;
  1188. border: 2rpx solid #fff;
  1189. padding: 0 10rpx;
  1190. border-radius: 15rpx;
  1191. font-size: 20rpx;
  1192. z-index: 100;
  1193. }
  1194. &.attr-background {
  1195. background-color: #f2f2f2;
  1196. color: #353535;
  1197. }
  1198. }
  1199. }
  1200. }
  1201. .wholesale-attr-group-list {
  1202. margin-top: 20rpx;
  1203. .wholesale-attr-group {
  1204. margin-bottom: 20rpx;
  1205. .wholesale-attr-item {
  1206. padding: 20rpx;
  1207. background-color: #f7f7f7;
  1208. width: 100%;
  1209. .attr-name {
  1210. width: 60%;
  1211. .attr-price {
  1212. color: #999999;
  1213. font-size: 24rpx;
  1214. }
  1215. }
  1216. .wholesale-number-box {
  1217. color: $uni-general-color-one;
  1218. .block {
  1219. width: #{60rpx};
  1220. height: #{60rpx};
  1221. margin: 0 #{4rpx};
  1222. &.disabled {
  1223. background-color: #fbfbfb;
  1224. color: $uni-general-color-two;
  1225. }
  1226. }
  1227. .wholesale-number-input {
  1228. width: #{88rpx};
  1229. height: #{60rpx};
  1230. color: $uni-important-color-black;
  1231. font-size: $uni-font-size-general-one;
  1232. background-color: #fff;
  1233. }
  1234. }
  1235. }
  1236. }
  1237. }
  1238. }
  1239. .total {
  1240. width: 100%;
  1241. height: 80rpx;
  1242. line-height: 80rpx;
  1243. text-align: right;
  1244. padding: 0 24rpx;
  1245. color: #353535;
  1246. font-size: 28rpx;
  1247. border-top: 1rpx solid #e2e2e2;
  1248. text {
  1249. color: #ff4544;
  1250. }
  1251. }
  1252. .u-attr-fixed {
  1253. position: fixed;
  1254. bottom: 0;
  1255. left: 0;
  1256. width: 100%;
  1257. background-color: #ffffff;
  1258. }
  1259. .service{
  1260. margin-bottom: 20rpx;
  1261. }
  1262. .service_title {
  1263. padding-top: 10px;
  1264. margin: 14px 10px 10px;
  1265. font-weight: 700;
  1266. font-size: 13px;
  1267. }
  1268. .service_item {
  1269. margin: 14px 0px 0px;
  1270. font-size: 26rpx;
  1271. color: #666;
  1272. display: flex;
  1273. justify-content: space-between;
  1274. }
  1275. .service_value {
  1276. display: flex;
  1277. flex-wrap: wrap;
  1278. padding: 0px 10px;
  1279. }
  1280. .service_block {
  1281. min-width: 46%;
  1282. height: 28px;
  1283. line-height: 26px;
  1284. border: 1px solid #f5f5f5;
  1285. border-radius: 16px;
  1286. text-align: center;
  1287. margin-right: 10px;
  1288. margin-top: 10px;
  1289. font-size: 12px;
  1290. background-color: #f5f5f5;
  1291. position: relative;
  1292. }
  1293. .service_block_active {
  1294. color: #f21c1c;
  1295. border: 1px solid #f21c1c;
  1296. }
  1297. .slh {
  1298. margin-left: 5upx;
  1299. overflow: hidden;
  1300. text-overflow: ellipsis;
  1301. width: 460upx;
  1302. white-space: nowrap;
  1303. float: left;
  1304. /* display: -webkit-box;
  1305. -webkit-line-clamp: 1;
  1306. -webkit-box-orient: vertical; */
  1307. }
  1308. </style>