index.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <view class="detail">
  3. <!-- header -->
  4. <cu-custom isBack custom bgColor="bg-gradual-blue"><view slot="content">商品详情</view></cu-custom>
  5. <!-- section -->
  6. <view class="section">
  7. <cu-swiper :value="swiperList" />
  8. <view class="bg-white padding">
  9. <view class="flex align-center ">
  10. <view style="flex: auto;">
  11. <view class="text-xl text-bold">{{ detail.name }}</view>
  12. <view class="text-price text-red"><cu-price :value="detail.price" size="64" /></view>
  13. </view>
  14. <view @click="favoriteFunc" style="min-width: 80upx;" class="text-right">
  15. <text v-if="dynamic.favorite" class="cuIcon-likefill text-red text-xxl"></text>
  16. <text v-else class="cuIcon-like text-xxl"></text>
  17. </view>
  18. </view>
  19. <view class="flex justify-between align-end margin-top-sm">
  20. <view class="bg-orange light padding-lr-xs">
  21. <text class="cuIcon-vip lg">会员价</text>
  22. <text class="text-price margin-left-xs">{{ detail.vip_price }}</text>
  23. </view>
  24. <view class="">
  25. {{detail.point_price}}积分
  26. </view>
  27. <view class="text-grey">已售{{ detail.sale_count }}件</view>
  28. </view>
  29. </view>
  30. <view v-if="Object.keys(addressValue).length>0" @click="addressListFunc" class="margin-tb-sm padding bg-white flex">
  31. <view style="min-width: 100upx;" class="text-black text-bold">配送至</view>
  32. <view style="flex: auto;">
  33. <view class="text-grey">
  34. {{addressValue.province}}{{addressValue.city}}{{addressValue.area}}{{addressValue.address}}
  35. <text class="cuIcon-location lg margin-left-sm"></text>
  36. </view>
  37. <view class="">{{addressValue.name}} {{addressValue.tel}}</view>
  38. </view>
  39. </view>
  40. <view class="padding margin-tb-sm bg-white">
  41. <view class="flex justify-between">
  42. <view class="text-bold text-black text-bold">评价(265)</view>
  43. <view @click="evaluateFunc">
  44. 查看全部
  45. <text class="cuIcon-right"></text>
  46. </view>
  47. </view>
  48. <cu-evaluate :value="evaluate" />
  49. </view>
  50. <view class="bg-white padding-tb">
  51. <view class="text-black text-bold margin-bottom-sm padding-lr">图文介绍</view>
  52. <image
  53. v-for="(item, index) in detailList"
  54. :key="index"
  55. lazy-load="true"
  56. style="width: 100%;vertical-align: top;display: block;"
  57. :src="item"
  58. mode="widthFix"
  59. ></image>
  60. </view>
  61. </view>
  62. <!-- footer -->
  63. <view class="footer">
  64. <view class=" cu-bar bg-white tabbar border shop">
  65. <button open-type="share" class="action ">
  66. <view class="cuIcon-share"></view>
  67. 分享
  68. </button>
  69. <view @click="favoriteFunc" v-if="dynamic.favorite" class="action text-orange">
  70. <view class="cuIcon-favorfill"></view>
  71. 已收藏
  72. </view>
  73. <view @click="favoriteFunc" v-else class="action ">
  74. <view class="cuIcon-favor"></view>
  75. 收藏
  76. </view>
  77. <view @click="shoppingCart" class="action">
  78. <view class="cuIcon-cart"></view>
  79. 购物车
  80. </view>
  81. <view class="btn-group">
  82. <button @click="show=true" :disabled="bind != 1" class="cu-btn bg-orange round shadow-blur">
  83. 添加购买
  84. </button>
  85. </view>
  86. </view>
  87. </view>
  88. <!-- 工具 -->
  89. <cu-goodA :value="value" @addcart="addcart" @buyclicked="buyclicked" :number="number" @changeNum="val=>number=val" :show.sync="show" />
  90. </view>
  91. </template>
  92. <script>
  93. import api from './api.js';
  94. import { mapState, mapActions } from 'vuex';
  95. export default {
  96. computed: {
  97. ...mapState(['bind']),
  98. ...mapState('addressDefault', ['addressValue']),
  99. value(){
  100. let {name,price,show_image,point_price,type}=this.detail;
  101. return {
  102. name,price,img:show_image,point_price,type
  103. }
  104. }
  105. },
  106. data() {
  107. return {
  108. number:1,
  109. show: false,
  110. detail: {},
  111. // 动态操作
  112. dynamic: { favorite: false },
  113. swiperList: [],
  114. detailList: [],
  115. evaluate: {
  116. avator: 'https://gd-hbimg.huaban.com/1f50f2135ba51e4b9aa20caef41860b15005c9386f0b-LxqWsh_fw658/format/webp',
  117. nickname: '用户昵称',
  118. rate: 3,
  119. createTime: '20220622 17:05:30',
  120. detail: "项目 'demo' 编译成功。前端运行日志,请另行在小程序开发工具的控制台查看。",
  121. imgs: [
  122. {
  123. id: 0,
  124. type: 'video',
  125. url: 'https://st0.dancf.com/gaoding/gaoding/229e7928-fb34-4a0c-b12b-b26fc0aba91453332268.mp4'
  126. },
  127. {
  128. id: 1,
  129. type: 'image',
  130. url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84001.jpg'
  131. },
  132. {
  133. id: 2,
  134. type: 'image',
  135. url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg'
  136. },
  137. {
  138. id: 3,
  139. type: 'image',
  140. url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg'
  141. },
  142. {
  143. id: 4,
  144. type: 'image',
  145. url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big25011.jpg'
  146. },
  147. {
  148. id: 5,
  149. type: 'image',
  150. url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big21016.jpg'
  151. },
  152. {
  153. id: 6,
  154. type: 'image',
  155. url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg'
  156. }
  157. ]
  158. }
  159. };
  160. },
  161. async onShow(){
  162. if(this.bind==1) await this.requestFunc();
  163. },
  164. async onLoad(options) {
  165. var result = await api.detail(options);
  166. if (result.code != 0) return false;
  167. let { carousel_urls, details_urls, is_collection, ...keys } = result.data;
  168. // 轮播
  169. this.swiperList = carousel_urls.map(item => ({ type: 'image', url: item }));
  170. // 收藏
  171. let dynamic = {};
  172. dynamic['favorite'] = is_collection;
  173. this.dynamic = dynamic;
  174. // 详情
  175. this.detail = keys;
  176. // 图文详情
  177. this.detailList = details_urls;
  178. },
  179. methods: {
  180. ...mapActions('addressDefault', ['requestFunc']),
  181. addressListFunc(){
  182. uni.navigateTo({
  183. url:"/loginPages/addressList/index"
  184. })
  185. },
  186. // 添加购物车
  187. async addcart(){
  188. var result= await api.shoppingCart({quantity:this.number,commodity_details:this.detail.id});
  189. if(result.code==0){
  190. uni.showToast({
  191. title:"添加成功",
  192. icon:'success'
  193. })
  194. }
  195. },
  196. async buyclicked(){
  197. let arr=[{...this.detail,count:this.number,img:this.detail.show_image}];
  198. this.show=false;
  199. uni.navigateTo({
  200. url:`/indexPages/pay/index?list=${JSON.stringify(arr)}`
  201. })
  202. },
  203. async favoriteFunc() {
  204. if (this.bind != 1) {
  205. uni.switchTab({
  206. url:"/pages/login/index?status=true"
  207. })
  208. return false;
  209. }
  210. let dynamic = JSON.parse(JSON.stringify(this.dynamic));
  211. dynamic['favorite'] = !dynamic.favorite;
  212. let result;
  213. if (dynamic['favorite']) {
  214. result = await api.favorite({ id: this.detail.id });
  215. } else {
  216. result = await api.unfavorite({ id: this.detail.id });
  217. }
  218. if (result.code != 0) return false;
  219. this.dynamic = dynamic;
  220. },
  221. shoppingCart() {
  222. uni.switchTab({
  223. url: '/pages/shoppingCart/index'
  224. });
  225. },
  226. evaluateFunc() {
  227. uni.navigateTo({
  228. url: '/detailPages/evaluate/index'
  229. });
  230. }
  231. },
  232. onShareAppMessage() {
  233. let {id,name,show_img}=this.detail;
  234. return {
  235. title: name,
  236. imageUrl: show_img,
  237. path: '/pages/detail/index?id='+id
  238. };
  239. },
  240. onShareTimeline() {
  241. return {};
  242. }
  243. };
  244. </script>
  245. <style lang="scss" scoped>
  246. .detail {
  247. .footer {
  248. height: calc(100rpx + env(safe-area-inset-bottom) / 2);
  249. padding-bottom: calc(env(safe-area-inset-bottom) / 2);
  250. .cu-bar {
  251. position: fixed;
  252. bottom: 0;
  253. left: 0;
  254. width: 100vw;
  255. }
  256. }
  257. }
  258. </style>