detail.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <template>
  2. <view class="bg-[var(--page-bg-color)] min-h-[100vh] overflow-hidden" :style="themeColor()" v-if="Object.keys(shopDetail).length">
  3. <view class="px-[var(--sidebar-m)] top-mar">
  4. <view class="card-template mb-[var(--top-m)]">
  5. <view class="flex items-center justify-between">
  6. <view class="flex items-center">
  7. <view class="w-[100rpx] h-[100rpx] overflow-hidden">
  8. <image v-if="shopDetail.icon" :src="img(shopDetail.icon)" class="w-[100rpx] h-[100rpx] rounded-full"></image>
  9. <image v-else :src="img('addon/mall/shop/shop_default.png')" class="w-[100rpx] h-[100rpx] rounded-full"></image>
  10. </view>
  11. <view class="ml-[20rpx]">
  12. <view class="flex items-center mb-[12rpx]">
  13. <text class="tag w-[60rpx] h-[32rpx] flex-center mr-[10rpx] text-[22rpx] text-[#802502] rounded-[6rpx]" v-if="shopDetail.is_self">自营</text>
  14. <text class="text-[30rpx] font-500">{{ shopDetail.site_name }}</text>
  15. </view>
  16. <view class="text-[24rpx] text-[var(--text-color-light9)]">
  17. {{shopDetail.follow_number}}人关注
  18. </view>
  19. </view>
  20. </view>
  21. <view>
  22. <view class="w-[130rpx] h-[54rpx] flex-center primary-btn-bg rounded-full" v-if="!isFollow" @click="collectShop(shopDetail.site_id,1)">
  23. <text class="nc-iconfont nc-icon-guanzhuV6xx text-[#fff] text-[26rpx]"></text>
  24. <text class="text-[22rpx] font-500 text-[#fff] ml-[6rpx]">关注</text>
  25. </view>
  26. <view v-else class="w-[130rpx] h-[54rpx] flex-center primary-btn-bg rounded-full">
  27. <text class="nc-iconfont nc-icon-xihuanV6mm text-[#fff] text-[26rpx]"></text>
  28. <text class="text-[22rpx] font-500 text-[#fff] ml-[6rpx]" @click="collectShop(shopDetail.site_id,0)">已关注</text>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. <view class="card-template mb-[var(--top-m)]">
  34. <view class="card-template-item justify-between" @click="storePic = true">
  35. <view class="text-[28rpx]">店铺资质</view>
  36. <view class="nc-iconfont nc-icon-gerenziliaoV6xx text-[40rpx]"></view>
  37. </view>
  38. <view class="card-template-item justify-between" @click="qrcode = true">
  39. <view class="text-[28rpx]">店铺二维码</view>
  40. <view class="nc-iconfont nc-icon-erweimaV6xx-1 text-[40rpx]"></view>
  41. </view>
  42. <view class="card-template-item justify-between" @click="call(shopDetail.phone)">
  43. <view class="text-[28rpx]">联系客服</view>
  44. <view class="nc-iconfont nc-icon-kefuV6xx-4 text-[40rpx]"></view>
  45. </view>
  46. </view>
  47. <view class="card-template mb-[var(--top-m)]">
  48. <view class="card-template-item justify-between !items-stretch">
  49. <view class="text-[28rpx] flex-shrink-0 mr-[20rpx]">店铺简介</view>
  50. <view class="text-[28rpx] text-right">{{shopDetail.desc }}</view>
  51. </view>
  52. <view class="card-template-item justify-between !items-stretch">
  53. <view class="text-[28rpx] flex-shrink-0 mr-[20rpx]">店铺地址</view>
  54. <view class="flex-1 flex items-center justify-end" @click="getAddress" v-if="shopDetail.full_address">
  55. <view class="text-[28rpx] text-right multi-hidden leading-[1.4]">{{shopDetail.full_address }}</view>
  56. <text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[30rpx] text-primary ml-[10rpx]"></text>
  57. </view>
  58. <view class="flex-1 flex items-center justify-end" v-else>商家暂未设置地址</view>
  59. </view>
  60. <view class="card-template-item justify-between" v-if="shopDetail.business_hours">
  61. <view class="text-[28rpx]">营业时间</view>
  62. <view class="text-[28rpx]">{{ shopDetail.business_hours }}</view>
  63. </view>
  64. </view>
  65. <view class="card-template text-center text-[30rpx] text-primary font-500" @click="redirect({url:'/addon/mall/pages/goods/list',param:{site_id:shopDetail.site_id}, mode: 'navigateTo'})">
  66. 查看全部商品
  67. </view>
  68. </view>
  69. <view @touchmove.prevent.stop>
  70. <u-popup class="popup-type" :show="qrcode" @close="qrcode = false" mode="center" round="var(--rounded-big)">
  71. <view class="w-[540rpx] rounded-[24rpx] min-h-[300rpx] popup-common" @touchmove.prevent.stop>
  72. <view class="title">店铺二维码</view>
  73. <view class="flex-center">
  74. <!-- #ifdef H5 -->
  75. <image :src="wapImage" class="w-[120rpx] h-[120rpx]" mode="aspectFill"></image>
  76. <!-- #endif -->
  77. <!-- #ifdef MP-WEIXIN -->
  78. <image :src="img(qrcodeImg)" class="w-[120rpx] h-[120rpx]" mode="aspectFill"></image>
  79. <!-- #endif -->
  80. </view>
  81. </view>
  82. </u-popup>
  83. </view>
  84. <view @touchmove.prevent.stop>
  85. <u-popup class="popup-type" :show="storePic" @close="storePic = false" mode="center" zIndex="995" :overlayStyle="{zIndex: 994}" round="var(--rounded-big)">
  86. <view class="w-[540rpx] rounded-[24rpx] min-h-[300rpx] popup-common" @touchmove.prevent.stop>
  87. <view class="title">店铺资质</view>
  88. <view class="flex-center pb-[56rpx]">
  89. <view class="w-[400rpx]">
  90. <template v-if="shopDetail.shop.business_image.length">
  91. <u-swiper :list="shopDetail.shop.business_image" :indicator="shopDetail.shop.business_image.length" :indicatorStyle="{'bottom': '50rpx'}" indicatorMode="dot" :autoplay="true" height="400rpx" radius="0" @click="swiperClick"></u-swiper>
  92. </template>
  93. <view v-else class="text-center">暂无店铺资质</view>
  94. </view>
  95. </view>
  96. </view>
  97. </u-popup>
  98. </view>
  99. <loading-page :loading="loading"></loading-page>
  100. </view>
  101. </template>
  102. <script setup lang="ts">
  103. import { reactive, ref, computed } from 'vue';
  104. import { onLoad, onUnload } from '@dcloudio/uni-app';
  105. import { img, redirect} from '@/utils/common'
  106. import { getShopInfo, editShopCollect } from '@/addon/mall/api/shop';
  107. import { getShopQrcode } from '@/app/api/shop';
  108. import { useLogin } from '@/hooks/useLogin'
  109. import useMemberStore from '@/stores/member'
  110. import QRCode from 'qrcode'
  111. // 会员信息
  112. const memberStore = useMemberStore()
  113. const userInfo = computed(() => memberStore.info)
  114. const siteId = ref('')
  115. const shopDetail = ref<Object>({});
  116. const loading = ref<boolean>(true);
  117. onLoad((option:any) => {
  118. siteId.value = option.site_id;
  119. shopInfoFn(siteId.value);
  120. // #ifdef MP-WEIXIN
  121. loadWeapp()
  122. // #endif
  123. });
  124. const shopInfoFn = (siteId:any) =>{
  125. loading.value = true;
  126. getShopInfo(siteId).then((res:any) =>{
  127. shopDetail.value = res.data;
  128. shopDetail.value.rate = 5
  129. shopDetail.value.shop.business_image = []
  130. if(shopDetail.value.shop.business_license){
  131. shopDetail.value.shop.business_license.split(',').forEach((item:any, index:any) => {
  132. shopDetail.value.shop.business_image.push(img(item))
  133. })
  134. }
  135. isFollow.value = shopDetail.value.member_info.is_follow
  136. loading.value = false;
  137. }).catch(() =>{
  138. loading.value = false;
  139. })
  140. }
  141. // 关注
  142. let isFollow = ref<any>(0);
  143. const collectShop = (site_id:any,is_follow:any) =>{
  144. // 检测是否登录
  145. if (!userInfo.value) {
  146. useLogin().setLoginBack({ url: '/addon/mall/pages/shop/detail', param: { site_id: shopDetail.value.site_id } })
  147. return false
  148. }
  149. editShopCollect({
  150. site_id: site_id,
  151. is_follow: is_follow
  152. }).then(res =>{
  153. isFollow.value = !isFollow.value;
  154. if (isFollow.value) {
  155. uni.showToast({
  156. title: '关注成功',
  157. icon: 'none'
  158. });
  159. } else {
  160. uni.showToast({
  161. title: '取消关注',
  162. icon: 'none'
  163. });
  164. }
  165. })
  166. }
  167. const storePic = ref(false)
  168. const qrcode = ref(false)
  169. const wapPreview = ref<any>('')
  170. const wapImage = ref('') //公众号二维码
  171. const qrcodeImg = ref('') //小程序二维码
  172. // #ifdef H5
  173. const loadQrcode = () => {
  174. wapPreview.value = location.href
  175. // errorCorrectionLevel:密度容错率L(低)H(高)
  176. QRCode.toDataURL(wapPreview.value, { errorCorrectionLevel: 'L', margin: 0, width: 120 }).then(url => {
  177. wapImage.value = url
  178. })
  179. }
  180. loadQrcode()
  181. // #endif
  182. const loadWeapp = () => {
  183. getShopQrcode(siteId.value).then((res:any) =>{
  184. qrcodeImg.value = res.data
  185. })
  186. }
  187. const call = (data: any) => {
  188. if (!data) {
  189. uni.showToast({
  190. title: '商家暂未设置联系电话',
  191. icon: 'none'
  192. });
  193. return false
  194. }
  195. uni.makePhoneCall({
  196. phoneNumber: data,
  197. success: (res: any) => {
  198. },
  199. fail: (res: any) => {
  200. }
  201. })
  202. }
  203. const getAddress = () => {
  204. uni.openLocation({
  205. latitude: Number(shopDetail.value.latitude),
  206. longitude: Number(shopDetail.value.longitude),
  207. success: function () { }
  208. });
  209. }
  210. const swiperClick = (index:any)=>{
  211. if(typeof index == 'number')
  212. imgListPreview(shopDetail.value.shop.business_image,index)
  213. }
  214. //预览图片
  215. const imgListPreview = (item:any,index:any) => {
  216. if(Array.isArray(item)){
  217. if (!item.length) return false
  218. var urlList =item;
  219. uni.previewImage({
  220. indicator: "number",
  221. current:index,
  222. loop: true,
  223. urls: urlList
  224. })
  225. }else{
  226. if (item === '') return false
  227. var urlList = []
  228. urlList.push(img(item)) //push中的参数为 :src="item.img_url" 中的图片地址
  229. uni.previewImage({
  230. indicator: "number",
  231. loop: true,
  232. urls: urlList
  233. })
  234. }
  235. }
  236. // 关闭预览图片
  237. onUnload(()=>{
  238. // #ifdef H5 || APP
  239. uni.closePreviewImage()
  240. // #endif
  241. })
  242. </script>
  243. <style lang="scss" scoped>
  244. .tag{
  245. background: linear-gradient( 90deg, #FFD6B5 0%, #FFBA8C 100%)
  246. }
  247. </style>