brand.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <template>
  2. <view class="">
  3. <!-- <view class="" :style="{height: navHeight+'px' }"></view> -->
  4. <u-navbar
  5. :placeholder="true"
  6. title="品牌导览"
  7. :autoBack="true"
  8. :safeAreaInsetTop="true"
  9. >
  10. </u-navbar>
  11. <view class="search-wrap">
  12. <u-search
  13. placeholder="请输入搜索的商品"
  14. :clearabled="true"
  15. :showAction="false"
  16. height="80rpx"
  17. @search="search"
  18. @custom="search"
  19. @clear="reloadList"
  20. bgColor="#fff"
  21. borderColor="#00A447"
  22. v-model="params.goodsName">
  23. </u-search>
  24. </view>
  25. <view class="out-wrap u-flex u-col-top">
  26. <view class="types">
  27. <view class="type"
  28. :class="{active:index==typesIndex}"
  29. @click="typesClick(index)"
  30. v-for="(item,index) in goodsTypeTree" :key="item.parentId+index">
  31. {{item.name}}
  32. </view>
  33. </view>
  34. <view class="right">
  35. <view class="second-types">
  36. <view class="u-flex u-row-between u-col-top u-border-bottom">
  37. <view class="u-flex u-flex-wrap">
  38. <view class="type"
  39. :class="{active:index==secondTypesIndex}"
  40. @click="secondTypesClick(index)"
  41. v-for="(item,index) in subTypeList" :key="item.id">
  42. {{item.name}}
  43. </view>
  44. </view>
  45. <u-icon
  46. @click="showMoreSecondTypes"
  47. v-if="subTypeListMore.length>0"
  48. size="24px"
  49. :name="showMoreSecondTypesIcon"></u-icon>
  50. </view>
  51. <view class="more-second-types u-flex" v-if="moreSecondTypes">
  52. <view class="type"
  53. :class="{active:index==moreSecondTypesIndex}"
  54. @click="moreSecondTypesClick(index)"
  55. v-for="(item,index) in subTypeListMore" :key="item.id">
  56. {{item.name}}
  57. </view>
  58. </view>
  59. </view>
  60. <mescroll-body class="mescroll-body" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
  61. <view class="page-wrap" @click="$u.route('/brand/branddetails',{id:item.id})" v-for="item in dataList" :key="item.id">
  62. <view class="hot">
  63. <view class="product small-product u-flex">
  64. <u--image :showLoading="true" :src="item.mainImg" width="160rpx" height="160rpx"></u--image>
  65. <view class="text">
  66. <view class="name ellipsis-2">{{item.goodsName}}</view>
  67. <view class="u-flex u-row-between">
  68. <view class="left">
  69. <view class="up">
  70. <view class="u-flex">
  71. <text class="price">¥ <text class="price-num">{{item.vipPrice}}</text></text>
  72. <!-- <text class="vip-icon">VIP</text> -->
  73. <text class="price-type">会员价</text>
  74. </view>
  75. <!-- <view class="" v-else>
  76. <text class="price">¥ <text class="price-num">{{item.salePrice}}</text></text>
  77. </view> -->
  78. </view>
  79. <view class="down">
  80. <!-- <text class="discount">8.8折</text> -->
  81. <text class="original-price gray line-through">¥ {{item.salePrice}}</text>
  82. <!-- <text class="sales gray">销量 {{item.saleCount}}</text> -->
  83. </view>
  84. </view>
  85. <u--image :showLoading="false" @click.native.stop="addCart(item.id)" :src="staticUrl+'/img/add.png'" width="48rpx" height="48rpx"></u--image>
  86. </view>
  87. </view>
  88. </view>
  89. </view>
  90. </view>
  91. </mescroll-body>
  92. </view>
  93. </view>
  94. <!-- <tabbar :tabbarIndexProps="Number(1)" /> -->
  95. <u-toast ref="uToast"></u-toast>
  96. </view>
  97. </template>
  98. <script>
  99. import { systemInfo } from "@/mixin.js";
  100. // 引入mescroll-mixins.js
  101. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  102. import tabbar from "../components/tabbar.vue";
  103. export default {
  104. mixins: [MescrollMixin,systemInfo], // 使用mixin
  105. components: {
  106. tabbar
  107. },
  108. data() {
  109. return {
  110. staticUrl:this.$commonConfig.staticUrl,
  111. typesIndex:0,
  112. secondTypesIndex:0,
  113. moreSecondTypesIndex:null,
  114. moreSecondTypes:false,
  115. showMoreSecondTypesIcon:'list',
  116. downOption: {},
  117. // 上拉加载的配置(可选, 绝大部分情况无需配置)
  118. upOption: {
  119. page: {
  120. size: 10 // 每页数据的数量,默认10
  121. },
  122. noMoreSize: 5, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
  123. empty: {
  124. tip: '暂无相关数据'
  125. }
  126. },
  127. //菜单
  128. goodsTypeTree:[],
  129. //子菜单
  130. subTypeList:[],
  131. subTypeListMore:[],
  132. // 列表数据
  133. dataList: [],
  134. params:{
  135. typeId:null,
  136. goodsName:'',
  137. // isExplode:0,//是否爆款 0不是,1是
  138. }
  139. }
  140. },
  141. watch:{
  142. typesIndex:{
  143. handler(val){
  144. console.log('typesIndex',val);
  145. this.params.goodsName = '' ;
  146. let data = uni.$u.deepClone(this.goodsTypeTree[val]);
  147. this.subTypeList = data.child.splice(0,3);
  148. this.subTypeListMore= data.child;
  149. this.secondTypesIndex = 0;
  150. this.moreSecondTypesIndex = null;
  151. this.mescroll.resetUpScroll();
  152. },
  153. immediate:false
  154. }
  155. },
  156. onLoad() {
  157. this.getSystemInfo();
  158. },
  159. onShow() {
  160. this.getgoodsTypeTree();
  161. },
  162. methods: {
  163. /*下拉刷新的回调, 重置列表为第一页 (此处可删,mixins已默认)
  164. downCallback(){
  165. this.mescroll.resetUpScroll();
  166. },
  167. /*上拉加载的回调*/
  168. upCallback(page) {
  169. // 此处可以继续请求其他接口
  170. // if(page.num == 1){
  171. // // 请求其他接口...
  172. // }
  173. if(this.moreSecondTypesIndex||this.moreSecondTypesIndex==0){
  174. this.params.typeId = this.subTypeListMore[this.moreSecondTypesIndex]?.id
  175. }else{
  176. this.params.typeId = this.subTypeList[this.secondTypesIndex]?.id
  177. }
  178. // 如果希望先请求其他接口,再触发upCallback,可参考以下写法
  179. if(!this.params.typeId){
  180. // this.getgoodsTypeTree();
  181. return // 此处return,先获取xx
  182. }
  183. console.log('this.params.typeId',this.params.typeId);
  184. let pageNum = page.num; // 页码, 默认从1开始
  185. let pageSize = page.size; // 页长, 默认每页10条
  186. this.params = Object.assign(this.params,{pageNum:pageNum,pageSize:pageSize});
  187. this.$u.api.memberGoodList(this.params).then(data => {
  188. console.log('data',JSON.parse(JSON.stringify(data)));
  189. // 接口返回的当前页数据列表 (数组)
  190. let curPageData = data.data.rows;
  191. console.log('curPageData',JSON.parse(JSON.stringify(curPageData)));
  192. // 接口返回的当前页数据长度 (如列表有26个数据,当前页返回8个,则curPageLen=8)
  193. let curPageLen = curPageData.length;
  194. // 接口返回的总页数 (如列表有26个数据,每页10条,共3页; 则totalPage=3)
  195. // let totalPage = data.data.data.totalPage;
  196. // 接口返回的总数据量(如列表有26个数据,每页10条,共3页; 则totalSize=26)
  197. let totalSize = data.data.total;
  198. // 接口返回的是否有下一页 (true/false)
  199. // let hasNext = data.xxx;
  200. // console.log('totalPage',totalPage,'curPageLen',curPageLen);
  201. //设置列表数据
  202. if(page.num == 1) this.dataList = []; //如果是第一页需手动置空列表
  203. this.dataList = this.dataList.concat(curPageData); //追加新数据
  204. // 请求成功,隐藏加载状态
  205. //方法一(推荐): 后台接口有返回列表的总页数 totalPage
  206. // this.mescroll.endByPage(curPageLen, totalPage);
  207. //方法二(推荐): 后台接口有返回列表的总数据量 totalSize
  208. this.mescroll.endBySize(curPageLen, totalSize);
  209. }).catch(err => {
  210. this.mescroll.endErr()
  211. console.log(err)
  212. });
  213. },
  214. /*若希望重新加载列表,只需调用此方法即可(内部会自动page.num=1,再主动触发up.callback)*/
  215. reloadList() {
  216. this.mescroll.resetUpScroll();
  217. },
  218. search(e){
  219. this.reloadList();
  220. },
  221. getgoodsTypeTree(){
  222. this.$u.api.goodsTypeTree().then(res=>{
  223. this.goodsTypeTree = res.data.filter(item=> item.child.length>0);
  224. console.log('this.goodsTypeTree',this.goodsTypeTree);
  225. let data = uni.$u.deepClone(this.goodsTypeTree[this.typesIndex]);
  226. // console.log('this.goodsTypeTree',this.goodsTypeTree);
  227. // console.log('data',data);
  228. this.subTypeList = data.child.splice(0,3);
  229. this.subTypeListMore= data.child;
  230. this.mescroll.resetUpScroll();
  231. }).catch(err=>{
  232. this.mescroll.endErr()
  233. console.log('getgoodsTypeTree',err);
  234. })
  235. },
  236. typesClick(index){
  237. this.typesIndex = index;
  238. },
  239. secondTypesClick(index){
  240. this.secondTypesIndex = index;
  241. this.moreSecondTypesIndex = null;
  242. this.mescroll.resetUpScroll();
  243. },
  244. moreSecondTypesClick(index){
  245. this.moreSecondTypesIndex = index;
  246. this.secondTypesIndex = null;
  247. this.mescroll.resetUpScroll();
  248. },
  249. showMoreSecondTypes(){
  250. // this.moreSecondTypes = !this.moreSecondTypes;
  251. if(this.showMoreSecondTypesIcon=='list'){
  252. this.showMoreSecondTypesIcon = 'close'
  253. this.subTypeList = this.subTypeList.concat(this.subTypeListMore)
  254. }else{
  255. this.showMoreSecondTypesIcon = 'list'
  256. this.subTypeList =this.subTypeList.splice(0,3);
  257. }
  258. },
  259. addCart(id){
  260. // console.log('addCart',id);
  261. this.$u.api.addCart({goodsId:id}).then(res=>{
  262. this.$refs.cartfixed.getCartList('isAdd');
  263. console.log('res',res.data);
  264. }).catch(err=>{
  265. console.log('addCart',err);
  266. })
  267. }
  268. }
  269. }
  270. </script>
  271. <style>
  272. page{
  273. /* padding-top: 0; */
  274. }
  275. </style>
  276. <style lang="scss" scoped>
  277. .out-wrap{
  278. background-color: #F5F5F5;
  279. .right{
  280. background-color: #fff;
  281. flex: 1;
  282. }
  283. }
  284. .types{
  285. width: 200rpx;
  286. font-size: 26rpx;
  287. text-align: center;
  288. font-weight: 600;
  289. .type{
  290. position: relative;
  291. padding: 25rpx 0;
  292. &.active{
  293. background-color: #fff;
  294. &:before{
  295. content: '';
  296. width: 4rpx;
  297. height: 1.6em;
  298. background-color: #00A447;
  299. position: absolute;
  300. left: 0;
  301. top: 50%;
  302. transform: translateY(-0.8em);
  303. }
  304. }
  305. }
  306. }
  307. .second-types{
  308. position: relative;
  309. font-size: 22rpx;
  310. padding: 20rpx 20rpx 0;
  311. background-color: #fff;
  312. .type{
  313. padding: 7rpx 22rpx;
  314. background-color: #F5F5F5;
  315. border-radius: 22rpx;
  316. margin-right: 20rpx;
  317. margin-bottom: 20rpx;
  318. &.active{
  319. background-color: #E5F6EC;
  320. color: #00A447;
  321. }
  322. }
  323. // .type + .type{
  324. // margin-left: 20rpx;
  325. // }
  326. .more-second-types{
  327. position: absolute;
  328. left: 0;
  329. right: 0;
  330. bottom: -120rpx;
  331. padding: 24px 20rpx;
  332. z-index: 99;
  333. background-color: #fff;
  334. box-shadow:
  335. 0px 4.5px 3.6px rgba(0, 0, 0, 0.024),
  336. 0px 12.5px 10px rgba(0, 0, 0, 0.035),
  337. 0px 30.1px 24.1px rgba(0, 0, 0, 0.046),
  338. 0px 100px 80px rgba(0, 0, 0, 0.07)
  339. ;
  340. }
  341. }
  342. .mescroll-body{
  343. background-color: #fff;
  344. }
  345. </style>