shop.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. <template>
  2. <view>
  3. <uv-navbar title="店铺信息" placeholder></uv-navbar>
  4. <view class="top">
  5. <view class="shop">
  6. <view class="shop_l">
  7. <image :src="details.logo" mode="" />
  8. <view>
  9. <view class="shop_l_title">{{details.businessName}}</view>
  10. <view class="shop_l_rate">
  11. <rate :value="Math.round(details.average)" />
  12. </view>
  13. </view>
  14. </view>
  15. <view class="shop_r" @click="goPhone()">
  16. 售后电话
  17. </view>
  18. </view>
  19. <view class="searchBox">
  20. <image :src="$handleImageUrl('/common/search.png')" mode=""></image>
  21. <input @click="searchClick" v-model="value" type="text" placeholder-style="color:#B3B3B3;font-size:28rpx" placeholder="可搜索本店商品" />
  22. </view>
  23. </view>
  24. <view class="tabsBox">
  25. <uv-tabs :list="tabList" keyName="categoryName" lineColor="#FA6138" activeStyle="color:#FA6138;" lineWidth="60rpx" @click="tabsClick"></uv-tabs>
  26. </view>
  27. <view class="list">
  28. <view class="goodsListA_item" v-for="item in list" :key="item.id" @click="goDetails(item)">
  29. <image :src="`${item.coverImage}`" mode=""></image>
  30. <view class="goodsListA_item_title">{{ item.title }}</view>
  31. <view class="goodsListA_item_pirce">
  32. <text v-if="item.productPaymentMode==1" style="font-size:22rpx;">{{item.minPoints}}积分</text>
  33. <rich-text v-else :nodes="mUtil.priceBigSmall(item.salePrice||item.minSalePrice)"></rich-text>
  34. <view>¥ {{ item.marketPrice||item.minMarketPrice }}</view>
  35. </view>
  36. <view class="goodsListA_item_num">已售{{ item.showSales}}件</view>
  37. </view>
  38. <!-- <view class="goodsListA_item" @click="goDetails()" v-for="(v,i) in 10" :key="i">
  39. <image src="https://jiangxishop.oss-cn-beijing.aliyuncs.com/20250920/b53b0ad4931340258ce217581c6bdcf4.png?x-oss-process=style/w_350" mode=""></image>
  40. <view class="goodsListA_item_title">陶瓷扒花雕刻品茗杯主人杯咖啡杯中式高档茶杯礼盒装</view>
  41. <view class="goodsListA_item_pirce">
  42. <rich-text :nodes="mUtil.priceBigSmall('133')"></rich-text>
  43. <view>¥ 500</view>
  44. </view>
  45. <view class="goodsListA_item_num">已售0件</view>
  46. </view> -->
  47. </view>
  48. <view v-if="list.length<=0" style="width: 100%;">
  49. <noData :config="{ top: 20, content: '暂无商品~' }"></noData>
  50. </view>
  51. <uv-load-more v-else :status="status" />
  52. </view>
  53. </template>
  54. <script setup >
  55. import { getBusinessInfo, getProductCategoryList, productList } from "@/api/shop.js"
  56. import { ref, getCurrentInstance } from 'vue'
  57. import { onShow, onLoad, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
  58. const { proxy } = getCurrentInstance();
  59. const mUtil = proxy.$mUtil;
  60. const details = ref({});
  61. const value = ref("");
  62. const status = ref('loadmore')
  63. const list = ref([]) // 添加缺失的商品列表数据
  64. const tabList = ref([
  65. {
  66. id: 1,
  67. categoryName: "推荐",
  68. categoryId: "recommend",
  69. },
  70. {
  71. id: 2,
  72. categoryName: "热销",
  73. categoryId: "hot",
  74. },
  75. {
  76. id: 3,
  77. categoryName: "新品",
  78. categoryId: "new",
  79. }
  80. ]);
  81. const params = ref({
  82. recommendStatus: true,
  83. pageNum: 1,
  84. pageSize: 10
  85. })
  86. onShow(() => {
  87. let id = uni.getStorageSync('businessId');
  88. if (id) {
  89. params.value.businessId = id;
  90. getDetails();
  91. getTabs()
  92. }
  93. })
  94. // 下拉刷新
  95. onPullDownRefresh(() => {
  96. params.value.pageNum = 1
  97. getProductList()
  98. })
  99. // 上拉加载更多
  100. onReachBottom(() => {
  101. if (status.value == 'loadmore') {
  102. params.value.pageNum++
  103. getProductList()
  104. }
  105. })
  106. const goBack = () => {
  107. // uni.navigateBack()
  108. uni.navigateTo({ url: '/pages/index/index' })
  109. }
  110. const getTabs = () => {
  111. getProductCategoryList({ businessId: params.value.businessId }).then(res => {
  112. tabList.value = [...tabList.value, ...res.data]
  113. }
  114. )
  115. }
  116. // 商家电话
  117. const goPhone = () => {
  118. uni.makePhoneCall({
  119. phoneNumber: details.value.contactPhone
  120. });
  121. }
  122. const getDetails = () => {
  123. getBusinessInfo({ businessId: params.value.businessId }).then(res => {
  124. details.value = res.data;
  125. getProductList()
  126. })
  127. }
  128. // 获取商品分页列表
  129. const getProductList = () => {
  130. status.value = 'loading'
  131. productList(params.value).then(res => {
  132. if (params.value.pageNum == 1) {
  133. list.value = res.rows
  134. } else {
  135. list.value = [...list.value, ...res.rows]
  136. }
  137. if (list.value.length < res.total) {
  138. status.value = 'loadmore'
  139. } else {
  140. status.value = 'noMore'
  141. }
  142. uni.stopPullDownRefresh()
  143. }).catch(e => {
  144. uni.stopPullDownRefresh()
  145. status.value = 'loadmore'
  146. })
  147. };
  148. const goDetails = (item) => {
  149. uni.navigateTo({
  150. url: `/pages/shop/goodsDetails?id=${item.productId}`
  151. });
  152. }
  153. const searchClick = () => {
  154. uni.navigateTo({
  155. url: '/pages/shop/goodSearch'
  156. });
  157. };
  158. const tabsClick = (e) => {
  159. // 重置分页参数
  160. params.value.pageNum = 1
  161. // 根据选中的标签设置不同的查询参数
  162. if (e.index === 0) {
  163. // 推荐
  164. params.value.recommendStatus = true
  165. delete params.value.productCategoryId
  166. delete params.value.hot
  167. delete params.value.newStatus
  168. } else if (e.index === 1) {
  169. // 热销
  170. params.value.hot = true
  171. delete params.value.productCategoryId
  172. delete params.value.recommendStatus
  173. delete params.value.newStatus
  174. } else if (e.index === 2) {
  175. // 新品
  176. params.value.newStatus = true
  177. delete params.value.productCategoryId
  178. delete params.value.recommendStatus
  179. delete params.value.hot
  180. } else {
  181. // 具体分类
  182. params.value.productCategoryId = tabList.value[e.index].categoryId
  183. delete params.value.recommendStatus
  184. delete params.value.hot
  185. delete params.value.newStatus
  186. }
  187. // 重新获取商品列表
  188. getProductList()
  189. }
  190. </script>
  191. <style lang="scss" scoped>
  192. .top {
  193. width: 720rpx;
  194. padding: 30rpx;
  195. box-shadow: 0rpx 4rpx 8rpx 0rpx #f1f1f1;
  196. background: #ffffff;
  197. border-radius: 20rpx;
  198. margin: auto;
  199. box-sizing: border-box;
  200. }
  201. .shop {
  202. display: flex;
  203. align-items: center;
  204. position: relative;
  205. .shop_l {
  206. display: flex;
  207. align-items: center;
  208. image {
  209. width: 124rpx;
  210. height: 124rpx;
  211. border-radius: 20rpx;
  212. }
  213. > view {
  214. flex: 1;
  215. margin-left: 20rpx;
  216. .shop_l_title {
  217. font-size: 32rpx;
  218. color: #333333;
  219. font-weight: 700;
  220. }
  221. .shop_l_rate {
  222. margin-top: 10rpx;
  223. }
  224. }
  225. }
  226. .shop_r {
  227. width: 150rpx;
  228. margin-left: auto;
  229. padding: 6rpx 0rpx;
  230. text-align: center;
  231. color: #666;
  232. border-radius: 25rpx;
  233. background-color: #fff;
  234. border: 1rpx solid #666;
  235. position: absolute;
  236. right: 30rpx;
  237. bottom: 25rpx;
  238. font-size: 28rpx;
  239. }
  240. }
  241. .searchBox {
  242. display: flex;
  243. padding: 10rpx 35rpx;
  244. border: 1rpx solid #cccccc;
  245. border-radius: 36rpx;
  246. margin: 30rpx 0 0;
  247. display: flex;
  248. align-items: center;
  249. margin-top: 10rpx;
  250. background: #fff;
  251. image {
  252. width: 35rpx;
  253. height: 35rpx;
  254. margin-right: 15rpx;
  255. flex-shrink: 0;
  256. }
  257. input {
  258. text-align: left;
  259. }
  260. }
  261. .tabsBox {
  262. margin-bottom: 20rpx;
  263. padding: 0 30rpx;
  264. }
  265. .list {
  266. padding: 0 30rpx;
  267. display: flex;
  268. flex-wrap: wrap;
  269. .goodsListA_item {
  270. width: 336rpx;
  271. box-shadow: 0rpx 4rpx 8rpx 0rpx #f1f1f1;
  272. border-radius: 18rpx;
  273. margin-left: 18rpx;
  274. margin-bottom: 30rpx;
  275. &:nth-child(2n-1) {
  276. margin-left: 0 !important;
  277. }
  278. image {
  279. width: 336rpx;
  280. height: 336rpx;
  281. border-radius: 18rpx 18rpx 0 0;
  282. }
  283. > view {
  284. padding: 0 20rpx;
  285. }
  286. .goodsListA_item_title {
  287. font-size: 28rpx;
  288. color: #181818;
  289. overflow: hidden;
  290. text-overflow: ellipsis;
  291. display: -webkit-box;
  292. -webkit-line-clamp: 2;
  293. -webkit-box-orient: vertical;
  294. }
  295. .goodsListA_item_pirce {
  296. display: flex;
  297. // align-items: flex-end;
  298. align-items: baseline;
  299. font-size: 20rpx;
  300. color: #ff6600;
  301. font-weight: 700;
  302. text {
  303. font-size: 36rpx;
  304. font-weight: 500;
  305. display: inline-block;
  306. // position: relative;
  307. // top: 4rpx;
  308. }
  309. > view {
  310. font-size: 24rpx;
  311. color: #cccccc;
  312. margin-left: 30rpx;
  313. text-decoration: line-through;
  314. font-weight: normal;
  315. }
  316. }
  317. .goodsListA_item_num {
  318. font-size: 22rpx;
  319. color: #999999;
  320. margin-top: 10rpx;
  321. padding-bottom: 20rpx;
  322. }
  323. }
  324. }
  325. </style>