index.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. <template>
  2. <view>
  3. <view class='shoppingCart copy-data' v-if="showCartList">
  4. <!-- <view class='labelNav acea-row row-around'>
  5. <view class='item'><text class='iconfont icon-xuanzhong'></text>100%正品保证</view>
  6. <view class='item'><text class='iconfont icon-xuanzhong'></text>所有商品精挑细选</view>
  7. <view class='item'><text class='iconfont icon-xuanzhong'></text>售后无忧</view>
  8. </view>
  9. -->
  10. <view class="borRadius14 cartBox">
  11. <view
  12. v-if="(cartList.valid.length === 0 && cartList.invalid.length === 0) || (cartList.valid.length > 0)"
  13. class='nav acea-row row-between-wrapper'>
  14. <view>购物数量 <text class='num font-color'>{{cartCount}}</text></view>
  15. <view v-if="cartList.valid.length > 0 || cartList.invalid.length > 0"
  16. class='administrate acea-row row-center-wrapper' @click='manage'>{{ footerswitch ? '管理' : '取消'}}
  17. </view>
  18. </view>
  19. <view v-if="cartList.valid.length > 0 || cartList.invalid.length > 0" class="pad30">
  20. <!-- 有效的购物车 -->
  21. <view class='list'>
  22. <checkbox-group @change="checkboxChange">
  23. <block v-for="(item,index) in cartList.valid" :key="index">
  24. <view class='item acea-row row-between-wrapper'>
  25. <!-- #ifndef MP -->
  26. <checkbox :value="item.id.toString()" :checked="item.selected"
  27. :disabled="!item.canChecked && footerswitch" style="margin-right: 10rpx;" />
  28. <!-- #endif -->
  29. <!-- #ifdef MP -->
  30. <checkbox :value="item.id.toString()" :checked="item.selected"
  31. :disabled="!item.canChecked && footerswitch" />
  32. <!-- #endif -->
  33. <navigator :url='"/pages/goods_details/index?id=" + item.spu.id' hover-class='none'
  34. class='picTxt acea-row row-between-wrapper'>
  35. <view class='pictrue'>
  36. <image v-if="item.sku" :src='item.sku.picUrl' />
  37. <image v-else :src='item.spu.picUrl' />
  38. </view>
  39. <view class='text'>
  40. <view class='line1' :class="item.canChecked?'':'reColor'">
  41. {{ item.spu.name }}
  42. </view>
  43. <view class='infor line1' v-if="item.sku">属性:
  44. <text v-for="property in item.sku.properties"
  45. style="padding-left: 2px">{{property.valueName}}</text>
  46. </view>
  47. <view class='money' v-if="item.canChecked">¥{{ fen2yuan(item.sku.price) }}
  48. </view>
  49. <view class="reElection acea-row row-between-wrapper" v-else>
  50. <view class="title">请重新选择商品规格</view>
  51. <view class="reBnt cart-color acea-row row-center-wrapper"
  52. @click.stop="reElection(item)">重选</view>
  53. </view>
  54. </view>
  55. <view class='carnum acea-row row-center-wrapper' v-if="item.canChecked">
  56. <view class="reduce" :class="item.numSub ? 'on' : ''"
  57. @click.stop='subCart(index)'>-</view>
  58. <view class='num'>{{ item.count }}</view>
  59. <view class="plus" :class="item.numAdd ? 'on' : ''"
  60. @click.stop='addCart(index)'>+</view>
  61. </view>
  62. </navigator>
  63. </view>
  64. </block>
  65. </checkbox-group>
  66. </view>
  67. <!-- 无效的购物车 -->
  68. <view v-if="cartList.invalid.length > 0" class='invalidGoods borRadius14' :style="cartList.valid.length === 0 && cartList.invalid.length > 0
  69. ? 'position: relative;z-index: 111;top: -120rpx;'
  70. :'position: static;'">
  71. <view class='goodsNav acea-row row-between-wrapper'>
  72. <view v-if="cartList.invalid.length > 1 || cartList.valid.length > 0" @click='goodsOpen'>
  73. <text class='iconfont' :class='goodsHidden ? "icon-xiangxia":"icon-xiangshang"' /> 失效商品
  74. </view>
  75. <view v-else>失效商品</view>
  76. <view class='del' @click='unsetCart'>
  77. <text class='iconfont icon-shanchu1' />清空
  78. </view>
  79. </view>
  80. <view class='goodsList' :hidden='goodsHidden'>
  81. <block v-for="(item,index) in cartList.invalid" :key='index'>
  82. <view class='item acea-row row-between-wrapper'>
  83. <view class='invalid'>失效</view>
  84. <view class='picTxt acea-row row-between-wrapper'>
  85. <view class='pictrue'>
  86. <image v-if="item.sku" :src='item.sku.picUrl' />
  87. <image v-else :src='item.spu.picUrl' />
  88. </view>
  89. <view class='text acea-row row-column-between'>
  90. <view class='line1 name'>{{ item.spu.name }}</view>
  91. <view class='infor line1' v-if="item.sku.properties">属性:
  92. <text v-for="property in item.sku.properties"
  93. style="padding-left: 2px">{{property.valueName}}</text>
  94. </view>
  95. <view class='acea-row row-between-wrapper'>
  96. <view class='end'>该商品已失效</view>
  97. </view>
  98. </view>
  99. </view>
  100. </view>
  101. </block>
  102. </view>
  103. </view>
  104. </view>
  105. <!-- 热门推荐 -->
  106. <!-- <view class='noCart' v-if="cartList.valid.length === 0 && cartList.invalid.length === 0 && canShow">
  107. <view class='pictrue'>
  108. <image src='../../static/images/noCart.png' />
  109. </view>
  110. <recommend :hostProduct='hostProduct'></recommend>
  111. </view> -->
  112. </view>
  113. </view>
  114. <!-- 管理操作 -->
  115. <view class='footer acea-row row-between-wrapper' @click="aaa">
  116. <view>
  117. <checkbox-group @change="checkboxAllChange">
  118. <checkbox value="all" :checked="!!isAllSelect" />
  119. <text class='checkAll'>全选({{selectValue.length}})</text>
  120. </checkbox-group>
  121. </view>
  122. <view class='money acea-row row-middle' v-if="footerswitch">
  123. <text class='font-color'>¥{{ fen2yuan(selectCountPrice) }}</text>
  124. <form @submit="subOrder" report-submit='true'>
  125. <button class='placeOrder bg-color' formType="submit">立即下单</button>
  126. </form>
  127. </view>
  128. <view class='button acea-row row-middle' v-else>
  129. <form @submit="subCollect" report-submit='true'>
  130. <button class='bnt cart-color' formType="submit">收藏</button>
  131. </form>
  132. <form @submit="subDel" report-submit='true'>
  133. <button class='bnt' formType="submit">删除</button>
  134. </form>
  135. </view>
  136. </view>
  137. <!-- SKU 不可用的商品,重新选择 SKU -->
  138. <productWindow :attr="attr" :isShow='1' :iSplus='1' :iScart='1' @ChangeAttr="ChangeAttr"
  139. @ChangeCartNum="ChangeCartNum" @iptCartNum="iptCartNum" @close="closeAttr" @goCat="reGoCat" />
  140. <!-- <view class="uni-p-b-96" />
  141. <view class="uni-p-b-98" /> -->
  142. </view>
  143. </template>
  144. <script>
  145. let sysHeight = 0
  146. import {
  147. toLogin
  148. } from '@/libs/login.js';
  149. import {
  150. mapGetters
  151. } from "vuex";
  152. import recommend from '@/components/recommend';
  153. import productWindow from '@/components/productWindow';
  154. import * as TradeCartApi from '@/api/trade/cart.js';
  155. import * as ProductSpuApi from '@/api/product/spu.js'
  156. import * as ProductFavoriteApi from '@/api/product/favorite.js';
  157. import * as Util from '@/utils/util.js';
  158. import * as ProductUtil from '@/utils/product.js';
  159. import * as PromotionActivityApi from '@/api/promotion/activity.js';
  160. export default {
  161. components: {
  162. recommend,
  163. productWindow,
  164. },
  165. data() {
  166. return {
  167. sysHeight: sysHeight,
  168. goodsHidden: false,
  169. footerswitch: true,
  170. hostProduct: [],
  171. hotPage: 1,
  172. hotLimit: 10,
  173. hotScroll: false,
  174. // 购物车列表
  175. cartList: { // 购物车列表
  176. valid: [], // 有效
  177. invalid: [] // 无效
  178. },
  179. isAllSelect: false, // 是否全选
  180. selectValue: [], // 选中的数据
  181. selectCountPrice: 0.00, // 选中的金额
  182. cartCount: 0, // 选中的商品数量
  183. canShow: false, // 是否可展示
  184. // 重选
  185. cartId: 0, // 重选的 cart id
  186. product_id: 0, // 重选的 SPU 编号
  187. attr: { // productWindow 组件,使用该属性
  188. cartAttr: false, // 是否打开属性的选择弹出
  189. // ↓↓↓ 属性数组,结构为:id = 属性编号;name = 属性编号的名字;values[].id = 属性值的编号,values[].name = 属性值的名字;index = 选中的属性值的名字
  190. properties: [],
  191. productSelect: {} // 选中的 SKU
  192. },
  193. spu: {}, // 商品 SPU 详情
  194. skuMap: [], // 商品 SKU Map
  195. attrValue: '', // 已选属性名的拼接,例如说 红色,大 这样的格式
  196. showCartList: false, //是否显示购物车list
  197. };
  198. },
  199. computed: mapGetters(['isLogin']),
  200. created() {
  201. console.log('我执行了')
  202. },
  203. created: function(options) {
  204. console.log(222)
  205. if (!this.isLogin) {
  206. toLogin();
  207. }
  208. },
  209. mounted: function() {
  210. console.log(1111)
  211. this.canShow = false
  212. if (this.isLogin === true) {
  213. // 加载热门商品
  214. this.hotPage = 1;
  215. this.hotLimit = 10;
  216. this.hostProduct = [];
  217. this.hotScroll = false;
  218. this.loadend = false;
  219. this.getHostProduct()
  220. // 加载购物车列表
  221. this.footerswitch = true;
  222. this.hotScroll = false;
  223. this.cartList = {
  224. valid: [],
  225. invalid: []
  226. };
  227. this.isAllSelect = false; // 全选
  228. this.selectValue = []; // 选中的数据
  229. this.selectCountPrice = 0.00;
  230. this.cartCount = 0;
  231. this.getCartList();
  232. }
  233. },
  234. methods: {
  235. /**
  236. * 修改购物车
  237. */
  238. reGoCat: function() {
  239. const productSelect = this.skuMap[this.attrValue];
  240. // 如果有属性,没有选择,提示用户选择
  241. if (this.attr.properties.length &&
  242. productSelect === undefined) {
  243. return this.$util.Tips({
  244. title: "产品库存不足,请选择其它"
  245. });
  246. }
  247. TradeCartApi.resetCart({
  248. id: this.cartId,
  249. skuId: this.attr.productSelect.id,
  250. count: this.attr.productSelect.cart_num
  251. }).then(res => {
  252. this.attr.cartAttr = false;
  253. this.$util.Tips({
  254. title: this.$t(`添加购物车成功`)
  255. });
  256. this.cartList.valid = [];
  257. this.getCartList();
  258. }).catch(res => {
  259. return this.$util.Tips({
  260. title: res
  261. });
  262. });
  263. },
  264. aaa() {
  265. console.log('我执行了点击btn')
  266. this.showCartList = true
  267. this.$emit('showMask')
  268. },
  269. /**
  270. * 重选 SKU
  271. */
  272. reElection: function(item) {
  273. this.getGoodsDetails(item)
  274. },
  275. /**
  276. * 获取产品详情
  277. */
  278. getGoodsDetails: function(item) {
  279. uni.showLoading({
  280. title: '加载中',
  281. mask: true
  282. });
  283. this.cartId = item.id;
  284. this.product_id = item.spu.id;
  285. ProductSpuApi.getSpuDetail(item.spu.id).then(res => {
  286. uni.hideLoading();
  287. this.attr.cartAttr = true;
  288. let spu = res.data;
  289. let properties = ProductUtil.convertProductPropertyList(res.data.skus);
  290. let skuMap = ProductUtil.convertProductSkuMap(res.data.skus);
  291. // 设置变量
  292. this.$set(this, 'spu', spu);
  293. this.$set(this.attr, 'properties', properties);
  294. this.$set(this, 'skuMap', skuMap);
  295. this.selectDefaultSku();
  296. }).catch(err => {
  297. uni.hideLoading();
  298. })
  299. },
  300. /**
  301. * 关闭 productWindow 弹窗
  302. */
  303. closeAttr: function() {
  304. this.$set(this.attr, "cartAttr", false);
  305. },
  306. /**
  307. * 属性变动赋值
  308. *
  309. * @param newSkuKey 新的 skuKey
  310. * @param propertyIndex properties 的下标
  311. * @param valueIndex values 的下标
  312. */
  313. ChangeAttr: function(newSkuKey, propertyIndex, valueIndex) {
  314. // SKU
  315. let sku = this.skuMap[newSkuKey];
  316. if (!sku) {
  317. return;
  318. }
  319. this.$set(this.attr.productSelect, "id", sku.id);
  320. this.$set(this.attr.productSelect, "picUrl", sku.picUrl);
  321. this.$set(this.attr.productSelect, "price", sku.price);
  322. this.$set(this.attr.productSelect, "stock", sku.stock);
  323. this.$set(this.attr.productSelect, "cart_num", 1);
  324. // SKU 关联属性
  325. this.$set(this.attr.properties[propertyIndex], 'index',
  326. this.attr.properties[propertyIndex].values[valueIndex].name);
  327. this.$set(this, "attrValue", newSkuKey);
  328. },
  329. /**
  330. * 查找默认选中的 sku,设置到 attr.productSelect 中
  331. *
  332. * 先找有库存的 SKU,否则找第一个 SKU
  333. */
  334. selectDefaultSku: function() {
  335. const properties = this.attr.properties;
  336. // 获得选中的属性值的名字,例如说 "黑色,大",则 skuKey = ["黑色", "大"]
  337. let skuKey = undefined;
  338. for (let key in this.skuMap) {
  339. if (this.skuMap[key].stock > 0) {
  340. skuKey = key.split(",");
  341. break;
  342. }
  343. }
  344. if (!skuKey) { // 如果找不到,则选中第一个
  345. skuKey = Object.keys(this.skuMap)[0].split(",");
  346. }
  347. // 使用 index 属性表示当前选中的,值为属性值的名字
  348. for (let i = 0; i < properties.length; i++) {
  349. this.$set(properties[i], "index", skuKey[i]);
  350. }
  351. let sku = this.skuMap[skuKey.join(",")];
  352. if (!sku) {
  353. return
  354. }
  355. this.$set(this.attr.productSelect, "spuName", this.spu.name);
  356. this.$set(this.attr.productSelect, "id", sku.id);
  357. this.$set(this.attr.productSelect, "picUrl", sku.picUrl);
  358. this.$set(this.attr.productSelect, "price", sku.price);
  359. this.$set(this.attr.productSelect, "stock", sku.stock);
  360. this.$set(this.attr.productSelect, "cart_num", 1);
  361. this.$set(this, "attrValue", skuKey.join(","));
  362. },
  363. /**
  364. * 购物车数量加和数量减
  365. *
  366. * @param changeValue true 增加;false 减少
  367. */
  368. ChangeCartNum: function(changeValue) {
  369. /// 获取当前 sku
  370. let sku = this.attr.productSelect;
  371. if (!sku) {
  372. return;
  373. }
  374. // 设置数量
  375. let stock = sku.stock || 0;
  376. if (changeValue) {
  377. sku.cart_num++;
  378. if (sku.cart_num > stock) {
  379. this.$set(this.attr.productSelect, "cart_num", stock);
  380. }
  381. } else {
  382. sku.cart_num--;
  383. if (sku.cart_num < 1) {
  384. this.$set(this.attr.productSelect, "cart_num", 1);
  385. }
  386. }
  387. },
  388. /**
  389. * 购物车手动填写
  390. */
  391. iptCartNum: function(number) {
  392. this.$set(this.attr.productSelect, 'cart_num', number ? number : 1);
  393. },
  394. /**
  395. * 删除选中的商品
  396. */
  397. subDel: function(event) {
  398. const selectValue = this.selectValue;
  399. if (selectValue.length === 0) {
  400. return this.$util.Tips({
  401. title: '请选择产品'
  402. });
  403. }
  404. TradeCartApi.deleteCart(selectValue).then(res => {
  405. this.getCartList();
  406. this.footerswitch=true
  407. this.$emit('hideMask')
  408. });
  409. },
  410. getSelectValueProductId: function() {
  411. const validList = this.cartList.valid;
  412. const selectValue = this.selectValue;
  413. let productId = [];
  414. if (selectValue.length > 0) {
  415. for (let index in validList) {
  416. if (this.inArray(validList[index].id, selectValue)) {
  417. productId.push(validList[index].spu.id);
  418. }
  419. }
  420. }
  421. return productId;
  422. },
  423. /**
  424. * 收藏选中的商品
  425. */
  426. subCollect: function(event) {
  427. const spuIds = this.getSelectValueProductId();
  428. if (spuIds.length === 0) {
  429. return this.$util.Tips({
  430. title: '请选择产品'
  431. });
  432. }
  433. ProductFavoriteApi.createFavoriteList(spuIds).then(res => {
  434. return this.$util.Tips({
  435. title: '收藏成功',
  436. icon: 'success'
  437. });
  438. }).catch(err => {
  439. return that.$util.Tips({
  440. title: err
  441. });
  442. });
  443. },
  444. /**
  445. * 立即下单
  446. */
  447. subOrder: function(event) {
  448. const selectValue = this.selectValue;
  449. if (selectValue.length === 0) {
  450. return this.$util.Tips({
  451. title: '请选择产品'
  452. });
  453. }
  454. uni.navigateTo({
  455. url: '/pages/users/order_confirm/index?cartIds=' + selectValue.join(',')
  456. });
  457. },
  458. /**
  459. * 预下单
  460. */
  461. getPreOrder: function() {
  462. let shoppingCartId = this.selectValue.map(item => {
  463. return {
  464. "shoppingCartId": Number(item)
  465. }
  466. })
  467. this.$Order.getPreOrder("shoppingCart", shoppingCartId);
  468. },
  469. /**
  470. * 全选 / 全不选
  471. */
  472. checkboxAllChange: function(event) {
  473. let value = event.detail.value;
  474. if (value.length > 0) {
  475. this.setAllSelectValue(true)
  476. } else {
  477. this.setAllSelectValue(false)
  478. }
  479. },
  480. /**
  481. * 全选 / 全不选
  482. */
  483. setAllSelectValue: function(selected) {
  484. const valid = this.cartList.valid;
  485. const values = [];
  486. for (const item of valid) {
  487. values.push(item.id.toString());
  488. }
  489. TradeCartApi.updateCartSelected({
  490. ids: values,
  491. selected: selected
  492. }).then(res => {
  493. this.getCartList()
  494. })
  495. },
  496. /**
  497. * 更新是否选中
  498. */
  499. checkboxChange: function(event) {
  500. // 由于 uniapp 不支持直接通过 event 获取到变更的值,所以只能通过比对
  501. const valid = this.cartList.valid;
  502. const oldValues = [];
  503. for (const item of valid) {
  504. if (item.canChecked && item.selected) {
  505. oldValues.push(item.id.toString());
  506. } else if (!this.footerswitch && item.selected) {
  507. oldValues.push(item.id.toString());
  508. }
  509. }
  510. const newValues = event.detail.value;
  511. // 情况一:选中
  512. const selectedItem = newValues.find(item => !oldValues.includes(item));
  513. if (selectedItem) {
  514. TradeCartApi.updateCartSelected({
  515. ids: [selectedItem],
  516. selected: true
  517. }).then(res => {
  518. this.getCartList()
  519. })
  520. return;
  521. }
  522. // 情况二:取消选中
  523. const cancelSelectedItem = oldValues.find(item => !newValues.includes(item));
  524. if (cancelSelectedItem) {
  525. TradeCartApi.updateCartSelected({
  526. ids: [cancelSelectedItem],
  527. selected: false
  528. }).then(res => {
  529. this.getCartList()
  530. })
  531. }
  532. },
  533. /**
  534. * 合计金额、数量
  535. */
  536. switchSelect: function() {
  537. // 是否全选
  538. const validList = this.cartList.valid;
  539. const selectValue = [];
  540. let isAllSelect = true;
  541. if (validList && validList.length > 0) {
  542. for (const item of validList) {
  543. if (item.canChecked) {
  544. if (item.selected) {
  545. selectValue.push(item.id);
  546. } else {
  547. isAllSelect = false;
  548. }
  549. } else {
  550. if (!this.footerswitch && item.selected) {
  551. selectValue.push(item.id);
  552. }
  553. if (!this.footerswitch && !item.selected) {
  554. isAllSelect = false;
  555. }
  556. }
  557. }
  558. }
  559. this.selectValue = selectValue;
  560. this.isAllSelect = isAllSelect;
  561. // 合计金额
  562. let selectCountPrice = 0.00;
  563. let cartCount = 0
  564. for (let index in validList) {
  565. if (this.inArray(validList[index].id, selectValue) &&
  566. validList[index].sku) {
  567. selectCountPrice = this.$util.$h.Add(selectCountPrice, this.$util.$h.Mul(validList[index]
  568. .count, validList[index].sku.price))
  569. cartCount += validList[index].count
  570. }
  571. }
  572. this.selectCountPrice = selectCountPrice;
  573. this.cartCount = cartCount;
  574. },
  575. /**
  576. * 减少购买数量
  577. */
  578. subCart: function(index) {
  579. let item = this.cartList.valid[index];
  580. console.log('我是减少的打印',item)
  581. if (item.count <= 1) {
  582. console.log('我进来减少了')
  583. this.$util.Tips({
  584. title: '商品数量不能减少!'
  585. });
  586. return;
  587. }
  588. // 本地先修改状态
  589. item.count = Number(item.count) - 1;
  590. console.log(item.count,8888)
  591. if (item.count <= 1) {
  592. item.count = 1;
  593. item.numSub = true;
  594. } else {
  595. item.numSub = false;
  596. item.numAdd = false;
  597. }
  598. // 提交修改
  599. this.setCartNum(item.id, item.count);
  600. },
  601. /**
  602. * 增加购买数量
  603. */
  604. addCart: function(index) {
  605. // 本地先修改状态
  606. let item = this.cartList.valid[index];
  607. item.count = Number(item.count) + 1
  608. if (item.count >= item.sku.stock) {
  609. item.count = item.sku.stock;
  610. item.numAdd = true;
  611. item.numSub = false;
  612. } else {
  613. item.numAdd = false;
  614. item.numSub = false;
  615. }
  616. // 提交修改
  617. this.setCartNum(item.id, item.count);
  618. },
  619. /**
  620. * 修改购物项为指定数量
  621. */
  622. setCartNum(cartId, cartNum) {
  623. TradeCartApi.updateCartCount({
  624. id: cartId,
  625. count: cartNum
  626. }).then(res => {
  627. // 加载最新状态
  628. this.getCartList()
  629. });
  630. },
  631. getCartData() {
  632. return new Promise((resolve, reject) => {
  633. TradeCartApi.getCartList().then((res) => {
  634. resolve(res.data);
  635. }).catch(function(err) {
  636. this.canShow = true;
  637. this.$util.Tips({
  638. title: err
  639. });
  640. })
  641. });
  642. },
  643. async getCartList() {
  644. console.log('我是组件购物车')
  645. uni.showLoading({
  646. title: '加载中',
  647. mask: true
  648. });
  649. // 加载购物车
  650. const cartList = await this.getCartData();
  651. const validList = cartList.validList;
  652. const invalidList = cartList.invalidList;
  653. // 有效的购物车
  654. if (validList.length > 0) {
  655. for (let index in validList) {
  656. // 设置是否可减少(到底,不可减少)
  657. validList[index].numSub = validList[index].cartNum === 1;
  658. // 设置是否可添加(到顶,不可添加)
  659. const sku = validList[index].sku;
  660. validList[index].numAdd = sku && validList[index].count < sku.stock;
  661. // 设置为选中,并添加到 selectValue 数组中
  662. // why?库存不足时,可以引导选择该 SPU 对应的其它 SKU。而 invalidList 是 SPU 不存在或者库存彻底不足
  663. if (sku && sku.stock > 0) {
  664. validList[index].canChecked = true; // 是否可选中:是
  665. } else {
  666. validList[index].canChecked = false; // 是否可选中:否
  667. }
  668. }
  669. }
  670. this.$Cache
  671. console.log(validList,'11111111111111111111111111111111111111111')
  672. this.$emit('cartList', validList);
  673. this.$set(this.cartList, 'valid', validList);
  674. console.log(this.cartList,888)
  675. this.switchSelect();
  676. // 无效的购物车
  677. this.$set(this.cartList, 'invalid', invalidList);
  678. // 标记加载结束
  679. this.canShow = true;
  680. uni.hideLoading();
  681. },
  682. /**
  683. * 获得“热门推荐”
  684. */
  685. getHostProduct: function() {
  686. ProductSpuApi.getSpuPage({
  687. recommendType: 'hot',
  688. pageNo: this.hotPage,
  689. pageSize: this.hotLimit
  690. }).then(res => {
  691. const good_list = res.data.list;
  692. this.hotPage++
  693. this.hotScroll = good_list.length < this.hotLimit
  694. // 设置营销活动
  695. const spuIds = good_list.map(item => item.id);
  696. if (spuIds.length > 0) {
  697. PromotionActivityApi.getActivityListBySpuIds(spuIds).then(res => {
  698. ProductUtil.setActivityList(good_list, res.data);
  699. this.hostProduct = this.hostProduct.concat(
  700. good_list) // 放在此处,避免 Vue 监控不到数组里的元素变化
  701. });
  702. }
  703. });
  704. },
  705. goodsOpen: function() {
  706. this.goodsHidden = !this.goodsHidden;
  707. },
  708. /**
  709. * 切换到管理
  710. */
  711. manage: function() {
  712. this.footerswitch = !this.footerswitch;
  713. this.switchSelect();
  714. },
  715. /**
  716. * 清空
  717. */
  718. unsetCart: function() {
  719. const ids = [];
  720. for (let i = 0, len = this.cartList.invalid.length; i < len; i++) {
  721. ids.push(this.cartList.invalid[i].id);
  722. }
  723. TradeCartApi.deleteCart(ids).then(res => {
  724. this.$util.Tips({
  725. title: '清除成功'
  726. });
  727. this.getCartList()
  728. }).catch(res => {});
  729. },
  730. fen2yuan(price) {
  731. return Util.fen2yuan(price)
  732. },
  733. inArray: function(search, array) {
  734. for (let i in array) {
  735. if (array[i] === search) {
  736. return true;
  737. }
  738. }
  739. return false;
  740. },
  741. },
  742. onReachBottom() {
  743. if (this.cartList.valid.length === 0 &&
  744. this.cartList.invalid.length === 0 &&
  745. this.hotPage != 1) {
  746. this.getHostProduct();
  747. }
  748. }
  749. }
  750. </script>
  751. <style scoped lang="scss">
  752. .invalidClas {
  753. position: relative;
  754. z-index: 111;
  755. top: -120rpx;
  756. }
  757. .invalidClasNO {
  758. position: static;
  759. margin-top: 15px;
  760. }
  761. .cartBox {
  762. // background-color: #fff;
  763. }
  764. .shoppingCart {
  765. /* #ifdef H5 */
  766. // padding-bottom: 0;
  767. // padding-bottom: constant(safe-area-inset-bottom);
  768. // padding-bottom: env(safe-area-inset-bottom);
  769. /* #endif */
  770. }
  771. .shoppingCart .labelNav {
  772. height: 178rpx;
  773. padding: 30rpx 30rpx 0 30rpx;
  774. font-size: 22rpx;
  775. color: #fff;
  776. position: fixed;
  777. left: 0;
  778. width: 100%;
  779. box-sizing: border-box;
  780. background-color: $theme-color;
  781. z-index: 5;
  782. top: 0;
  783. }
  784. .shoppingCart .labelNav .item .iconfont {
  785. font-size: 25rpx;
  786. margin-right: 10rpx;
  787. }
  788. .shoppingCart .nav {
  789. width: 92%;
  790. height: 90rpx;
  791. background-color: #fff;
  792. padding: 0 24rpx;
  793. -webkit-box-sizing: border-box;
  794. box-sizing: border-box;
  795. font-size: 28rpx;
  796. color: #282828;
  797. // position: fixed;
  798. left: 30rpx;
  799. z-index: 6;
  800. top: 94rpx;
  801. border-top-left-radius: 14rpx;
  802. border-top-right-radius: 14rpx;
  803. }
  804. .shoppingCart .nav .num {
  805. margin-left: 12rpx;
  806. }
  807. .shoppingCart .nav .administrate {
  808. font-size: 28rpx;
  809. color: #333333;
  810. }
  811. .shoppingCart .noCart {
  812. margin-top: 171rpx;
  813. background-color: #fff;
  814. padding-top: 0.1rpx;
  815. }
  816. .shoppingCart .noCart .pictrue {
  817. width: 414rpx;
  818. height: 336rpx;
  819. margin: 78rpx auto 56rpx auto;
  820. }
  821. .shoppingCart .noCart .pictrue image {
  822. width: 100%;
  823. height: 100%;
  824. }
  825. .shoppingCart .list {
  826. width: 100%;
  827. // margin-top: 178rpx;
  828. overflow: hidden;
  829. border-bottom-left-radius: 14rpx;
  830. border-bottom-right-radius: 14rpx;
  831. }
  832. .shoppingCart .list .item {
  833. padding: 24rpx;
  834. background-color: #fff;
  835. }
  836. .shoppingCart .list .item .picTxt {
  837. width: 582rpx;
  838. position: relative;
  839. }
  840. .shoppingCart .list .item .picTxt .pictrue {
  841. width: 160rpx;
  842. height: 160rpx;
  843. }
  844. .shoppingCart .list .item .picTxt .pictrue image {
  845. width: 100%;
  846. height: 100%;
  847. border-radius: 6rpx;
  848. }
  849. .shoppingCart .list .item .picTxt .text {
  850. width: 396rpx;
  851. font-size: 28rpx;
  852. color: #282828;
  853. }
  854. .shoppingCart .list .item .picTxt .text .reColor {
  855. color: #999;
  856. }
  857. .shoppingCart .list .item .picTxt .text .reElection {
  858. margin-top: 20rpx;
  859. }
  860. .shoppingCart .list .item .picTxt .text .reElection .title {
  861. font-size: 24rpx;
  862. }
  863. .shoppingCart .list .item .picTxt .text .reElection .reBnt {
  864. width: 120rpx;
  865. height: 46rpx;
  866. border-radius: 23rpx;
  867. font-size: 26rpx;
  868. }
  869. .shoppingCart .list .item .picTxt .text .infor {
  870. font-size: 24rpx;
  871. color: #999999;
  872. margin-top: 16rpx;
  873. }
  874. .shoppingCart .list .item .picTxt .text .money {
  875. font-size: 32rpx;
  876. color: #E93323;
  877. margin-top: 28rpx;
  878. font-weight: 600;
  879. }
  880. .shoppingCart .list .item .picTxt .carnum {
  881. height: 47rpx;
  882. position: absolute;
  883. bottom: 7rpx;
  884. right: 0;
  885. }
  886. .shoppingCart .list .item .picTxt .carnum view {
  887. border: 1rpx solid #a4a4a4;
  888. width: 66rpx;
  889. text-align: center;
  890. height: 100%;
  891. line-height: 44rpx;
  892. font-size: 28rpx;
  893. color: #a4a4a4;
  894. }
  895. .shoppingCart .list .item .picTxt .carnum .reduce {
  896. border-right: 0;
  897. border-radius: 3rpx 0 0 3rpx;
  898. border-radius: 22rpx 0rpx 0rpx 22rpx;
  899. font-size: 34rpx;
  900. line-height: 40rpx;
  901. }
  902. .shoppingCart .list .item .picTxt .carnum .reduce.on {
  903. border-color: #e3e3e3;
  904. color: #dedede;
  905. }
  906. .shoppingCart .list .item .picTxt .carnum .plus {
  907. border-left: 0;
  908. border-radius: 0 3rpx 3rpx 0;
  909. border-radius: 0rpx 22rpx 22rpx 0rpx;
  910. font-size: 34rpx;
  911. line-height: 40rpx;
  912. }
  913. .shoppingCart .list .item .picTxt .carnum .num {
  914. color: #282828;
  915. }
  916. .shoppingCart .invalidGoods {
  917. background-color: #fff;
  918. margin-top: 30rpx;
  919. /* #ifdef MP */
  920. margin-top: 140rpx;
  921. /* #endif */
  922. }
  923. .shoppingCart .invalidGoods .goodsNav {
  924. width: 100%;
  925. height: 90rpx;
  926. padding: 0 24rpx;
  927. box-sizing: border-box;
  928. font-size: 28rpx;
  929. color: #333333;
  930. }
  931. .shoppingCart .invalidGoods .goodsNav .iconfont {
  932. color: #424242;
  933. font-size: 28rpx;
  934. margin-right: 17rpx;
  935. }
  936. .shoppingCart .invalidGoods .goodsNav .del {
  937. font-size: 26rpx;
  938. color: #333;
  939. }
  940. .shoppingCart .invalidGoods .goodsNav .del .icon-shanchu1 {
  941. color: #333;
  942. font-size: 33rpx;
  943. vertical-align: -2rpx;
  944. margin-right: 8rpx;
  945. }
  946. .shoppingCart .invalidGoods .goodsList .item {
  947. padding: 24rpx;
  948. }
  949. .shoppingCart .invalidGoods .goodsList .picTxt {
  950. width: 576rpx;
  951. }
  952. .shoppingCart .invalidGoods .goodsList .item .invalid {
  953. font-size: 22rpx;
  954. color: #CCCCCC;
  955. height: 36rpx;
  956. border-radius: 3rpx;
  957. text-align: center;
  958. line-height: 36rpx;
  959. }
  960. .shoppingCart .invalidGoods .goodsList .item .pictrue {
  961. width: 160rpx;
  962. height: 160rpx;
  963. }
  964. .shoppingCart .invalidGoods .goodsList .item .pictrue image {
  965. width: 100%;
  966. height: 100%;
  967. border-radius: 6rpx;
  968. }
  969. .shoppingCart .invalidGoods .goodsList .item .text {
  970. width: 396rpx;
  971. font-size: 28rpx;
  972. color: #999;
  973. height: 140rpx;
  974. }
  975. .shoppingCart .invalidGoods .goodsList .item .text .name {
  976. width: 100%;
  977. }
  978. .shoppingCart .invalidGoods .goodsList .item .text .infor {
  979. font-size: 24rpx;
  980. }
  981. .shoppingCart .invalidGoods .goodsList .item .text .end {
  982. font-size: 26rpx;
  983. color: #bbb;
  984. }
  985. .footer {
  986. z-index: 9;
  987. width: 100%;
  988. height: 100rpx;
  989. background-color: #fff;
  990. position: fixed;
  991. padding: 0 24rpx;
  992. box-sizing: border-box;
  993. border-top: 1rpx solid #eee;
  994. // border-bottom: 1px solid #EEEEEE;
  995. /* #ifdef H5 */
  996. bottom: 98rpx;
  997. /* #endif */
  998. /* #ifdef MP */
  999. bottom: 0;
  1000. /* #endif */
  1001. /* #ifndef MP */
  1002. // bottom: 98rpx;
  1003. // bottom: calc(98rpx+ constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  1004. // bottom: calc(98rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  1005. /* #endif */
  1006. }
  1007. .footer .checkAll {
  1008. font-size: 28rpx;
  1009. color: #282828;
  1010. margin-left: 14rpx;
  1011. }
  1012. .footer .money {
  1013. font-size: 30rpx;
  1014. .font-color {
  1015. font-weight: 600;
  1016. }
  1017. }
  1018. .footer .placeOrder {
  1019. color: #fff;
  1020. font-size: 30rpx;
  1021. width: 226rpx;
  1022. height: 70rpx;
  1023. border-radius: 50rpx;
  1024. text-align: center;
  1025. line-height: 70rpx;
  1026. margin-left: 22rpx;
  1027. }
  1028. .footer .button .bnt {
  1029. font-size: 28rpx;
  1030. color: #999;
  1031. border-radius: 50rpx;
  1032. border: 1px solid #999;
  1033. width: 160rpx;
  1034. height: 60rpx;
  1035. text-align: center;
  1036. line-height: 60rpx;
  1037. }
  1038. .footer .button form~form {
  1039. margin-left: 17rpx;
  1040. }
  1041. .uni-p-b-96 {
  1042. height: 96rpx;
  1043. }
  1044. </style>