shop-detail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <template>
  2. <view class="brand-detail-container">
  3. <BeeBack
  4. :success-cb="successCb"
  5. style="position: sticky;top: 0;z-index: 3;padding-top: 16upx;background-color: #ffffff;"
  6. >
  7. <view style="display: flex;align-items: center;justify-content: space-between;">
  8. <BeeIcon
  9. name="arrowleft" :size="34" color="#222229"
  10. style="width: fit-content;padding: 1upx;margin-left: 30upx;border: 1upx solid #eeeeee;border-radius: 50%;line-height: 1;"
  11. >
  12. </BeeIcon>
  13. <text style="flex: 1;margin-left: -104upx;text-align: center;font-size: 38upx;font-weight: bold;">门店详情</text>
  14. </view>
  15. </BeeBack>
  16. <view style="padding: 0 30upx 28upx;background-color: #ffffff;">
  17. <BrandInfo
  18. :brand-detail="brandDetail" style="padding-top: 40upx;" @navgation="handleNavigate"
  19. @refresh="getBrandDetail"
  20. ></BrandInfo>
  21. </view>
  22. <!-- <view
  23. style="display: flex;justify-content: space-between;align-items: center;padding: 18upx 30upx;margin-top: 18upx;background-color: #ffffff;"
  24. @click="handleApplyForRecruit"
  25. >
  26. <view style="display: flex;align-items: center;">
  27. <tui-icon name="friendadd" color="#222229" :size="22"></tui-icon>
  28. <text style="margin-left: 16upx;">成为分销员</text>
  29. </view>
  30. <tui-icon name="arrowright" color="#151515" :size="26"></tui-icon>
  31. </view> -->
  32. <!-- ['商品', '四季鲜蔬', '火锅食材', '烧烤食材', '鲜果礼篮', '粮油副食']allTabList.map(i => i.classifyName) -->
  33. <tui-tab
  34. :tabs="allTabList" :current="currentTab" scroll background-color="transparent"
  35. :size="32" bold bottom="6upx"
  36. color="#222229" selected-color="#222229" slider-bg-color="#ef530e" slider-height="4px"
  37. @change="handleTabChange"
  38. ></tui-tab>
  39. <view
  40. v-if="allTabListData[currentTab].classify && allTabListData[currentTab].classify.length > 0"
  41. class="childsSelect"
  42. >
  43. <view
  44. v-for="(item, index) in allTabListData[currentTab].classify" :key="index" class="childsItem"
  45. :class="{ active: index == childsCurrent }" @click="checkChildsClassIfyIds(item, index)"
  46. >
  47. {{ item.classifyName }}
  48. </view>
  49. </view>
  50. <view class="brand-pane">
  51. <view v-if="currentTab === -1">
  52. <CanvasPage
  53. v-if="componentsData && componentsData.length" :components-data="componentsData" :terminal="terminal"
  54. :type-id="3" :shop-id="Number(shopId)"
  55. >
  56. </CanvasPage>
  57. <tui-no-data v-else-if="componentsData && !componentsData.length" :fixed="false" style="margin-top: 40upx;">
  58. 商家未装修首页
  59. </tui-no-data>
  60. </view>
  61. <view v-else>
  62. <view v-if="bannerInfoList && bannerInfoList.length > 0" style="background: #f7f7f7;padding: 20upx 30upx;">
  63. <swiper indicator-dots="true">
  64. <swiper-item v-for="(item, index) in bannerInfoList" :key="index" @click="handleApplyForRecruit()">
  65. <image :src="item.bannerImage" style="width: 100%;height: 280upx;border-radius: 20upx;"></image>
  66. </swiper-item>
  67. </swiper>
  68. </view>
  69. <view style="display: flex;align-items: center;justify-content: space-around;padding: 10upx 0;font-size: 26upx;">
  70. <view :style="{ color: sortGoodsIndex == 1 ? '#ff7911' : '#000000' }" @click="handleGoodsSortTap(1)">
  71. <text>新品</text>
  72. </view>
  73. <view :style="{ color: sortGoodsIndex == 2 ? '#ff7911' : '#000000' }" @click="handleGoodsSortTap(2)">
  74. <text>价格</text>
  75. <tui-icon
  76. :name="shopGoodsInfo.query.type == 1 ? 'turningup' : shopGoodsInfo.query.type == 2 ? 'turningdown' : ''"
  77. color="#666666" :size="16"
  78. ></tui-icon>
  79. </view>
  80. <view :style="{ color: sortGoodsIndex == 3 ? '#ff7911' : '#000000' }" @click="handleGoodsSortTap(3)">
  81. <text>销量</text>
  82. <tui-icon
  83. v-if="[1, 2].includes(shopGoodsInfo.query.volume)"
  84. :name="shopGoodsInfo.query.volume == 1 ? 'turningup' : shopGoodsInfo.query.volume == 2 ? 'turningdown' : ''"
  85. color="#666666" :size="16"
  86. ></tui-icon>
  87. </view>
  88. </view>
  89. <view v-if="shopGoodsInfo.data && shopGoodsInfo.data.length" style="width: 100%;">
  90. <tui-waterfall :list-data="shopGoodsInfo.data" :type="2">
  91. <template #left="{ entity }">
  92. <ShopGoods
  93. :shop-id="shopId" :c-item="entity"
  94. @add-car="(e) => $refs.refATFSpecificationScreen.open(e.shopId, e.productId, e.skuId)"
  95. >
  96. </ShopGoods>
  97. </template>
  98. <template #right="{ entity }">
  99. <ShopGoods
  100. :shop-id="shopId" :c-item="entity"
  101. @add-car="(e) => $refs.refATFSpecificationScreen.open(e.shopId, e.productId, e.skuId)"
  102. >
  103. </ShopGoods>
  104. </template>
  105. </tui-waterfall>
  106. </view>
  107. <view style="padding-bottom: 45upx;">
  108. <LoadingMore
  109. :status="!shopGoodsInfo.isEmpty && !shopGoodsInfo.data.length
  110. ? 'loading' : !shopGoodsInfo.isEmpty && shopGoodsInfo.data.length && (shopGoodsInfo.data.length >= shopGoodsInfo.listTotal) ? 'no-more' : ''"
  111. >
  112. </LoadingMore>
  113. <tui-no-data v-if="shopGoodsInfo.isEmpty" :fixed="false" style="margin-top: 60upx;">暂无数据</tui-no-data>
  114. </view>
  115. </view>
  116. </view>
  117. <ATFSpecificationScreen ref="refATFSpecificationScreen" @success="initShopCart"></ATFSpecificationScreen>
  118. <view v-if="currentTab === 0 && brandDetail.shopId">
  119. <StoreShopCart ref="refStoreShopCart" :brand-id="brandDetail.shopId"></StoreShopCart>
  120. </view>
  121. </view>
  122. </template>
  123. <script>
  124. import BrandInfo from './components/BrandInfo'
  125. import CanvasPage from '../../../components/canvasShow/canvasShowPage.vue'
  126. import ShopGoods from './components/ShopGoods'
  127. import StoreShopCart from './components/StoreShopCart.vue'
  128. import { getIndexShopDetailApi, checkDistributorHasApplyApi, getShopClassifyApi, getShopProductsApi, getShopBannerApi, getCanvasApi, addShopBusinessBuyerUserApi } from '../../../api/anotherTFInterface'
  129. import { navigationAddress } from '../../../utils'
  130. export default {
  131. name: 'ShopDetail',
  132. components: {
  133. BrandInfo,
  134. CanvasPage,
  135. ShopGoods,
  136. StoreShopCart
  137. },
  138. data() {
  139. return {
  140. successCb: () => {
  141. const pages = getCurrentPages()
  142. if (pages[pages.length - 2].route === 'pages/business-district/business-district') uni.$emit('sendStoreDetailMsg', { data: { meaning: 'refreshCurrentData' } })
  143. },
  144. shopId: null,
  145. brandDetail: {},
  146. allTabList: [ '商品' ],
  147. allTabListData: [ { classifyName: '商品', classifyId: 0 } ], // [{ classifyName: '商品', classifyId: 0 }, { classifyName: '首页', classifyId: 0 }]
  148. currentTab: 0,
  149. childsCurrent: -1,
  150. // 首页
  151. componentsData: null,
  152. terminal: getApp().globalData.terminal,
  153. // 全部等其它tab
  154. classifyId: '',
  155. bannerInfoList: [],
  156. sortGoodsIndex: '',
  157. shopGoodsInfo: {
  158. query: {
  159. ifNew: 1, // 是否新品
  160. type: 1, // 价格排序条件
  161. volume: 0, // 销量排序条件
  162. page: 1, // 当前页
  163. pageSize: 20 // 每页记录数
  164. },
  165. data: [],
  166. listTotal: 0, // 列表数据总数
  167. isEmpty: false // 列表是否为空
  168. }
  169. }
  170. },
  171. onLoad(options) {
  172. this.shopId = options.shopId
  173. this.getBrandDetail()
  174. getShopClassifyApi({
  175. shopId: this.shopId
  176. }).then((res) => {
  177. this.allTabListData = this.allTabListData.concat(res.data.filter((item) => JSON.stringify(item) !== '{}'))
  178. this.allTabList = this.allTabListData.map((item) => item.classifyName)
  179. })
  180. getShopBannerApi({
  181. shopId: this.shopId
  182. }).then((res) => {
  183. this.bannerInfoList = res.data
  184. })
  185. getCanvasApi({ terminal: this.terminal, type: 3, shopId: this.shopId }).then((res) => {
  186. if (JSON.stringify(res.data) !== '{}') {
  187. this.componentsData = JSON.parse(res.data.json)
  188. } else {
  189. this.componentsData = []
  190. }
  191. })
  192. addShopBusinessBuyerUserApi({ shopId: this.shopId })
  193. this.getShopGoodsTemplate()
  194. },
  195. onShow() {
  196. this.initShopCart()
  197. },
  198. methods: {
  199. initShopCart() {
  200. if (this.currentTab === 0 && this.brandDetail.shopId && this.$refs.refStoreShopCart && this.$refs.refStoreShopCart.$refs.refATFShopCartList) {
  201. this.$refs.refStoreShopCart.$refs.refATFShopCartList.getShopCartData('single')
  202. }
  203. },
  204. async getBrandDetail() {
  205. try {
  206. uni.showLoading()
  207. const { data } = await getIndexShopDetailApi({
  208. shopId: this.shopId,
  209. longitude: this.$store.state.location.locationInfo.streetNumber.location.split(',')[0],
  210. latitude: this.$store.state.location.locationInfo.streetNumber.location.split(',')[1]
  211. })
  212. console.log(data)
  213. this.brandDetail = data || {}
  214. uni.hideLoading()
  215. } catch (error) {
  216. console.log(error)
  217. uni.hideLoading()
  218. }
  219. },
  220. // 导航
  221. handleNavigate() {
  222. if (!this.brandDetail.shopAdress) return this.$showToast('商家地址有误,导航失败')
  223. navigationAddress(`${this.brandDetail.longitude},${this.brandDetail.latitude}`)
  224. },
  225. // 判断是否已申请成为该店铺的分销员
  226. handleApplyForRecruit() {
  227. uni.showLoading()
  228. checkDistributorHasApplyApi({
  229. shopId: this.shopId
  230. }).then((res) => {
  231. uni.hideLoading()
  232. if (!res.data.distributorId) {
  233. this.go('/another-tf/another-serve/distributionModule/recruit?shopId=' + this.shopId)
  234. } else if (res.data.state === 1) {
  235. this.$showToast('您已申请成为该店铺的分销员')
  236. } else {
  237. this.$showToast('您的申请正在审核中,请稍后查看')
  238. }
  239. })
  240. .catch(() => {
  241. uni.hideLoading()
  242. })
  243. },
  244. // 栏目切换
  245. handleTabChange(e) {
  246. this.childsCurrent = 0
  247. this.currentTab = e.index
  248. console.log(this.currentTab)
  249. this.initShopCart()
  250. // if (e.index === 1) return
  251. this.shopGoodsInfo.data = []
  252. this.shopGoodsInfo.query.page = 1
  253. if (this.allTabListData[e.index].classify && this.allTabListData[e.index].classify.length > 0) {
  254. this.classifyId = this.allTabListData[e.index].classify[0].classifyId
  255. this.getShopGoodsTemplate()
  256. return
  257. }
  258. if (e.index === 0) {
  259. this.classifyId = ''
  260. } else {
  261. this.classifyId = this.allTabListData[e.index].classifyId
  262. }
  263. this.getShopGoodsTemplate()
  264. },
  265. getShopGoodsTemplate(isLoadmore) {
  266. uni.showLoading()
  267. getShopProductsApi({
  268. ...this.shopGoodsInfo.query,
  269. shopId: this.shopId,
  270. groupId: this.classifyId
  271. }).then((res) => {
  272. this.shopGoodsInfo.listTotal = res.data.page.total
  273. if (isLoadmore) {
  274. this.shopGoodsInfo.data.push(...res.data.page.list)
  275. } else {
  276. this.shopGoodsInfo.data = res.data.page.list
  277. }
  278. this.shopGoodsInfo.isEmpty = this.shopGoodsInfo.data.length === 0
  279. uni.hideLoading()
  280. })
  281. .catch((e) => {
  282. uni.hideLoading()
  283. })
  284. },
  285. handleGoodsSortTap(index) {
  286. this.shopGoodsInfo.query.page = 1
  287. this.shopGoodsInfo.data = []
  288. if (index == 1) {
  289. this.shopGoodsInfo.query.ifNew = this.shopGoodsInfo.query.ifNew != 0 ? 0 : 1,
  290. this.shopGoodsInfo.query.type = 1,
  291. this.shopGoodsInfo.query.volume = 1,
  292. this.sortGoodsIndex = index
  293. } else if (index == 2) {
  294. this.shopGoodsInfo.query.ifNew = 0,
  295. this.shopGoodsInfo.query.type = this.shopGoodsInfo.query.type != 1 ? 1 : 2,
  296. this.shopGoodsInfo.query.volume = 1,
  297. this.sortGoodsIndex = index
  298. } else if (index == 3) {
  299. this.shopGoodsInfo.query.ifNew = 0,
  300. this.shopGoodsInfo.query.type = 1,
  301. this.shopGoodsInfo.query.volume = this.shopGoodsInfo.query.volume != 1 ? 1 : 2,
  302. this.sortGoodsIndex = index
  303. }
  304. this.getShopGoodsTemplate()
  305. },
  306. checkChildsClassIfyIds(item, index) {
  307. this.childsCurrent = index
  308. this.classifyId = item.classifyId
  309. this.getShopGoodsTemplate()
  310. }
  311. },
  312. onReachBottom() {
  313. if (this.currentTab !== 0) {
  314. if (this.shopGoodsInfo.data.length < this.shopGoodsInfo.listTotal) {
  315. ++this.shopGoodsInfo.query.page
  316. this.getShopGoodsTemplate(true)
  317. }
  318. }
  319. }
  320. }
  321. </script>
  322. <style lang="less" scoped>
  323. .childsSelect {
  324. margin-top: 4rpx;
  325. box-sizing: border-box;
  326. padding: 0rpx 20rpx;
  327. width: 100vw;
  328. height: 60rpx;
  329. display: flex;
  330. align-items: center;
  331. gap: 20rpx;
  332. white-space: nowrap;
  333. overflow-x: auto;
  334. overflow-y: hidden;
  335. .childsItem {
  336. border-radius: 8rpx;
  337. box-sizing: border-box;
  338. padding: 12rpx 10rpx;
  339. // display: flex;
  340. // align-items: center;
  341. // line-height: 48rpx;
  342. // width: 70rpx;
  343. height: 58rpx;
  344. color: #8c8b8d;
  345. font-size: 30rpx;
  346. background-color: #fffffff2;
  347. display: inline-block;
  348. }
  349. .active {
  350. color: #fff;
  351. background-color: #ff8000;
  352. }
  353. }
  354. .brand-detail-container {
  355. position: relative;
  356. min-height: 100vh;
  357. padding-bottom: 120upx;
  358. background-color: #f5f4f6;
  359. box-sizing: border-box;
  360. .tui-scroll__view {
  361. /deep/ .tui-tabs__line {
  362. clip-path: inset(0% 15% 0% 15% round 4upx 4upx 4upx 4upx);
  363. }
  364. }
  365. .brand-pane {
  366. background-color: #fff;
  367. padding: 4upx 20upx 0 20upx;
  368. margin-top: 10upx;
  369. }
  370. }
  371. </style>