index.tsx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. import { moneyFormat } from '@/helpers/utils'
  2. import {
  3. Button,
  4. Cell,
  5. Dialog,
  6. Image,
  7. Loading,
  8. Radio,
  9. RadioGroup,
  10. Stepper,
  11. Tag,
  12. Toast
  13. } from 'vant'
  14. import { defineComponent, PropType } from 'vue'
  15. import styles from './index.module.less'
  16. import iconSellOut from '../../images/icon-sell-out.png'
  17. import request from '@/helpers/request'
  18. export default defineComponent({
  19. name: 'add-goods-cart',
  20. props: {
  21. show: {
  22. type: Boolean,
  23. default: false,
  24. },
  25. item: {
  26. type: Object,
  27. default: {}
  28. },
  29. defaultRadio: {
  30. type: Number,
  31. default: 0
  32. },
  33. showType: {
  34. type: String,
  35. default: 'cart'
  36. },
  37. onGetCartCount: {
  38. type: Function,
  39. default: (n: any) => {}
  40. }
  41. },
  42. watch:{
  43. show(val){ // 添加购物车显示
  44. if (val){
  45. this.totalData = {}
  46. this.total = 1
  47. this.radio = ''
  48. this.setList()
  49. }
  50. }
  51. },
  52. data() {
  53. return {
  54. radio: '',
  55. total: 1,
  56. totalData: {},
  57. skuStockList: []
  58. }
  59. },
  60. computed: {
  61. selectItem() {
  62. const radio = this.radio
  63. const select = this.skuStockList.find((n: any) => n.id == radio) as any
  64. if (select) {
  65. let stock : number = select.stock - select.lockStock - select.cartNum
  66. return {
  67. ...select,
  68. stock
  69. }
  70. }
  71. return {
  72. stock: 0
  73. }
  74. }
  75. },
  76. mounted(){
  77. this.setList()
  78. },
  79. methods: {
  80. setList(){
  81. // 处理规格
  82. let skuStockList = [] as any
  83. const item = JSON.parse(JSON.stringify(this.item))
  84. if (Array.isArray(item.skuStockList)) {
  85. skuStockList = item.skuStockList.map((n: any) => {
  86. n.pic = n.pic || item.pic
  87. n.cartNum = 0
  88. if (n.spData) {
  89. const spData = JSON.parse(n.spData)
  90. let str = ''
  91. spData.forEach((sp: any) => {
  92. str += `${sp.value}`
  93. })
  94. n.spDataJson = str
  95. } else {
  96. n.spDataJson = '默认'
  97. }
  98. n.lockStock = n.lockStock > 0 ? n.lockStock : 0
  99. return {
  100. ...n
  101. }
  102. })
  103. }
  104. if (!skuStockList.length) return skuStockList
  105. // 处理默认显示
  106. let index = 0
  107. if (this.defaultRadio) {
  108. let i = skuStockList.findIndex(n => n.id == this.defaultRadio)
  109. index = i > -1 ? i : 0
  110. }
  111. this.radio = skuStockList[index].id
  112. this.skuStockList = skuStockList
  113. this.getProductAddCartCount(skuStockList[index].id)
  114. },
  115. async onAddCart() {
  116. const selectItem = this.selectItem
  117. const item = this.item
  118. const body = {
  119. price: selectItem.price, //添加到购物车的价格
  120. productSkuId: selectItem.id,
  121. quantity: this.total, // 数量
  122. productId: item.id,
  123. hidden: this.showType === 'cart' ? 0 : 1,
  124. promoterId: this.$route.query.promoterId ? this.$route.query.promoterId : undefined
  125. }
  126. // console.log(body)
  127. try {
  128. let { code, data } = await request.post('/api-mall-portal/cart/add', {
  129. data: body
  130. })
  131. if (code === 200) {
  132. // this.getProductAddCartCount(selectItem.id, true)
  133. if (this.showType === 'cart') {
  134. this.onGetCartCount()
  135. this.$nextTick(() => {
  136. setTimeout(() => {
  137. Toast({
  138. icon: 'success',
  139. message: '添加商品成功'
  140. })
  141. }, 500)
  142. })
  143. } else {
  144. this.$router.push({
  145. path: '/cartConfirm',
  146. query: {
  147. cartIds: data.id
  148. }
  149. })
  150. }
  151. }
  152. } catch (error) {
  153. let msg : string = (error as any).message
  154. if (msg === "库存不足") {
  155. for(let i = 0; i < this.skuStockList.length; i++){
  156. if ((this.skuStockList[i] as any).id === this.selectItem.id){
  157. (this.skuStockList[i] as any).stock = 0
  158. }
  159. }
  160. }
  161. }
  162. },
  163. // 获取购物车当前产品的数量
  164. async getProductAddCartCount(id?: any, isRest = false) {
  165. id = id ? id : this.selectItem.id
  166. if (this.totalData.hasOwnProperty(id) && !isRest) {
  167. this.setProductStock(this.totalData[id])
  168. return
  169. }
  170. if (!id) return
  171. try {
  172. let res = await request.get(`/api-mall-portal/product/cart/${id}`)
  173. this.setProductStock(res.data || 0)
  174. this.totalData[id] = res.data || 0
  175. } catch (err) {}
  176. },
  177. // 更新产品规格的库存
  178. setProductStock(n: number){
  179. // 根据当前用户的购物车,当前产品规格的数量,限制库存
  180. for(let i = 0; i < this.skuStockList.length; i++){
  181. if ((this.skuStockList[i] as any).id === this.radio) {
  182. (this.skuStockList[i] as any).cartNum = n
  183. }
  184. }
  185. }
  186. },
  187. render() {
  188. return (
  189. <div class={styles.addGoodsCart}>
  190. <Cell
  191. titleStyle={{ paddingLeft: '12px' }}
  192. v-slots={{
  193. icon: () => (
  194. <div class={styles.goodsSection}>
  195. <Image
  196. src={this.selectItem.pic}
  197. class={styles.goodsImg}
  198. fit="cover"
  199. />
  200. {this.selectItem.stock <= 0 && (
  201. <div class={styles.sellOut}>
  202. <Image
  203. src={iconSellOut}
  204. fit="cover"
  205. class={styles.sellOutImg}
  206. />
  207. </div>
  208. )}
  209. </div>
  210. ),
  211. title: () => (
  212. <div class={styles.goodsInfo}>
  213. <p class={styles.goodsPrice}>
  214. <span>¥</span>
  215. {moneyFormat(this.selectItem.price)}
  216. </p>
  217. <p class={styles.goodsStore}>库存:{this.selectItem.stock}</p>
  218. </div>
  219. )
  220. }}
  221. />
  222. <Cell
  223. v-slots={{
  224. title: () => <div class={styles.title}>规格</div>,
  225. label: () => (
  226. <RadioGroup class={styles['radio-group']} modelValue={this.radio}>
  227. {this.skuStockList.map((item: any) => {
  228. const isActive = item.id === this.radio
  229. const type = isActive ? 'primary' : 'default'
  230. return (
  231. <Radio
  232. class={styles.radio}
  233. name={item.id}
  234. onClick={() => {
  235. if (this.radio == item.id) return
  236. this.radio = item.id
  237. this.getProductAddCartCount(item.id)
  238. }}
  239. >
  240. <Tag size="large" plain={isActive} type={type}>
  241. {item.spDataJson}
  242. </Tag>
  243. </Radio>
  244. )
  245. })}
  246. </RadioGroup>
  247. )
  248. }}
  249. />
  250. <Cell
  251. title="购买数量"
  252. style={{ margin: '12px 0' }}
  253. border={false}
  254. titleClass={styles.title}
  255. center
  256. >
  257. <Stepper
  258. v-model={this.total}
  259. inputWidth="50px"
  260. theme="round"
  261. buttonSize="24px"
  262. max={this.selectItem.stock > 200 ? 200 : this.selectItem.stock}
  263. min={1}
  264. disabled={this.selectItem.stock <= 0}
  265. integer
  266. />
  267. </Cell>
  268. <div class={['btnGroup']} style={{ marginBottom: '8px' }}>
  269. <Button
  270. block
  271. round
  272. type="primary"
  273. text="确定"
  274. disabled={this.selectItem.stock <= 0}
  275. onClick={() => this.onAddCart()}
  276. />
  277. </div>
  278. </div>
  279. )
  280. }
  281. })