ATFSpecificationScreen.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <template>
  2. <view class="specification-screen-container">
  3. <tui-landscape
  4. :show="showSpecification" :position="1" :mask-closable="true" icon-left="50rpx"
  5. icon-right="50rpx"
  6. @close="showSpecification = false"
  7. >
  8. <view
  9. style="position: relative;width: 600upx;max-height: 75vh;padding: 46upx 46upx 0;box-sizing: border-box;overflow-y: auto;background-color: #ffffff;border-radius: 40upx;"
  10. >
  11. <view v-if="selectedSku" style="display: flex;align-items: center;">
  12. <image
  13. style="width: 180upx;height: 180upx;"
  14. :src="common.seamingImgUrl(selectedSku.image || (goodsDetail.images && goodsDetail.images[0]))" mode=""
  15. />
  16. <view
  17. style="flex: 1;margin-left: 40upx;word-break: break-all;display: -webkit-box;overflow: hidden;-webkit-box-orient: vertical;-webkit-line-clamp: 2;"
  18. >
  19. <text style="font-size: 34upx;font-weight: bold;">{{ goodsDetail.productName }}</text>
  20. </view>
  21. </view>
  22. <view v-if="goodsDetail.names">
  23. <view v-for="item in goodsDetail.names" :key="item.nameCode" style="margin-top: 20upx;">
  24. <view v-if="item.nameCode" style="font-size: 26upx;color: #a5a4a4;">{{ item.skuName }}</view>
  25. <view style="display: flex;flex-wrap: wrap;margin-top: 10upx;font-size: 28upx;">
  26. <view
  27. v-for="tag in item.values" :key="tag.id"
  28. style="width: fit-content;padding: 6upx 28upx;margin-right: 20upx;border-radius: 20upx;" :style="{
  29. border: selectedAttr[item.nameCode] == tag.valueCode ? '1upx solid #ffbd87' : '1upx solid #c2c2c2',
  30. backgroundColor: selectedAttr[item.nameCode] == tag.valueCode ? '#fffce3' : 'transparent'
  31. }" @click="handleClickSkuItem(item.nameCode, tag.valueCode)"
  32. >
  33. {{ tag.skuValue }}
  34. </view>
  35. </view>
  36. </view>
  37. </view>
  38. <view style="display: flex;justify-content: space-between;align-items: center;margin-top: 20upx;">
  39. <view>数量</view>
  40. <view>
  41. <uni-number-box v-model="number" :min="1" :max="maxNumber"></uni-number-box>
  42. </view>
  43. </view>
  44. <view style="position: sticky;bottom: 0;margin-top: 40upx;padding-bottom: 20upx;background-color: #ffffff;">
  45. <view style="padding: 12upx 46upx;margin: 0 -46upx;font-size: 28upx;color: #868686;background-color: #efefef;">
  46. <text>已选规格:</text>
  47. <text>{{ spStr }}</text>
  48. </view>
  49. <view style="display: flex;justify-content: space-between;align-items: center;margin-top: 20upx;">
  50. <view>
  51. <view v-if="selectedSku">
  52. <text style="font-size: 28upx;">总计</text>
  53. <text style="margin-left: 10upx;font-size: 38upx;color: #ff0505;">¥{{ selectedSku.price * number }}</text>
  54. </view>
  55. </view>
  56. <view>
  57. <view v-if="!showSelectBtn">
  58. <tui-button
  59. type="danger" width="240rpx" height="64rpx" margin="0 10rpx 0 0"
  60. style="border-radius: 14rpx;"
  61. @click="addShopCar"
  62. >
  63. {{ btnText || '+ 加入购物车' }}
  64. </tui-button>
  65. </view>
  66. <view v-else>
  67. <tui-button
  68. type="danger" width="240rpx" height="64rpx" margin="0 10rpx 0 0"
  69. style="border-radius: 14rpx;"
  70. @click="handleClickBtn"
  71. >
  72. {{ btnText }}
  73. </tui-button>
  74. </view>
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. </tui-landscape>
  80. <tui-toast ref="toast"></tui-toast>
  81. </view>
  82. </template>
  83. <script>
  84. import { getProductDetailsByIdApi, addCartShoppingApi } from '../../api/anotherTFInterface'
  85. export default {
  86. name: 'ATFSpecificationScreen',
  87. props: {
  88. data: {
  89. type: Object
  90. },
  91. maxNumber: {
  92. type: Number,
  93. default: 100
  94. },
  95. showSelectBtn: {
  96. type: Boolean,
  97. default: false
  98. },
  99. showSuccessToast: {
  100. type: Boolean,
  101. default: true
  102. },
  103. btnText: {
  104. type: String,
  105. default: ''
  106. }
  107. },
  108. data() {
  109. return {
  110. showSpecification: false,
  111. goodsDetail: {},
  112. selectedAttr: {},
  113. spStr: '请选择商品规格',
  114. selectedSku: { collageOrders: [] },
  115. currentSku: [],
  116. number: 1
  117. }
  118. },
  119. watch: {
  120. number() {
  121. this.getCurrentSkuName()
  122. }
  123. },
  124. methods: {
  125. async open(shopId, productId, skuId) {
  126. uni.showLoading()
  127. this.goodsDetail = {}
  128. this.spStr = '请选择商品规格'
  129. this.selectedSku = {}
  130. this.currentSku = []
  131. this.number = 1
  132. let data
  133. if (this.data && this.data.info) {
  134. data = this.data
  135. } else {
  136. const res = await getProductDetailsByIdApi({
  137. shopId,
  138. productId,
  139. skuId,
  140. terminal: 1
  141. })
  142. data = res.data
  143. }
  144. uni.hideLoading()
  145. this.goodsDetail = data
  146. console.log(data)
  147. const skuCollectionListKeys = Object.keys(this.goodsDetail.map)
  148. if ((skuCollectionListKeys.length === 1) && (skuCollectionListKeys[0] === '单款项')) {
  149. this.goodsDetail.names[0].values.push({
  150. skuValue: this.goodsDetail.names[0].skuName,
  151. valueCode: '单款项'
  152. })
  153. }
  154. skuCollectionListKeys.forEach((allSkuValueCodeMap) => {
  155. if (!this.goodsDetail.map[allSkuValueCodeMap].image) this.goodsDetail.map[allSkuValueCodeMap].image = this.goodsDetail.images[0]
  156. })
  157. this.$nextTick(() => {
  158. if (skuId) {
  159. this.handleSelectBySkuId(skuId)
  160. } else {
  161. // 默认选中第0个
  162. this.goodsDetail.names.forEach((skuRowItem) => {
  163. this.handleClickSkuItem(skuRowItem.nameCode, skuRowItem.values[0].valueCode)
  164. })
  165. }
  166. })
  167. this.showSpecification = true
  168. },
  169. handleSelectBySkuId(skuId) {
  170. if (!skuId) return
  171. Object.keys(this.goodsDetail.map).forEach((allSkuValueCodeMap) => {
  172. if (this.goodsDetail.map[allSkuValueCodeMap].skuId === skuId) {
  173. this.selectedSku = this.goodsDetail.map[allSkuValueCodeMap]
  174. this.getCurrentSkuName()
  175. this.goodsDetail.names.forEach((skuRow) => {
  176. skuRow.values.some((skuCol) => {
  177. if (this.selectedSku.valueCodes.split(',').includes(skuCol.valueCode)) {
  178. this.$set(this.selectedAttr, skuRow.nameCode, skuCol.valueCode)
  179. return true
  180. }
  181. return false
  182. })
  183. })
  184. }
  185. })
  186. },
  187. handleClickSkuItem(nameCode, valueCode) {
  188. this.$set(this.selectedAttr, nameCode, valueCode)
  189. Object.keys(this.goodsDetail.map).forEach((allSkuValueCodeMap) => {
  190. if (Object.values(this.selectedAttr).join(',') === allSkuValueCodeMap) {
  191. this.selectedSku = this.goodsDetail.map[allSkuValueCodeMap]
  192. this.getCurrentSkuName()
  193. }
  194. })
  195. },
  196. // 获取选择后的文本显示
  197. getCurrentSkuName() {
  198. if (this.selectedSku.valueCodes) {
  199. let str = ''
  200. const currentSku = []
  201. this.goodsDetail.names.forEach((skuRow) => {
  202. skuRow.values.some((skuValue) => {
  203. if (this.selectedSku.valueCodes.split(',').includes(skuValue.valueCode)) {
  204. if (skuValue.valueCode === '单款项') {
  205. currentSku.push({ skuText: skuValue.skuValue })
  206. } else {
  207. currentSku.push({ skuText: `${skuValue.skuName}:${skuValue.skuValue}` })
  208. }
  209. str += skuValue.skuValue + ','
  210. return true
  211. }
  212. return false
  213. })
  214. })
  215. this.spStr = str + this.number + '(数量)'
  216. return currentSku
  217. }
  218. return []
  219. },
  220. // 添加购物车
  221. async addShopCar() {
  222. if (this.isLogin()) {
  223. try {
  224. if (this.showSpecification) {
  225. const tempGoodsInfo = {
  226. selectedSku: this.selectedSku,
  227. currentSku: this.currentSku,
  228. number: this.number
  229. }
  230. if (tempGoodsInfo.number > this.selectedSku.stockNumber) {
  231. this.$showToast('该货品库存为' + this.selectedSku.stockNumber)
  232. return
  233. }
  234. if (tempGoodsInfo.selectedSku.skuId) {
  235. uni.showLoading()
  236. addCartShoppingApi({
  237. skuId: this.selectedSku.skuId,
  238. number: this.number
  239. })
  240. .then((res) => {
  241. uni.hideLoading()
  242. if (this.showSuccessToast) this.ttoast('购物车添加成功')
  243. this.showSpecification = false
  244. this.$emit('success')
  245. })
  246. .catch((e) => {
  247. uni.hideLoading()
  248. })
  249. } else {
  250. this.$showToast('商品参数出错,无法添加!')
  251. }
  252. } else {
  253. this.$showToast('请先开启规格弹窗显示')
  254. }
  255. } catch (error) {
  256. console.log(error)
  257. }
  258. } else {
  259. this.$showToast('未登录')
  260. }
  261. },
  262. // 选择
  263. handleClickBtn() {
  264. if (this.showSpecification) {
  265. const tempGoodsInfo = {
  266. selectedSku: this.selectedSku,
  267. currentSku: this.currentSku,
  268. number: this.number
  269. }
  270. if (tempGoodsInfo.number > tempGoodsInfo.selectedSku.stockNumber) {
  271. this.$showToast('该货品库存为' + tempGoodsInfo.selectedSku.stockNumber)
  272. return
  273. }
  274. if (tempGoodsInfo.selectedSku.skuId) {
  275. this.$emit('select', tempGoodsInfo)
  276. this.showSpecification = false
  277. } else {
  278. this.$showToast('商品参数出错!')
  279. }
  280. } else {
  281. this.$showToast('请先开启规格弹窗显示')
  282. }
  283. }
  284. }
  285. }
  286. </script>
  287. <style lang="less" scoped>
  288. .specification-screen-container {
  289. }
  290. </style>