storeIndex.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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. <!-- <scroll-view :scroll-y="true" 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. </scroll-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: 0 24rpx;">
  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. // if (this.storeInfo.doctorList && this.storeInfo.doctorList.length > 0) {
  238. // this.storeInfo.doctorList = this.storeInfo.doctorList.map(doctor => {
  239. // if (doctor.images) {
  240. // doctor.practiseImages = doctor.practiseImages.split(',').map(img => img.trim());
  241. // }
  242. // return doctor;
  243. // });
  244. // }
  245. this.storeInfo.doctorList = this.storeInfo.doctorList.map(doctor => {
  246. return {
  247. ...doctor,
  248. // 假设images字段是逗号分隔的图片字符串
  249. imagesArray: doctor.practiseImages ?
  250. doctor.practiseImages.split(',').map(img => img.trim()).filter(img => img) : []
  251. };
  252. });
  253. console.log(this.storeInfo.doctorList)
  254. }
  255. this.getElementTop('storeDetailTop');
  256. })
  257. },
  258. navback() {
  259. const pages = getCurrentPages(); // 获取当前页面栈
  260. if (pages.length > 1) {
  261. uni.navigateBack({ delta: 1 }); // 有上一页才返回
  262. } else {
  263. // 如果是首页,跳转到某个默认页面(如首页)
  264. uni.reLaunch({ url: '/pages/home/index' });
  265. }
  266. },
  267. tabChange(item) {
  268. this.current=item.index
  269. this.isScrollUpdating = true;
  270. if ([0, 2, 3].includes(this.current)) {
  271. const scrollMap = {
  272. 0: 0,
  273. 2: this.evaluateTop,
  274. 3: this.storeDetailTop
  275. };
  276. setTimeout(()=>{
  277. uni.pageScrollTo({
  278. scrollTop: scrollMap[this.current] || 0 ,
  279. duration: 0,
  280. complete: () => {
  281. this.isScrollUpdating = false;
  282. }
  283. });
  284. },100)
  285. }
  286. },
  287. toSearch() {
  288. uni.navigateTo({
  289. url: '/pages_shopping/home/productSearch?storeId='+this.storeId
  290. })
  291. },
  292. handleAdvClick(item){
  293. if(item.showType==1){
  294. uni.setStorageSync('url',item.advUrl);
  295. uni.navigateTo({
  296. url:"/pages_shopping/home/h5"
  297. })
  298. }
  299. else if(item.showType==2){
  300. uni.navigateTo({
  301. url:item.advUrl
  302. })
  303. }
  304. else if(item.showType==3){
  305. uni.setStorageSync('content',item.content);
  306. uni.navigateTo({
  307. url:"/pages_shopping/home/content"
  308. })
  309. }
  310. },
  311. getAdv(){
  312. let data = {advType:2};
  313. getAdv(data).then(
  314. res => {
  315. if(res.code==200){
  316. this.advs=res.data;
  317. }
  318. },
  319. rej => {}
  320. );
  321. },
  322. getProductCate(){
  323. let data = {
  324. // storeId: this.storeId
  325. };
  326. getProductCate(data).then(
  327. res => {
  328. if(res.code==200){
  329. this.allCates=res.data;
  330. this.cates = this.allCates.filter(function (item) {
  331. return item.pid==0
  332. });
  333. if(this.cates!=null&&this.cates.length>0){
  334. this.cateSelect=this.cates[0].cateId;
  335. this.form.cateId = this.cates[0].cateId;
  336. // this.form.pid = this.cates[0].pid;
  337. this.mescroll&&this.mescroll.resetUpScroll()
  338. }
  339. }else{
  340. uni.showToast({
  341. icon:'none',
  342. title: "请求失败",
  343. });
  344. }
  345. },
  346. rej => {}
  347. );
  348. },
  349. // 药品分类选择
  350. choseCate(item) {
  351. this.cateSelect = item.cateId;
  352. // this.getSubCate()
  353. this.form.cateId = item.cateId;
  354. this.mescroll.resetUpScroll()
  355. },
  356. getSubCate(){
  357. var that=this;
  358. this.subCates = this.allCates.filter(function (item) {
  359. // let subList = that.allCates.filter(child => {
  360. // //返回每一项的子级数组
  361. // return child.pid === item.cateId
  362. // });
  363. // subList.length > 0 ? item.children = subList : [];
  364. return item.pid==that.cateSelect
  365. });
  366. },
  367. // 查看药品详情
  368. showProductList(item) {
  369. uni.navigateTo({
  370. url: '/pages_shopping/productList?cateId='+item.cateId+"&pid="+item.pid+'&storeId='+this.storeId
  371. })
  372. },
  373. goSearch(e) {
  374. if(e.detail.value!=null&&e.detail.value!=""){
  375. this.$addHisSearch(e.detail.value);
  376. }
  377. uni.navigateTo({
  378. url: '/pages_shopping/home/productList?storeId='+this.storeId+'&searchValue=' + e.detail.value
  379. })
  380. },
  381. goStoreDetail() {
  382. uni.navigateTo({
  383. url: '/pages_store/storeDetail?storeId='+this.storeId
  384. })
  385. },
  386. mescrollInit(mescroll) {
  387. this.mescroll = mescroll;
  388. },
  389. /*下拉刷新的回调 */
  390. downCallback(mescroll) {
  391. mescroll.resetUpScroll()
  392. },
  393. upCallback(page) {
  394. //联网加载数据
  395. var that = this;
  396. this.form.page=page.num;
  397. this.form.pageSize=page.size;
  398. getProducts(this.form).then(res => {
  399. if(res.code==200){
  400. //设置列表数据
  401. if (page.num == 1) {
  402. that.dataList = res.data.list;
  403. } else {
  404. that.dataList = that.dataList.concat(res.data.list);
  405. }
  406. that.mescroll.endBySize(res.data.list.length, res.data.total);
  407. }else{
  408. uni.showToast({
  409. icon:'none',
  410. title: "请求失败",
  411. });
  412. that.dataList = null;
  413. that.mescroll.endErr();
  414. }
  415. });
  416. },
  417. moreEvaluate() {
  418. uni.navigateTo({
  419. url: '/pages_shopping/evaluate?storeId='+this.storeId,
  420. })
  421. },
  422. getCommentByUser(){
  423. const param = {
  424. page: 1,
  425. pageSize: 2,
  426. storeId:this.storeId,
  427. orderId: null,
  428. productIds:null,
  429. userId: uni.getStorageSync('userId') || null,
  430. showSelf: 0
  431. }
  432. selectCommentByUser(param).then(res=>{
  433. if(res.code==200) {
  434. this.evaluate = res.data.list
  435. this.evaluateTotal = res.data.total
  436. } else {
  437. this.evaluate = []
  438. this.evaluateTotal = 0
  439. }
  440. this.getElementTop('evaluate');
  441. })
  442. }
  443. }
  444. }
  445. </script>
  446. <style lang="scss" scoped>
  447. .evaluate {
  448. padding: 30rpx 30rpx 0 30rpx;
  449. background-color: #FFFFFF;
  450. margin-bottom: 24rpx;
  451. .title {
  452. font-family: PingFang SC, PingFang SC;
  453. font-weight: 600;
  454. font-size: 30rpx;
  455. color: #222222;
  456. padding-bottom: 24rpx;
  457. }
  458. .footer-desc {
  459. text-align: center;
  460. padding: 0 32rpx 24rpx 0;
  461. font-size: 28rpx;
  462. color: #999;
  463. image{
  464. margin-left: 10rpx;
  465. width:15rpx;
  466. height:20rpx;
  467. }
  468. }
  469. }
  470. .storebox {
  471. padding: 26rpx 32rpx;
  472. font-family: PingFang SC, PingFang SC;
  473. color: #FFFFFF;
  474. .logo {
  475. width: 104rpx;
  476. height: 104rpx;
  477. background: #FFFFFF;
  478. border-radius: 16rpx 16rpx 16rpx 16rpx;
  479. margin-right: 26rpx;
  480. }
  481. .storename {
  482. font-weight: 500;
  483. font-size: 32rpx;
  484. }
  485. .storedesc {
  486. margin-top: 12rpx;
  487. font-weight: 400;
  488. font-size: 22rpx;
  489. }
  490. .storebox-r {
  491. flex: 1;
  492. overflow: hidden;
  493. }
  494. .storebox-btn {
  495. flex-shrink: 0;
  496. padding: 10rpx 16rpx;
  497. background: rgba(46, 218, 212, 0.50);
  498. font-size: 28rpx;
  499. border-radius: 8rpx 8rpx 8rpx 8rpx;
  500. }
  501. }
  502. .content{
  503. height: 100%;
  504. display: flex;
  505. flex-direction: column;
  506. .top-content{
  507. position: fixed;
  508. left: 0;
  509. top: 0;
  510. width: 100%;
  511. z-index: 10;
  512. background-repeat: no-repeat;
  513. background-image: url('https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/app/image/index_img/home_top_bg.png');
  514. background-size: 100% 100%;
  515. .top-title{
  516. height: 88upx;
  517. line-height: 88upx;
  518. font-size: 42upx;
  519. font-family: Source Han Sans CN;
  520. font-weight: bold;
  521. color: #222222;
  522. padding-left: 41upx;
  523. background-color: transparent;
  524. display: flex;
  525. align-items: center;
  526. }
  527. .search-cont{
  528. padding: 6upx 30upx;
  529. .inner{
  530. box-sizing: border-box;
  531. width: 70%;
  532. height: 72upx;
  533. background: #FFFFFF;
  534. border-radius: 36upx;
  535. display: flex;
  536. align-items: center;
  537. padding: 0 30upx;
  538. .icon-search{
  539. width: 28upx;
  540. height: 28upx;
  541. margin-right: 20upx;
  542. }
  543. input{
  544. height: 60upx;
  545. line-height: 60upx;
  546. flex: 1;
  547. }
  548. }
  549. }
  550. }
  551. .medic-box{
  552. display: flex;
  553. background: #fff;
  554. // ::v-deep{
  555. // .mescroll-body, .mescroll-body{
  556. // padding-left: 204rpx;
  557. // }
  558. // }
  559. .cate-list{
  560. position: fixed;
  561. left: 0;
  562. z-index: 999;
  563. box-sizing: border-box;
  564. width: 180upx;
  565. background: #F2F5F9;
  566. display: flex;
  567. flex-direction: column;
  568. padding: 20upx 0;
  569. overflow-y: scroll;
  570. .item{
  571. height: 100upx;
  572. line-height: 100upx;
  573. padding-left: 20upx;
  574. font-size: 28upx;
  575. font-family: PingFang SC;
  576. font-weight: 500;
  577. color: #333333;
  578. position: relative;
  579. overflow: hidden;
  580. white-space: nowrap;
  581. text-overflow: ellipsis;
  582. &.active{
  583. color: #2583EB;
  584. &::after{
  585. content: "";
  586. width: 8upx;
  587. height: 50upx;
  588. background: #2583EB;
  589. position: absolute;
  590. top: 25upx;
  591. left: 0;
  592. }
  593. }
  594. }
  595. }
  596. .medic{
  597. overflow: hidden;
  598. box-sizing: border-box;
  599. .banner-box{
  600. margin-top: 30rpx;
  601. width: 100%;
  602. height: 160upx;
  603. border-radius: 10upx;
  604. overflow: hidden;
  605. .swiper,
  606. .swiper-item,
  607. .swiper-item image{
  608. width: 100%;
  609. height: 100%;
  610. }
  611. }
  612. }
  613. }
  614. }
  615. </style>