storeIndex.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. <template>
  2. <view class="content">
  3. <view class="top-content">
  4. <view class="status_bar" :style="{height: statusBarHeight}"></view>
  5. <!-- 这里是状态栏 -->
  6. <view class="top-title">
  7. <u-icon name="arrow-left" color="#fff" size="24" @click="navback()"></u-icon>
  8. <view class="search-cont">
  9. <view class="inner">
  10. <image class="icon-search" src="https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/icon_search.png" mode=""></image>
  11. <input type="text" disabled confirm-type="搜索" @click="toSearch" placeholder="查找店内药品" placeholder-style="font-size:28rpx;color:#BBBBBB;font-family: PingFang SC;" />
  12. </view>
  13. </view>
  14. </view>
  15. <view class="storebox x-bc">
  16. <view class="x-f">
  17. <image class="logo" :src="storeInfo.logoUrl" mode="aspectFill"></image>
  18. <view class="storebox-r" @click="goStoreDetail">
  19. <view class="storename ellipsis2">{{storeInfo.storeName}}</view>
  20. <!-- <view class="storedesc">24小时营业 销售{{storeInfo.salesCount|| 0}}</view> -->
  21. </view>
  22. </view>
  23. <!-- <view class="storebox-btn" @click="goStoreDetail">详情</view> -->
  24. </view>
  25. <view class="top-fixed x-ac" style="background-color: #fff;">
  26. <view>
  27. <u-tabs
  28. :scrollable="false"
  29. :list="tabs"
  30. lineColor="#2583EB"
  31. :current="current"
  32. @change="tabChange">
  33. </u-tabs>
  34. </view>
  35. </view>
  36. </view>
  37. <view v-show="current!=1" :style="{paddingTop: mescrollTop+'px'}">
  38. <tuiStoreProduct ref="tuiStoreProduct" :top="mescrollTop" :storeId="storeId" @refreshElementTop="getElementTop"></tuiStoreProduct>
  39. <view class="evaluate">
  40. <view class="title">店内商品评价({{evaluateTotal}})</view>
  41. <evaluateItem v-for="(item,index) in evaluate" :key="index" :item="item"></evaluateItem>
  42. <view class="footer-desc" v-if="evaluate&&evaluate.length>0">
  43. <text @click="moreEvaluate">查看更多评价</text>
  44. <image src="https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/arrow_gray.png"></image>
  45. </view>
  46. </view>
  47. <detail class="store-detail" ref="getStoreInfo" :storeInfo="storeInfo"></detail>
  48. </view>
  49. <view v-if="current==1" class="medic-box">
  50. <view class="cate-list" :style="{top: mescrollTop+'px',height:divHeight}">
  51. <view
  52. v-for="(item,index) in cates"
  53. :key="index"
  54. :class="cateSelect == item.cateId?'item active':'item'"
  55. @click="choseCate(item)"
  56. >{{item.cateName }}</view>
  57. </view>
  58. <view class="medic">
  59. <mescroll-body :top="mescrollTop+'px'" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
  60. <view style="padding-right: 16rpx;">
  61. <medicineItem v-for="(item, index) in dataList" :key="index" :item="item" :storeId="storeId"></medicineItem>
  62. <!-- <medicineVerticalItem v-for="(item, index) in dataList" :key="index" :item="item" :storeId="storeId"></medicineVerticalItem> -->
  63. </view>
  64. </mescroll-body>
  65. <!-- 轮播图 -->
  66. <!-- <view class="banner-box">
  67. <swiper
  68. class="swiper"
  69. :indicator-dots="true"
  70. :circular="true"
  71. :autoplay="true"
  72. :interval="3000"
  73. :duration="1000"
  74. indicator-color="rgba(255, 255, 255, 0.6)"
  75. indicator-active-color="#ffffff"
  76. >
  77. <swiper-item class="swiper-item" v-for="(item,index) in advs" :key="index" @click="handleAdvClick(item)">
  78. <image :src="item.imageUrl" mode=""></image>
  79. </swiper-item>
  80. </swiper>
  81. </view> -->
  82. </view>
  83. </view>
  84. </view>
  85. </template>
  86. <script>
  87. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  88. import tuiStoreProduct from './components/tuiStoreProduct.vue'
  89. import qualifications from './components/qualifications.vue'
  90. import {getProductCate,storeDetail,getProducts} from '@/api/index.js'
  91. import medicineVerticalItem from "@/components/medicineVerticalItem";
  92. import medicineItem from "@/components/medicineItem";
  93. import evaluateItem from "@/components/evaluateItem";
  94. import detail from './components/storeDetail.vue'
  95. import {selectCommentByUser} from '@/api/myStoreOrder.js'
  96. // import {getAdv} from '@/api/adv'
  97. export default {
  98. mixins: [MescrollMixin], // 使用mixin
  99. components: {
  100. tuiStoreProduct,
  101. qualifications,
  102. medicineVerticalItem,
  103. medicineItem,
  104. evaluateItem,
  105. detail
  106. },
  107. data() {
  108. return {
  109. divHeight:'0px',
  110. allCates:[],
  111. cates:[],
  112. subCates:[],
  113. // 状态栏的高度
  114. statusBarHeight: uni.getStorageSync('menuInfo').statusBarHeight,
  115. // 选中药品分类
  116. cateSelect: 0,
  117. // 轮播图
  118. advs: [],
  119. tabs:[
  120. {
  121. id:1,
  122. name:'推荐'
  123. },
  124. {
  125. id:2,
  126. name:'分类'
  127. },
  128. {
  129. id:3,
  130. name:'评价'
  131. },
  132. {
  133. id:4,
  134. name:'详情'
  135. }
  136. ],
  137. current:0,
  138. storeInfo: {},
  139. storeId:'',
  140. mescroll:null,
  141. downOption: { //下拉刷新
  142. use:true,
  143. auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
  144. },
  145. // 上拉加载的配置
  146. upOption: {
  147. onScroll:true,
  148. use: true, // 是否启用上拉加载; 默认true
  149. page: {
  150. num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
  151. size: 10 // 每页数据的数量,默认10
  152. },
  153. noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
  154. empty: {
  155. icon:'https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/app/newImages/empty_icon.png',
  156. tip: '暂无数据'
  157. },
  158. textNoMore:"已经到底了",
  159. },
  160. // 列表数据
  161. dataList: [],
  162. form:{
  163. defaultOrder:'desc',
  164. newOrder:null,
  165. priceOrder:null,
  166. salesOrder:null,
  167. productName:"",
  168. storeId: "",
  169. cateId:'',
  170. pid:'',
  171. storeId: ''
  172. },
  173. mescrollTop: 200,
  174. evaluate: [],
  175. evaluateTotal: 0,
  176. isScrollUpdating: false, // 标志位
  177. evaluateTop: 0,
  178. storeDetailTop: 0
  179. };
  180. },
  181. onLoad(option) {
  182. this.storeId = option.storeId
  183. this.form.storeId = option.storeId || ''
  184. uni.showShareMenu({
  185. withShareTicket:true,
  186. //小程序的原生菜单中显示分享按钮,才能够让发送给朋友与分享到朋友圈两个按钮可以点击
  187. menus:["shareAppMessage","shareTimeline"] //不设置默认发送给朋友
  188. })
  189. this.getProductCate();
  190. this.getStoreInfo();
  191. this.getCommentByUser();
  192. },
  193. onReady() {
  194. this.$refs.tuiStoreProduct.getProducts(this.storeId)
  195. },
  196. onShow() {
  197. var that=this;
  198. setTimeout(function(){
  199. let info = uni.createSelectorQuery().select(".top-content");
  200.     info.boundingClientRect(function(data) { //data - 各种参数
  201. //       console.log(data.height) // 获取元素宽度
  202. // console.log(uni.upx2px(10))
  203. that.divHeight="calc(100% - "+data.height+"px)"
  204. that.mescrollTop = data.height
  205.    }).exec()
  206. },500);
  207. },
  208. onPageScroll(e) {
  209. if (this.isScrollUpdating) return;
  210. const scrollTop = e.scrollTop;
  211. if (this.evaluateTop && this.storeDetailTop) {
  212. if (scrollTop >= this.storeDetailTop) {
  213. this.current = 3;
  214. } else if (scrollTop >= this.evaluateTop) {
  215. this.current = 2;
  216. } else {
  217. this.current = 0; // 或其他默认值
  218. }
  219. }
  220. },
  221. methods:{
  222. getElementTop(type) {
  223. this.$nextTick(() => {
  224. const query = uni.createSelectorQuery().in(this);
  225. query.select('.evaluate').boundingClientRect();
  226. query.select('.store-detail').boundingClientRect(); // 注意:ref 不能直接用于 select,需要加 class
  227. query.exec(res => {
  228. this.evaluateTop = res[0]?.top - this.mescrollTop || 0;
  229. this.storeDetailTop = res[1]?.top - this.mescrollTop || 0;
  230. });
  231. });
  232. },
  233. getStoreInfo() {
  234. storeDetail(this.storeId).then(res=>{
  235. if(res.code==200) {
  236. this.storeInfo =res.data || {}
  237. }
  238. this.getElementTop('storeDetailTop');
  239. })
  240. },
  241. navback() {
  242. uni.navigateBack()
  243. },
  244. tabChange(item) {
  245. this.current=item.index
  246. this.isScrollUpdating = true;
  247. if ([0, 2, 3].includes(this.current)) {
  248. const scrollMap = {
  249. 0: 0,
  250. 2: this.evaluateTop,
  251. 3: this.storeDetailTop
  252. };
  253. setTimeout(()=>{
  254. uni.pageScrollTo({
  255. scrollTop: scrollMap[this.current] || 0 ,
  256. duration: 0,
  257. complete: () => {
  258. this.isScrollUpdating = false;
  259. }
  260. });
  261. },100)
  262. }
  263. },
  264. toSearch() {
  265. uni.navigateTo({
  266. url: '/pages_shopping/home/productSearch?storeId='+this.storeId
  267. })
  268. },
  269. handleAdvClick(item){
  270. if(item.showType==1){
  271. uni.setStorageSync('url',item.advUrl);
  272. uni.navigateTo({
  273. url:"/pages_shopping/home/h5"
  274. })
  275. }
  276. else if(item.showType==2){
  277. uni.navigateTo({
  278. url:item.advUrl
  279. })
  280. }
  281. else if(item.showType==3){
  282. uni.setStorageSync('content',item.content);
  283. uni.navigateTo({
  284. url:"/pages_shopping/home/content"
  285. })
  286. }
  287. },
  288. getAdv(){
  289. let data = {advType:2};
  290. getAdv(data).then(
  291. res => {
  292. if(res.code==200){
  293. this.advs=res.data;
  294. }
  295. },
  296. rej => {}
  297. );
  298. },
  299. getProductCate(){
  300. let data = {
  301. // storeId: this.storeId
  302. };
  303. getProductCate(data).then(
  304. res => {
  305. if(res.code==200){
  306. this.allCates=res.data;
  307. this.cates = this.allCates.filter(function (item) {
  308. return item.pid==0
  309. });
  310. if(this.cates!=null&&this.cates.length>0){
  311. this.cateSelect=this.cates[0].cateId;
  312. this.form.cateId = this.cates[0].cateId;
  313. // this.form.pid = this.cates[0].pid;
  314. this.mescroll&&this.mescroll.resetUpScroll()
  315. }
  316. }else{
  317. uni.showToast({
  318. icon:'none',
  319. title: "请求失败",
  320. });
  321. }
  322. },
  323. rej => {}
  324. );
  325. },
  326. // 药品分类选择
  327. choseCate(item) {
  328. this.cateSelect = item.cateId;
  329. // this.getSubCate()
  330. this.form.cateId = item.cateId;
  331. this.mescroll.resetUpScroll()
  332. },
  333. getSubCate(){
  334. var that=this;
  335. this.subCates = this.allCates.filter(function (item) {
  336. // let subList = that.allCates.filter(child => {
  337. // //返回每一项的子级数组
  338. // return child.pid === item.cateId
  339. // });
  340. // subList.length > 0 ? item.children = subList : [];
  341. return item.pid==that.cateSelect
  342. });
  343. },
  344. // 查看药品详情
  345. showProductList(item) {
  346. uni.navigateTo({
  347. url: '/pages_shopping/productList?cateId='+item.cateId+"&pid="+item.pid+'&storeId='+this.storeId
  348. })
  349. },
  350. goSearch(e) {
  351. if(e.detail.value!=null&&e.detail.value!=""){
  352. this.$addHisSearch(e.detail.value);
  353. }
  354. uni.navigateTo({
  355. url: '/pages_shopping/home/productList?storeId='+this.storeId+'&searchValue=' + e.detail.value
  356. })
  357. },
  358. goStoreDetail() {
  359. uni.navigateTo({
  360. url: '/pages_store/storeDetail?storeId='+this.storeId
  361. })
  362. },
  363. mescrollInit(mescroll) {
  364. this.mescroll = mescroll;
  365. },
  366. /*下拉刷新的回调 */
  367. downCallback(mescroll) {
  368. mescroll.resetUpScroll()
  369. },
  370. upCallback(page) {
  371. //联网加载数据
  372. var that = this;
  373. this.form.page=page.num;
  374. this.form.pageSize=page.size;
  375. getProducts(this.form).then(res => {
  376. if(res.code==200){
  377. //设置列表数据
  378. if (page.num == 1) {
  379. that.dataList = res.data.list;
  380. } else {
  381. that.dataList = that.dataList.concat(res.data.list);
  382. }
  383. that.mescroll.endBySize(res.data.list.length, res.data.total);
  384. }else{
  385. uni.showToast({
  386. icon:'none',
  387. title: "请求失败",
  388. });
  389. that.dataList = null;
  390. that.mescroll.endErr();
  391. }
  392. });
  393. },
  394. moreEvaluate() {
  395. uni.navigateTo({
  396. url: '/pages_shopping/evaluate?storeId='+this.storeId,
  397. })
  398. },
  399. getCommentByUser(){
  400. const param = {
  401. page: 1,
  402. pageSize: 2,
  403. storeId:this.storeId,
  404. orderId: null,
  405. productIds:null,
  406. userId: uni.getStorageSync('userId') || null,
  407. showSelf: 0
  408. }
  409. selectCommentByUser(param).then(res=>{
  410. if(res.code==200) {
  411. this.evaluate = res.data.list
  412. this.evaluateTotal = res.data.total
  413. } else {
  414. this.evaluate = []
  415. this.evaluateTotal = 0
  416. }
  417. this.getElementTop('evaluate');
  418. })
  419. }
  420. }
  421. }
  422. </script>
  423. <style lang="scss" scoped>
  424. .evaluate {
  425. padding: 30rpx 30rpx 0 30rpx;
  426. background-color: #FFFFFF;
  427. margin-bottom: 24rpx;
  428. .title {
  429. font-family: PingFang SC, PingFang SC;
  430. font-weight: 600;
  431. font-size: 30rpx;
  432. color: #222222;
  433. padding-bottom: 24rpx;
  434. }
  435. .footer-desc {
  436. text-align: center;
  437. padding: 0 32rpx 24rpx 0;
  438. font-size: 28rpx;
  439. color: #999;
  440. image{
  441. margin-left: 10rpx;
  442. width:15rpx;
  443. height:20rpx;
  444. }
  445. }
  446. }
  447. .storebox {
  448. padding: 26rpx 32rpx;
  449. font-family: PingFang SC, PingFang SC;
  450. color: #FFFFFF;
  451. .logo {
  452. width: 104rpx;
  453. height: 104rpx;
  454. background: #FFFFFF;
  455. border-radius: 16rpx 16rpx 16rpx 16rpx;
  456. margin-right: 26rpx;
  457. }
  458. .storename {
  459. font-weight: 500;
  460. font-size: 32rpx;
  461. }
  462. .storedesc {
  463. margin-top: 12rpx;
  464. font-weight: 400;
  465. font-size: 22rpx;
  466. }
  467. .storebox-r {
  468. flex: 1;
  469. overflow: hidden;
  470. }
  471. .storebox-btn {
  472. flex-shrink: 0;
  473. padding: 10rpx 16rpx;
  474. background: rgba(46, 218, 212, 0.50);
  475. font-size: 28rpx;
  476. border-radius: 8rpx 8rpx 8rpx 8rpx;
  477. }
  478. }
  479. .content{
  480. height: 100%;
  481. display: flex;
  482. flex-direction: column;
  483. .top-content{
  484. position: fixed;
  485. left: 0;
  486. top: 0;
  487. width: 100%;
  488. z-index: 10;
  489. background-repeat: no-repeat;
  490. background-image: url('https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/app/image/index_img/home_top_bg.png');
  491. background-size: 100% 100%;
  492. .top-title{
  493. height: 88upx;
  494. line-height: 88upx;
  495. font-size: 42upx;
  496. font-family: Source Han Sans CN;
  497. font-weight: bold;
  498. color: #222222;
  499. padding-left: 41upx;
  500. background-color: transparent;
  501. display: flex;
  502. align-items: center;
  503. }
  504. .search-cont{
  505. padding: 6upx 30upx;
  506. .inner{
  507. box-sizing: border-box;
  508. width: 70%;
  509. height: 72upx;
  510. background: #FFFFFF;
  511. border-radius: 36upx;
  512. display: flex;
  513. align-items: center;
  514. padding: 0 30upx;
  515. .icon-search{
  516. width: 28upx;
  517. height: 28upx;
  518. margin-right: 20upx;
  519. }
  520. input{
  521. height: 60upx;
  522. line-height: 60upx;
  523. flex: 1;
  524. }
  525. }
  526. }
  527. }
  528. .medic-box{
  529. display: flex;
  530. background: #fff;
  531. ::v-deep{
  532. .mescroll-body, .mescroll-body{
  533. padding-left: 204rpx;
  534. }
  535. }
  536. .cate-list{
  537. position: fixed;
  538. left: 0;
  539. z-index: 999;
  540. box-sizing: border-box;
  541. width: 180upx;
  542. background: #F2F5F9;
  543. display: flex;
  544. flex-direction: column;
  545. padding: 20upx 0;
  546. overflow-y: scroll;
  547. .item{
  548. height: 100upx;
  549. line-height: 100upx;
  550. padding-left: 20upx;
  551. font-size: 28upx;
  552. font-family: PingFang SC;
  553. font-weight: 500;
  554. color: #333333;
  555. position: relative;
  556. &.active{
  557. color: #2583EB;
  558. &::after{
  559. content: "";
  560. width: 8upx;
  561. height: 50upx;
  562. background: #2583EB;
  563. position: absolute;
  564. top: 25upx;
  565. left: 0;
  566. }
  567. }
  568. }
  569. }
  570. .medic{
  571. overflow: hidden;
  572. box-sizing: border-box;
  573. .banner-box{
  574. margin-top: 30rpx;
  575. width: 100%;
  576. height: 160upx;
  577. border-radius: 10upx;
  578. overflow: hidden;
  579. .swiper,
  580. .swiper-item,
  581. .swiper-item image{
  582. width: 100%;
  583. height: 100%;
  584. }
  585. }
  586. }
  587. }
  588. }
  589. </style>