storeIndex.vue 17 KB

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