pond.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. <template>
  2. <app-layout>
  3. <view class="pond">
  4. <view class="bulletin dir-left-nowrap">
  5. <text class="bulletin-text">结算规则:选购商品数等于任选商品数的倍数</text>
  6. <view class="edit" v-if="!edit" @click="setEdit(true)">编辑</view>
  7. <view class="edit" v-else @click="setEdit(false)">完成</view>
  8. </view>
  9. <view class="list">
  10. <view class="empty" v-if="pond.length === 0">
  11. <view class="cart">
  12. <image src="/static/image/icon/nav-icon-cart.png"></image>
  13. </view>
  14. <text>凑单池还是空的哦</text>
  15. </view>
  16. <view class="item dir-left-nowrap" v-for="(item) in pond" :key="item.id" v-else>
  17. <view class="radio dir-top-nowrap main-center cross-center" @click="changeActive(item)" v-if="item.pick_activity_id == pick_activity_id && !edit">
  18. <view class="radio-single" v-if="!item.is_active"></view>
  19. <view class="radio-single-active" v-else :style="{'background-color': getTheme.background}"></view>
  20. </view>
  21. <view class="radio dir-top-nowrap main-center cross-center" @click="changeActive(item)" v-if="edit">
  22. <view class="radio-single" v-if="!item.is_active"></view>
  23. <view class="radio-single-active" v-else :style="{'background-color': getTheme.background}"></view>
  24. </view>
  25. <view class="radio dir-top-nowrap main-center cross-center" v-else-if="item.pick_activity_id != pick_activity_id && !edit">
  26. <view class="radio-lapse">
  27. 失效
  28. </view>
  29. </view>
  30. <view class="content dir-left-nowrap">
  31. <image class="cover-pic" :src="item.attrs.pic_url ? item.attrs.pic_url : item.goods.cover_pic "></image>
  32. <view class="text dir-top-nowrap main-between">
  33. <text class="name t-omit-two">
  34. {{item.goods.name}}
  35. </text>
  36. <view class="it-attr t-omit">
  37. <text v-for="(it, i) in item.attrs.attr" :key="i">
  38. {{it.attr_group_name}}:{{it.attr_name}}<text class="empty-nbsp"></text>
  39. </text>
  40. </view>
  41. <view class="dir-left-nowrap main-between cross-center">
  42. <template v-if="item.pick_activity_id == pick_activity_id">
  43. <text class="price" :style="{'color': getTheme.color}">{{item.attrs.price}}</text>
  44. <view class="aob dir-left-nowrap main-around cross-center">
  45. <view class="icon" @click="_calcValue(item, 'minus')" :class="{'app-unreducible': item.num == 1, 'app-can-be-reduced': item.num > 1}"></view>
  46. <input v-model="item.num" @change="editInput(item)" type="number">
  47. <view class="icon" @click="_calcValue(item, 'plus')" :style="{'background-color': getTheme.background}" :class="[{'app-not-add': item.num >= item.attrs.stock, ' app-can-add': item.num < item.attrs.stock}]"></view>
  48. </view>
  49. </template>
  50. <view v-else style="font-size: 25rpx;">
  51. 此活动已过期,无法购买
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. </view>
  58. <view class="safe-area-inset-bottom u-bottom-fixed">
  59. <view class="settlement dir-left-nowrap">
  60. <view class="all-price dir-left-nowrap">
  61. <view class="all-select dir-left-nowrap main-center cross-center" @click="selectAll">
  62. <view class="all-radio">
  63. <view class="radio-single" v-if="!is_active"></view>
  64. <view class="radio-single-active" :style="{'background-color': getTheme.background}" v-else></view>
  65. </view>
  66. <text class="all-text">全选</text>
  67. </view>
  68. <view class="red-text dir-top-nowrap main-center" v-if="!edit">
  69. <text class="all-price-text" :style="{'color': getTheme.color}">总计:¥{{all_price}}</text>
  70. <text class="other-good" :style="{'color': getTheme.color}" v-if="stillNeed !== 0">还需添加{{stillNeed}}件商品</text>
  71. </view>
  72. </view>
  73. <view class="button" :style="{'background-color': getTheme.background}" :class="[{'disabled': all_num == 0}, {'disabled': stillNeed > 0}]" @click="buy" v-if="!edit">
  74. 去结算
  75. </view>
  76. <view class="delete" :style="{'color': getTheme.color}" @click="del()" v-else>
  77. <view>
  78. 删除
  79. </view>
  80. </view>
  81. </view>
  82. </view>
  83. </view>
  84. </app-layout>
  85. </template>
  86. <script>
  87. import {mapGetters} from "vuex";
  88. export default {
  89. name: "pond",
  90. data() {
  91. return {
  92. pond: [],
  93. step: 1,
  94. pick_activity_id: 0,
  95. pay_pond: [],
  96. all_price: 0,
  97. is_active: false,
  98. rule_num: 0,
  99. edit: false,
  100. stillNeed: 0,
  101. buy_goods_list: [],
  102. all_num: 0
  103. }
  104. },
  105. computed: {
  106. ...mapGetters('mallConfig', {
  107. getTheme: 'getTheme',
  108. }),
  109. },
  110. onLoad(options) { this.$commonLoad.onload(options);
  111. this.pick_activity_id = options.pick_activity_id;
  112. this.rule_num = options.rule_num;
  113. },
  114. onShow() {
  115. this.getCart();
  116. },
  117. methods: {
  118. changeActive(item) {
  119. item.is_active = !item.is_active;
  120. },
  121. _calcValue(item, type) {
  122. const scale = this._getDecimalScale();
  123. let value = item.num * scale;
  124. let step = this.step * scale;
  125. if (type === "minus") {
  126. value -= step;
  127. } else if (type === "plus") {
  128. value += step;
  129. }
  130. if (value < 1 || value > item.attrs.stock) {
  131. return;
  132. }
  133. item.num = String(value / scale);
  134. this.editList();
  135. // this.$storage.setStorageSync('PICK', this.pond);
  136. },
  137. editInput() {
  138. this.editList();
  139. },
  140. _getDecimalScale() {
  141. let scale = 1;
  142. // 浮点型
  143. if (~~this.step !== this.step) {
  144. scale = Math.pow(10, (this.step + "").split(".")[1].length);
  145. }
  146. return scale;
  147. },
  148. selectAll() {
  149. this.is_active = !this.is_active;
  150. for (let i = 0; i < this.pond.length; i++) {
  151. if (this.pond[i].pick_activity_id == this.pick_activity_id && !this.edit) {
  152. this.pond[i].is_active = this.is_active;
  153. } else if (this.edit) {
  154. this.pond[i].is_active = this.is_active;
  155. }
  156. }
  157. },
  158. buy() {
  159. let data = [];
  160. this.buy_goods_list = [];
  161. let obj = {
  162. mch_id: '0',
  163. goods_list: this.buy_goods_list,
  164. pick_activity_id: this.pick_activity_id
  165. };
  166. data.push(obj);
  167. for (let i = 0; i < this.pay_pond.length; i++) {
  168. this.buy_goods_list.push({
  169. id: this.pay_pond[i].goods_id,
  170. attr: this.pay_pond[i].attrs.attr,
  171. num: this.pay_pond[i].num,
  172. cat_id:0,
  173. cart_id: this.pay_pond[i].id,
  174. goods_attr_id: this.pay_pond[i].attrs.id
  175. });
  176. }
  177. if (this.stillNeed !== 0) {
  178. return;
  179. }
  180. if (this.buy_goods_list.length === 0) {
  181. return;
  182. }
  183. let str = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(data)}&preview_url=${encodeURIComponent(this.$api.pick.order_preview)}&submit_url=${encodeURIComponent(this.$api.pick.order_submit)}`;
  184. uni.navigateTo({
  185. url: str
  186. });
  187. },
  188. setEdit(boolean) {
  189. for (let i = 0; i < this.pond.length; i++) {
  190. this.pond[i].is_active = false;
  191. }
  192. this.is_active = false;
  193. this.edit = boolean;
  194. },
  195. async del() {
  196. let data = JSON.parse(JSON.stringify(this.pay_pond));
  197. let list = [];
  198. for (let i = 0; i < data.length; i++) {
  199. list.push( data[i].id);
  200. }
  201. const e = await this.$request({
  202. url: this.$api.pick.delete,
  203. method: 'post',
  204. data: {
  205. cart_id_list: JSON.stringify(list),
  206. }
  207. });
  208. if (e.code === 0) {
  209. this.is_active = false;
  210. this.getCart();
  211. }
  212. },
  213. async getCart() {
  214. const e = await this.$request({
  215. url: this.$api.pick.list
  216. });
  217. if (e.code === 0) {
  218. let list = e.data.list;
  219. for (let i = 0; i < list.length; i++) {
  220. list[i].is_active = false;
  221. }
  222. this.pond = list;
  223. }
  224. },
  225. async editList() {
  226. let data = JSON.parse(JSON.stringify(this.pond));
  227. let list = [];
  228. for (let i = 0; i < data.length; i++) {
  229. list.push({
  230. attr: data[i].attr_id,
  231. goods_id: data[i].goods_id,
  232. num: data[i].num
  233. })
  234. }
  235. const e = await this.$request({
  236. url: this.$api.pick.edit,
  237. method: 'post',
  238. data: {
  239. list: JSON.stringify(list),
  240. }
  241. });
  242. }
  243. },
  244. watch: {
  245. pond: {
  246. handler(data) {
  247. this.pay_pond = [];
  248. let all_price = 0;
  249. let all_active = 0;
  250. this.all_num = 0;
  251. for (let i = 0; i < data.length; i++) {
  252. if (data[i].is_active) {
  253. this.pay_pond.push(data[i]);
  254. all_active++;
  255. this.all_num += Number(data[i].num);
  256. all_price += data[i].num*data[i].attrs.price;
  257. }
  258. }
  259. if (all_active === data.length) {
  260. this.is_active = true;
  261. data.length === 0 ? this.is_active = false : null;
  262. } else {
  263. this.is_active = false;
  264. }
  265. this.all_num%this.rule_num === 0 ? this.stillNeed = 0 : this.stillNeed = this.rule_num - (this.all_num%this.rule_num);
  266. this.all_price = all_price.toFixed(2);
  267. },
  268. deep: true
  269. }
  270. },
  271. }
  272. </script>
  273. <style scoped lang="scss">
  274. .pond {
  275. padding-bottom: #{100upx};
  276. }
  277. .settlement {
  278. height: #{110upx};
  279. width: #{750upx};
  280. background-color: #ffffff;
  281. border-top: #{1upx} solid #e2e2e2;
  282. }
  283. .button {
  284. width: #{250upx};
  285. height: #{110upx};
  286. font-size: #{32upx};
  287. color: #ffffff;
  288. text-align: center;
  289. line-height: #{110upx};
  290. }
  291. .all-price {
  292. width: #{500upx};
  293. height: #{100upx};
  294. }
  295. .bulletin {
  296. height: #{70upx};
  297. width: #{750upx};
  298. background-color: #ffffff;
  299. position: fixed;
  300. top: 0;
  301. }
  302. .edit {
  303. width: #{116upx};
  304. height: #{70upx};
  305. line-height: #{70upx};
  306. font-size: #{25upx};
  307. text-align: center;
  308. }
  309. .bulletin-text {
  310. font-size: #{25upx};
  311. line-height: #{70upx};
  312. width: #{610upx};
  313. color: #999999;
  314. margin-left: #{24upx};
  315. }
  316. .list {
  317. margin-top: #{100upx};
  318. background-color: #ffffff;
  319. }
  320. .item {
  321. width: #{750upx};
  322. border-bottom: #{1upx} solid #e2e2e2;
  323. height: #{218upx};
  324. padding: #{30upx 0 15upx 0};
  325. }
  326. .radio {
  327. width: #{85upx};
  328. height: #{156upx};
  329. }
  330. .radio-single {
  331. width: #{40rpx};
  332. height: #{40rpx};
  333. border-radius: 50%;
  334. background-color: white;
  335. border: #{1rpx} solid #e2e2e2;
  336. }
  337. .radio-single-active {
  338. width: #{40rpx};
  339. height: #{40rpx};
  340. border-radius: 50%;
  341. background-repeat: repeat;
  342. background-size: 100% 100%;
  343. background-image: url("../../../static/image/icon/icon-checkbox-checked.png");
  344. }
  345. .content {
  346. width: #{665upx};
  347. padding-right: #{25upx};
  348. }
  349. .cover-pic {
  350. width: #{156upx};
  351. height: #{156upx};
  352. }
  353. .text {
  354. margin-left: #{20upx};
  355. height: #{171upx};
  356. width: #{440upx};
  357. }
  358. .text>view {
  359. width: 100%;
  360. }
  361. .name {
  362. font-size: #{28upx};
  363. color: #3f3f3f;
  364. }
  365. .price {
  366. font-size: #{32upx};
  367. }
  368. .price:before {
  369. content: '¥';
  370. font-size: #{24upx};
  371. }
  372. .aob {
  373. height: #{60upx};
  374. input {
  375. height: #{60rpx};
  376. width: #{88rpx};
  377. font-size: #{21rpx};
  378. color: #353535;
  379. text-align: center;
  380. }
  381. }
  382. .app-unreducible {
  383. background-image: url("../../../static/image/cart/unreducible.png");
  384. }
  385. .app-not-add {
  386. background-image: url("./../../../static/image/cart/can-add.png");
  387. }
  388. .app-can-add {
  389. background-image: url("../../../static/image/icon/add-but.png");
  390. }
  391. .app-can-be-reduced {
  392. background-image: url("../../../static/image/icon/subtract.png");
  393. }
  394. .all-select {
  395. width: #{150upx};
  396. height: 100%;
  397. }
  398. .all-text {
  399. font-size: #{26upx};
  400. color: #3f3f3f;
  401. margin-left: #{5upx};
  402. }
  403. .all-radio {
  404. margin-right: #{5upx};
  405. }
  406. .all-price-text {
  407. font-size: #{26upx};
  408. line-height: 1;
  409. }
  410. .red-text {
  411. width: #{350upx};
  412. }
  413. .other-good {
  414. font-size: #{21upx};
  415. margin-top: #{10upx};
  416. line-height: 1;
  417. }
  418. .delete {
  419. width: #{250upx};
  420. height: #{100upx};
  421. position: relative;
  422. >view {
  423. font-size: #{24upx};
  424. text-align: center;
  425. width: #{140upx};
  426. height: #{64upx};
  427. line-height: #{64upx};
  428. border-radius: #{28upx};
  429. border: #{1upx} solid;
  430. position: absolute;
  431. right: #{24upx};
  432. top: #{18upx};
  433. }
  434. }
  435. .it-attr {
  436. font-size: #{22upx};
  437. color: #999999;
  438. }
  439. .disabled {
  440. background-color: #999999;
  441. }
  442. .empty {
  443. margin-top: #{150upx};
  444. width: #{750upx};
  445. /*position: relative;*/
  446. text-align: center;
  447. >text {
  448. color: #999999;
  449. font-size: #{26upx};
  450. position: absolute;
  451. top: #{325upx};
  452. transform: translateX(-50%);
  453. }
  454. }
  455. .cart {
  456. width: #{160upx};
  457. height: #{160upx};
  458. border-radius: 50%;
  459. background-color: #dedede;
  460. position: absolute;
  461. left: 50%;
  462. transform: translateX(-50%);
  463. >image {
  464. width: #{59upx};
  465. height: #{59upx};
  466. position: absolute;
  467. left: 50%;
  468. top:50%;
  469. transform: translate(-50%, -50%);
  470. }
  471. }
  472. .empty-nbsp {
  473. width: #{10upx};
  474. display: inline-block;
  475. }
  476. .radio-lapse {
  477. height: #{32upx};
  478. width: #{64upx};
  479. border-radius: #{16upx};
  480. background-color: #cdcdcd;
  481. font-size: #{23upx};
  482. color: #ffffff;
  483. line-height: #{32upx};
  484. text-align: center;
  485. }
  486. .icon {
  487. height: #{44rpx};
  488. width: #{44rpx};
  489. background-size: 100% 100%;
  490. background-repeat: no-repeat;
  491. }
  492. .u-bottom-fixed {
  493. position: fixed;
  494. bottom: 0;
  495. left: 0;
  496. width: 100%;
  497. z-index: 1602;
  498. background-color: #ffffff;
  499. }
  500. </style>