good-detail.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <template>
  2. <view class="good-detail">
  3. <custom-nav noback="noback" transparent="transparent" ref="ltm" title=" " />
  4. <view class="shopcar-buy">
  5. <navigator open-type="switchTab" url="../shop-car1/shop-car1" id="shopcar" class="shopcar">
  6. <text class="cuIcon-cart"></text>
  7. <text>购物车</text>
  8. <text v-if="shopcarNum" class="num">{{ shopcarNum }}</text>
  9. </navigator>
  10. <view class="addshopcar" @tap="addToshopCar">加入购物车</view>
  11. <view class="buy" @tap="buy">立即购买</view>
  12. </view>
  13. <view class="content">
  14. <swiper :indicator-dots="true" :circular="true" :autoplay="true" :interval="3456" :duration="234" indicator-color="#FFFFFF" indicator-active-color="#F76454">
  15. <swiper-item v-for="(item, index) in goodInfo.imgList" :key="index">
  16. <image :src="item"></image>
  17. </swiper-item>
  18. </swiper>
  19. <view class="goodinfo app-item">
  20. <view class="name">商品名称:{{ goodInfo.name || '' }}</view>
  21. <view class="price-storage">
  22. <text class="price">进货价:¥{{ goodInfo.price || '' }}</text>
  23. <text class="storage">我的库存:{{ goodInfo.storage || '' }} 套</text>
  24. </view>
  25. </view>
  26. <navigator :url="'../choose-size/choose-size?typeList=' + JSON.stringify(goodInfo.typeList)" class="choose-size app-item">
  27. <text>选择尺码</text>
  28. <view class="size-right">
  29. <view class="size">
  30. <view v-if="s">
  31. <text>S</text>
  32. <text v-if="!flying" id="s" class="num">{{ s }}</text>
  33. </view>
  34. <view v-if="m">
  35. <text>M</text>
  36. <text v-if="!flying" id="m" class="num">{{ m }}</text>
  37. </view>
  38. <view v-if="l">
  39. <text>L</text>
  40. <text v-if="!flying" id="l" class="num">{{ l }}</text>
  41. </view>
  42. <view v-if="xl">
  43. <text>XL</text>
  44. <text v-if="!flying" id="xl" class="num">{{ xl }}</text>
  45. </view>
  46. <view v-if="xxl">
  47. <text>XXL</text>
  48. <text v-if="!flying" id="xxl" class="num">{{ xxl }}</text>
  49. </view>
  50. <view v-if="xxxl">
  51. <text>XXXL</text>
  52. <text v-if="!flying" id="xxxl" class="num">{{ xxxl }}</text>
  53. </view>
  54. </view>
  55. <text class="cuIcon-right"></text>
  56. </view>
  57. </navigator>
  58. <view class="choose-num app-item item-space">
  59. <text>已选数量</text>
  60. <text>{{ choosedNum + ' '}}套</text>
  61. </view>
  62. <view class="choose-money app-item">
  63. <text>总计金额</text>
  64. <text>¥{{ ' ' + choosedPrice + ' .00' }}元</text>
  65. </view>
  66. </view>
  67. <flyto-cart v-if="s" ref="flytoCart1" :self="positions.s" :cart="positions.shopcar"><text>{{ s }}</text></flyto-cart>
  68. <flyto-cart v-if="m" ref="flytoCart2" :self="positions.m" :cart="positions.shopcar"><text>{{ m }}</text></flyto-cart>
  69. <flyto-cart v-if="l" ref="flytoCart3" :self="positions.l" :cart="positions.shopcar"><text>{{ l }}</text></flyto-cart>
  70. <flyto-cart v-if="xl" ref="flytoCart4" :self="positions.xl" :cart="positions.shopcar"><text>{{ xl }}</text></flyto-cart>
  71. <flyto-cart v-if="xxl" ref="flytoCart5" :self="positions.xxl" :cart="positions.shopcar"><text>{{ xxl }}</text></flyto-cart>
  72. <flyto-cart v-if="xxxl" ref="flytoCart6" :self="positions.xxxl" :cart="positions.shopcar"><text>{{ xxxl }}</text></flyto-cart>
  73. </view>
  74. </template>
  75. <script>
  76. import { _API_GoodDetail } from '@/apis/good.js'
  77. import { deepClone, clearTypeListZeros } from '@/common/util/index.js'
  78. import flytoCart from '@/components/flytocart/fly-to-cart.vue'
  79. export default {
  80. components: {
  81. flytoCart
  82. },
  83. data() {
  84. return {
  85. title: '商品详情',
  86. flying: false,
  87. goodInfo: {},
  88. positions: { s: {}, m: {}, l: {}, xl: {}, xxl: {}, xxxl: {}, shopcar: {} }
  89. }
  90. },
  91. computed: {
  92. s() { return this.$store.getters['choosed/S'] }, // 已选择 s 数量
  93. m() { return this.$store.getters['choosed/M'] }, // 已选择 m 数量
  94. l() { return this.$store.getters['choosed/L'] }, // 已选择 l 数量
  95. xl() { return this.$store.getters['choosed/XL'] }, // 已选择 xl 数量
  96. xxl() { return this.$store.getters['choosed/XXL'] }, // 已选择 xxl 数量
  97. xxxl() { return this.$store.getters['choosed/XXXL'] }, // 已选择 xxxl 数量
  98. choosedList() { return this.$store.state.choosed.list }, // 已选类型列表
  99. choosedNum() { return this.$store.getters['choosed/total'] }, // 已选择 总 数量
  100. choosedPrice() { return this.choosedNum * (this.goodInfo.price || 0) }, // 已选择 总 价值
  101. shopcarNum() { return this.$store.getters['shopcar/shopcarNum'] } // 购车车商品数量
  102. },
  103. created() { // 页面初始化后清除已选择的尺寸
  104. this.$store.commit('choosed/CLEAR')
  105. },
  106. onShow() {
  107. this.$nextTick(() =>{ // 页面显示后获取 尺寸按钮 的位置
  108. this.getSizePositons()
  109. })
  110. },
  111. onLoad(opt) { // 进入页面后获取商品 ID (发送网络请求)
  112. _API_GoodDetail({ id: opt.id }).then(res => {
  113. this.goodInfo = res.data
  114. this.goodInfo.storage = opt.storage
  115. })
  116. },
  117. methods: {
  118. buy() {
  119. if (this.choosedNum) { // 点击立即购买
  120. const choosed = deepClone(this.choosedList) // 克隆已选列表,不改变原数据,防止用户点击立即购买后直接返回造成数据不可逆
  121. clearTypeListZeros(choosed) // 清除数量为 0 的 typeListItem
  122. uni.navigateTo({ url: `../confirm-order/confirm-order?from=gooddetail&order=${JSON.stringify([{ ...this.goodInfo, typeList: choosed }])}` })
  123. } else {
  124. uni.toast('您还没有选择尺寸')
  125. }
  126. },
  127. addToshopCar(e) { // 点击加入购物车
  128. if (this.choosedNum) {
  129. if (!this.flying) { // 防止连点
  130. this.$refs.flytoCart1 ? this.$refs.flytoCart1.fly() : '' // 飞入购物车
  131. this.$refs.flytoCart2 ? this.$refs.flytoCart2.fly() : '' // 飞入购物车
  132. this.$refs.flytoCart3 ? this.$refs.flytoCart3.fly() : '' // 飞入购物车
  133. this.$refs.flytoCart4 ? this.$refs.flytoCart4.fly() : '' // 飞入购物车
  134. this.$refs.flytoCart5 ? this.$refs.flytoCart5.fly() : '' // 飞入购物车
  135. this.$refs.flytoCart6 ? this.$refs.flytoCart6.fly() : '' // 飞入购物车
  136. this.goodInfo.choosed = true // 该商品在购物车默认为选中状态
  137. clearTypeListZeros(this.choosedList) // 清除 数量为空的 type 和 size
  138. this.$store.commit('shopcar/ADD', { ...this.goodInfo, typeList: deepClone(this.choosedList) }) // 加入购物车<!一定要 deepClone!>
  139. this.flying = true
  140. setTimeout(() => {
  141. this.flying = false
  142. this.$store.commit('choosed/CLEAR') // 清除已选择的尺寸按钮
  143. }, 678)
  144. }
  145. } else {
  146. uni.toast('您还没有选择尺寸')
  147. }
  148. },
  149. getSizePositons() { // 获取尺寸按钮和购物车的位置信息
  150. this.$offset('#s').then(res => this.positions.s = res).catch(e => e)
  151. this.$offset('#m').then(res => this.positions.m = res).catch(e => e)
  152. this.$offset('#l').then(res => this.positions.l = res).catch(e => e)
  153. this.$offset('#xl').then(res => this.positions.xl = res).catch(e => e)
  154. this.$offset('#xxl').then(res => this.positions.xxl = res).catch(e => e)
  155. this.$offset('#xxxl').then(res => this.positions.xxxl = res).catch(e => e)
  156. this.$offset('#shopcar').then(res => this.positions.shopcar = res).catch(e => e)
  157. }
  158. },
  159. onBackPress(opt) {
  160. if (this.choosedNum && opt.from === 'backbutton') {
  161. this.$refs.ltm.modal('提示', ['离开页面将不会保存您选择的尺寸']).then(() => {
  162. uni.navigateBack()
  163. })
  164. return true
  165. } else {
  166. return false
  167. }
  168. }
  169. }
  170. </script>
  171. <style lang="scss">
  172. .good-detail {
  173. @include page();
  174. .shopcar-buy {
  175. @include flex();
  176. left: 0;
  177. right: 0;
  178. bottom: 0;
  179. z-index: 1;
  180. height: 98rpx;
  181. position: fixed;
  182. view, navigator {
  183. @include flex();
  184. flex: 1;
  185. height: 100%;
  186. color: #FFFFFF;
  187. font-size: 32rpx;
  188. position: relative;
  189. &.shopcar {
  190. background: #FFFFFF;
  191. color: $app-base-color;
  192. .cuIcon-cart {
  193. font-size: 40rpx;
  194. margin-right: 6rpx;
  195. }
  196. .num {
  197. @include flex();
  198. top: 12rpx;
  199. right: 20rpx;
  200. height: 34rpx;
  201. min-width: 34rpx;
  202. padding: 0 8rpx;
  203. color: #FFFFFF;
  204. min-width: 34rpx;
  205. font-size: 20rpx;
  206. position: absolute;
  207. border-radius: 16rpx;
  208. background: $app-base-color;
  209. }
  210. }
  211. &.addshopcar {
  212. background: #FFA94C;
  213. }
  214. &.buy {
  215. background: $app-base-color;
  216. }
  217. }
  218. }
  219. .content {
  220. swiper {
  221. height: 400rpx;
  222. image {
  223. width: 100%;
  224. height: 100%;
  225. }
  226. }
  227. .app-item {
  228. font-size: 26rpx;
  229. }
  230. .goodinfo {
  231. height: 134rpx;
  232. flex-direction: column;
  233. align-items: flex-start;
  234. justify-content: flex-start;
  235. .name {
  236. font-size: 32rpx;
  237. margin-top: 30rpx;
  238. }
  239. .price-storage {
  240. margin-top: 12rpx;
  241. .price {
  242. color: $app-base-color;
  243. }
  244. .storage {
  245. margin-left: 30rpx;
  246. color: $app-sec-text-color;
  247. }
  248. }
  249. }
  250. .choose-size {
  251. .size-right {
  252. @include flex();
  253. flex: 1;
  254. margin-left: 30rpx;
  255. height: $app-item-height;
  256. justify-content: space-between;
  257. .size {
  258. @include flex();
  259. flex: 1;
  260. height: 100%;
  261. justify-content: flex-end;
  262. view {
  263. @include flex();
  264. position: relative;
  265. width: 68rpx;
  266. height: 44rpx;
  267. font-size: 26rpx;
  268. margin-right: 18rpx;
  269. border-radius: 4rpx;
  270. border: 2rpx solid $app-main-text-color;
  271. .num {
  272. @include flex();
  273. top: -10rpx;
  274. width: 30rpx;
  275. height: 30rpx;
  276. right: -10rpx;
  277. color: #FFFFFF;
  278. font-size: 18rpx;
  279. position: absolute;
  280. border-radius: 50%;
  281. background: $app-base-color;
  282. }
  283. }
  284. }
  285. }
  286. }
  287. .choose-money, .freight {
  288. text:nth-child(2) {
  289. color: $app-base-color;
  290. }
  291. }
  292. // .address {
  293. // .default-address {
  294. // @include flex();
  295. // flex: 1;
  296. // font-size: 26rpx;
  297. // margin-left: 30rpx;
  298. // height: $app-item-height;
  299. // justify-content: space-between;
  300. // .cuIcon-location {
  301. // width: 32rpx;
  302. // color: $app-base-color;
  303. // }
  304. // .addressText {
  305. // width: 500rpx;
  306. // height: 100%;
  307. // overflow: hidden;
  308. // white-space: nowrap;
  309. // text-overflow: ellipsis;
  310. // line-height: $app-item-height;
  311. // }
  312. // .cuIcon-right {
  313. // width: 32rpx;
  314. // font-size: 32rpx;
  315. // }
  316. // }
  317. // }
  318. }
  319. flyto-cart {
  320. text {
  321. font-size: 18rpx;
  322. }
  323. }
  324. }
  325. </style>