ProdInfo.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <template>
  2. <div class="prod-info">
  3. <!-- 轮播 -->
  4. <van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
  5. <van-swipe-item v-if="prodData.imgs" v-for="(img, index) in prodData.imgs " :key="index">
  6. <van-image alt="" :src="img" />
  7. </van-swipe-item>
  8. </van-swipe>
  9. <van-divider />
  10. <!-- 商品信息介绍 -->
  11. <div class="prod-title">
  12. <van-row>
  13. <van-col class="prod-title-name" span="18">
  14. {{ prodData.prodName }}
  15. </van-col>
  16. <van-col span="6" class="prod-title-icon">
  17. <div @click="addOrCancel">
  18. <van-icon v-if="!isCollection" name="like-o" size="20" />
  19. <van-icon v-if="isCollection" style="color:red" name="like" size="20" />
  20. <span> 收藏</span>
  21. </div>
  22. </van-col>
  23. </van-row>
  24. <van-row>
  25. <van-col span="20" class="prod-title-brief">
  26. {{ prodData.brief }}
  27. </van-col>
  28. <van-col span="4" class="prod-title-icon">
  29. </van-col>
  30. </van-row>
  31. <van-row>
  32. <van-col class="prod-title-name prod-title-price" span="20">
  33. ¥<span class="title-price">{{ prodData.price }}</span>
  34. </van-col>
  35. <van-col span="4" class="prod-title-icon">
  36. </van-col>
  37. </van-row>
  38. </div>
  39. <!-- 分割线 -->
  40. <van-divider :style="{ border: '.5rem solid #ebedf0' }" />
  41. <!-- 类别 -->
  42. <div class="prod-categray" v-if="skuList.length > 0" @click="show = true">
  43. <span class="left">已选 </span> {{ defaultSku.skuName }} <span class="right">...</span>
  44. </div>
  45. <!-- 分割线 -->
  46. <van-divider :style="{ border: '.5rem solid #ebedf0', marginBottom: 0 }" />
  47. <!-- 评价信息 -->
  48. <van-cell title-style="cell-title" center value="共0条" is-link>
  49. <!-- 使用 title 插槽来自定义标题 -->
  50. <template #title>
  51. <span class="custom-title">评价: </span>
  52. <span>好评{{ commData.positiveRating }}%</span>
  53. </template>
  54. </van-cell>
  55. <van-grid :column-num="5" :border="false">
  56. <van-grid-item><van-tag type="warning">全部({{ commData.number }})</van-tag></van-grid-item>
  57. <van-grid-item><van-tag type="warning">好评({{ commData.praiseNumber }})</van-tag></van-grid-item>
  58. <van-grid-item><van-tag type="warning">中评({{ commData.secondaryNumber }})</van-tag></van-grid-item>
  59. <van-grid-item><van-tag type="warning">差评({{ commData.negativeNumber }})</van-tag></van-grid-item>
  60. <van-grid-item><van-tag type="warning">有图({{ commData.picNumber }})</van-tag></van-grid-item>
  61. </van-grid>
  62. <!-- 内容页 -->
  63. <div class="content" v-if="prodData.content" v-html="formatHtml(prodData.content)"></div>
  64. <!-- 购物提示框 -->
  65. <van-action-sheet v-model="showDesc">
  66. <div style="height: 1rem;"></div>
  67. <van-card :num="confirm.orderItem.prodCount" :price="defaultSku.price ? defaultSku.price : prodData.price"
  68. :desc="prodData.brief" :title="defaultSku.skuName ? defaultSku.skuName : prodData.prodName"
  69. :thumb="defaultSku.pic ? defaultSku.pic : prodData.pic">
  70. <template #tags>
  71. </template>
  72. <template #footer>
  73. <van-stepper v-model="confirm.orderItem.prodCount" integer />
  74. </template>
  75. </van-card>
  76. <div class="action-sheet-content">
  77. <div>
  78. <div v-for="(tag, idx) in tags" :key="idx">
  79. <div style="text-align: left;">
  80. {{ idx }}
  81. </div>
  82. <van-tag @click="selectTag(idx, t)"
  83. :class="{ 'prop-selected': selectedTag[idx] === t ? true : false }" plain
  84. v-for="(t, index) in tag" :key="index" type="danger">{{ t }}</van-tag>
  85. </div>
  86. </div>
  87. <div style="margin-top: 2rem;"></div>
  88. <div class="shopcart-button">
  89. <van-button class="left" :disabled="defaultSku.price ? false : true" type="danger"
  90. @click="shopcartAdd">加入购物车</van-button>
  91. <van-button class="right" :disabled="defaultSku.price ? false : true" type="danger"
  92. @click="buynow">立即购买</van-button>
  93. </div>
  94. </div>
  95. </van-action-sheet>
  96. <!-- 选择型号 -->
  97. <van-action-sheet v-model="show" title="选择产品类别">
  98. <div class="action-sheet-content">
  99. <div>
  100. <div v-for="(tag, idx) in tags" :key="idx">
  101. <div style="text-align: left;">
  102. {{ idx }}
  103. </div>
  104. <van-tag @click="selectTag(idx, t)"
  105. :class="{ 'prop-selected': selectedTag[idx] === t ? true : false }" plain
  106. v-for="(t, index) in tag" :key="index" type="danger">{{ t }}</van-tag>
  107. </div>
  108. </div>
  109. <div style="margin-top: 2rem;"></div>
  110. <van-button :disabled="defaultSku.skuName ? false : true" type="danger" block
  111. @click="show = false">确定</van-button>
  112. </div>
  113. </van-action-sheet>
  114. <van-goods-action>
  115. <van-goods-action-icon icon="cart-o" @click="$router.push('/shopCart')" text="购物车" />
  116. <van-goods-action-icon icon="shop-o" text="店铺" />
  117. <van-goods-action-button type="danger" text="立即购买" @click="showDesc = true" />
  118. </van-goods-action>
  119. <div style="height: 5rem;"> </div>
  120. </div>
  121. </template>
  122. <script>
  123. import { prodInfo, prodCommData, isCollection, changeItem, confirm, addOrCancel }
  124. from '../api/prodinfo'
  125. import { formatHtml } from '../utils/util'
  126. import { Toast } from 'vant'
  127. export default {
  128. data() {
  129. return {
  130. defaultSku: {},
  131. selectedTag: {},
  132. showDesc: false,
  133. prodData: {},
  134. skuList: [],
  135. transport: {},
  136. commData: {
  137. positiveRating: 0,
  138. number: 0,
  139. praiseNumber: 0,
  140. secondaryNumber: 0,
  141. negativeNumber: 0,
  142. picNumber: 0
  143. },
  144. isCollection: false,
  145. show: false,
  146. tags: {},
  147. confirm: {
  148. basketIds: [],
  149. orderItem: {
  150. prodId: 0,
  151. skuId: 0,
  152. prodCount: 1,
  153. shopId: 0,
  154. distributionCardNo: ""
  155. },
  156. addrId: 0,
  157. userChangeCoupon: 0,
  158. couponIds: []
  159. },
  160. shopcart: {
  161. basketId: 0,
  162. prodId: 0,
  163. skuId: 0,
  164. shopId: 0,
  165. count: 0,
  166. distributionCardNo: ""
  167. }
  168. }
  169. },
  170. created() {
  171. this.loadData()
  172. },
  173. methods: {
  174. async loadData() {
  175. const prod = await prodInfo({ prodId: this.$route.query.prodId })
  176. this.skuList = prod.skuList
  177. this.transport = prod.transport
  178. prod.imgs = prod.imgs.split(",")
  179. this.prodData = prod
  180. this.commData = await prodCommData({ prodId: prod.prodId })
  181. this.isCollection = await isCollection({ prodId: prod.prodId })
  182. this.init(this.skuList)
  183. },
  184. async addOrCancel() {
  185. await addOrCancel(this.prodData.prodId)
  186. this.isCollection = await isCollection({ prodId: this.prodData.prodId })
  187. },
  188. buynow() {
  189. this.confirm.orderItem.prodId = this.prodData.prodId
  190. this.confirm.orderItem.skuId = this.defaultSku.skuId
  191. this.confirm.orderItem.shopId = this.prodData.shopId
  192. this.confirm.orderItem.distributionCardNo = ""
  193. sessionStorage.setItem("confirm", JSON.stringify(this.confirm) )
  194. this.$router.push("/submitinfo")
  195. },
  196. shopcartAdd() {
  197. this.shopcart.basketId = 0
  198. this.shopcart.prodId = this.prodData.prodId
  199. this.shopcart.skuId = this.defaultSku.skuId
  200. this.shopcart.shopId = this.prodData.shopId
  201. this.shopcart.count = this.confirm.orderItem.prodCount
  202. changeItem(this.shopcart).then(r => {
  203. Toast("添加成功!")
  204. this.showDesc = false
  205. }).catch(e => {
  206. console.log(e)
  207. })
  208. },
  209. init(sku) {
  210. const properties = []
  211. const propObject = {}
  212. let defaultArr = []
  213. for (let i = 0; i < sku.length; i++) {
  214. properties.push(sku[i].properties)
  215. }
  216. for (let i = 0; i < properties.length; i++) {
  217. const propStr = properties[i]
  218. const propArr = propStr.split(";")
  219. if (defaultArr.length === 0) {
  220. defaultArr = propArr
  221. this.defaultSku = sku[i]
  222. if (sku.length === 1) return;
  223. }
  224. for (let n = 0; n < propArr.length; n++) {
  225. const valueStr = propArr[n];
  226. const valueArr = valueStr.split(":")
  227. if (!propObject[valueArr[0]]) {
  228. propObject[valueArr[0]] = new Set()
  229. }
  230. propObject[valueArr[0]].add(valueArr[1])
  231. }
  232. }
  233. this.tags = propObject
  234. for (let i = defaultArr.length - 1; i >= 0; i--) {
  235. const valueStr = defaultArr[i];
  236. const valueArr = valueStr.split(":")
  237. this.$set(this.selectedTag, valueArr[0], valueArr[1])
  238. }
  239. },
  240. selectTag(propTitle, Propvalue) {
  241. //当用户选择一个属性的时候, 我们存储他的选择
  242. this.$set(this.selectedTag, propTitle, Propvalue)
  243. //然后我们判断 用户选择的属性时候能找到对应的prop
  244. let str = ""
  245. for (let item in this.selectedTag) {
  246. str = item + ":" + this.selectedTag[item] + ";" + str
  247. }
  248. str = str.substring(0, str.length - 1)
  249. for (let i = 0; i < this.skuList.length; i++) {
  250. if (this.skuList[i].properties === str) {
  251. this.defaultSku = this.skuList[i]
  252. return;
  253. }
  254. }
  255. this.defaultSku = {}
  256. },
  257. formatHtml(t) {
  258. return formatHtml(t)
  259. }
  260. }
  261. }
  262. </script>
  263. <style scoped lang="less">
  264. .shopcart-button {
  265. .left {
  266. width: 50%;
  267. background-color: #595959;
  268. border: 1px solid #595959;
  269. }
  270. .right {
  271. width: 50%;
  272. }
  273. }
  274. .prop-selected {
  275. color: #FFF !important;
  276. background-color: red !important;
  277. }
  278. .prod-info /deep/ .van-tag {
  279. color: #ee0a24;
  280. margin-left: 1rem;
  281. padding: 0.3rem;
  282. }
  283. .prod-info /deep/ .action-sheet-content {
  284. padding: 1rem;
  285. }
  286. .prod-info /deep/ .van-card {
  287. background-color: #FFF;
  288. }
  289. .van-tag--warning {
  290. background-color: #ff976a;
  291. padding: 0.3rem;
  292. }
  293. .prod-info {
  294. padding: auto;
  295. .van-cell {
  296. .van-cell__title {
  297. text-align: left;
  298. }
  299. }
  300. .content {
  301. padding: 0%;
  302. }
  303. .prod-categray {
  304. height: 1rem;
  305. line-height: 1rem;
  306. text-align: left;
  307. padding-left: 1rem;
  308. font-weight: 700;
  309. .left {
  310. font-size: .9rem;
  311. color: grey;
  312. font-weight: 200;
  313. }
  314. .right {
  315. text-align: right;
  316. float: right;
  317. margin-right: 1rem;
  318. font-weight: 200;
  319. }
  320. }
  321. .prod-title {
  322. .prod-title-brief {
  323. height: 3rem;
  324. padding-left: 1rem;
  325. text-align: left;
  326. font-size: .6rem;
  327. color: #595959;
  328. }
  329. .prod-title-price {
  330. color: red;
  331. .title-price {
  332. font-size: 1.5rem;
  333. font-weight: 500;
  334. }
  335. }
  336. .prod-title-name {
  337. height: 3rem;
  338. padding-left: 1rem;
  339. text-align: left;
  340. }
  341. .prod-title-icon {
  342. height: 3rem;
  343. line-height: 3rem;
  344. padding-right: 1rem;
  345. }
  346. }
  347. }
  348. </style>