CateFour.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. <template>
  2. <view :class="['qn-page-' + theme]">
  3. <view class="tabs-view" v-if="tlist.length">
  4. <u-tabs
  5. height="70"
  6. inactive-color="#2A2A2A"
  7. :active-color="primaryColor"
  8. :bar-style="{ borderRadius: '0', height: '4rpx', backgroundColor: primaryColor }"
  9. :list="tlist"
  10. name="title"
  11. font-size="28"
  12. :is-scroll="true"
  13. :current="cate_current"
  14. @change="cateChange($event)"
  15. ></u-tabs>
  16. </view>
  17. <view class="clearfix main-cont" :style="mainStyle">
  18. <view class="float_left">
  19. <scroll-view scroll-y class="left-aside">
  20. <view v-for="(item, index) in flist" :key="index" class="f-item ellipsis" :class="{ active: item.id === one_id }" @click="tabtap(item, 1)">
  21. <view v-if="item.id === one_id" class="active-line primary-bg"></view>
  22. {{ item.title }}
  23. </view>
  24. </scroll-view>
  25. </view>
  26. <view class="float_right">
  27. <view class="search-view">
  28. <view class="search-li" @click="changeSearch('zh')">综合</view>
  29. <view class="search-li" @click="changeSearch('xl')">
  30. 销量
  31. <view class="arrow-icon arrow-up"><u-icon name="arrow-up-fill" :color="sortt === 1 ? primaryColor : '#6c6c6c'" size="10"></u-icon></view>
  32. <view class="arrow-icon arrow-down"><u-icon name="arrow-down-fill" :color="sortt === 2 ? primaryColor : '#6c6c6c'" size="10"></u-icon></view>
  33. </view>
  34. <view class="search-li" @click="openKey('show_brand')">
  35. <text style="margin-right: 10rpx;">品牌</text>
  36. <u-icon color="#6c6c6c" name="arrow-down" size="20"></u-icon>
  37. </view>
  38. <view class="search-li" @click="openKey('show_support')">
  39. <text style="margin-right: 10rpx;">其他</text>
  40. <u-icon color="#6c6c6c" name="arrow-down" size="20"></u-icon>
  41. </view>
  42. </view>
  43. <!-- 品牌选择 -->
  44. <view class="cate-down-view" v-if="show_brand">
  45. <view class="search-pop">
  46. <view class="head-view clearfix">
  47. <text class="float_left">商品品牌</text>
  48. <view class="float_right" @click.stop="closeKey('show_brand')"><u-icon color="#8f8f8f" size="28" name="arrow-down"></u-icon></view>
  49. </view>
  50. <view class="cate-cont">
  51. <block v-for="(item, index) in brand_list" :key="index">
  52. <view class="cate-li ellipsis" :class="[brandId_zc.indexOf(item.id) > -1 ? 'primary-btn-pain' : '']" @click.stop="brandChange(item.id)">
  53. {{ item.title }}
  54. </view>
  55. </block>
  56. </view>
  57. <view class="btn-ul">
  58. <view class="btn-li primary-btn-pain" @click="resetBrand">重置</view>
  59. <view class="btn-li primary-bg" @click="confirmBrand">确认</view>
  60. </view>
  61. </view>
  62. </view>
  63. <!-- 商品服务选择 -->
  64. <view class="cate-down-view" v-if="show_support">
  65. <view class="search-pop">
  66. <view class="head-view clearfix">
  67. <text class="float_left">商品服务</text>
  68. <view class="float_right" @click.stop="closeKey('show_support')"><u-icon color="#8f8f8f" size="28" name="arrow-down"></u-icon></view>
  69. </view>
  70. <view class="cate-cont">
  71. <block v-for="(item, index) in support_list" :key="index">
  72. <view class="cate-li ellipsis" :class="[supplier_zc.indexOf(item.id) > -1 ? 'primary-btn-pain' : '']" @click.stop="supportChange(item.id)">
  73. {{ item.servicesName }}
  74. </view>
  75. </block>
  76. </view>
  77. <view class="btn-ul">
  78. <view class="btn-li primary-btn-pain" @click="resetSupport">重置</view>
  79. <view class="btn-li primary-bg" @click="confirmSupport">确认</view>
  80. </view>
  81. </view>
  82. </view>
  83. <!-- 三级下拉菜单 -->
  84. <view class="cate-down-view" @click="changeThreeCate(false)" v-if="show_cate">
  85. <view @click.stop="changeThreeCate(true)">
  86. <view class="head-view clearfix">
  87. <text class="float_left">{{ two_cate }}</text>
  88. <view class="float_right" @click.stop="changeThreeCate(false)"><u-icon color="#8f8f8f" size="28" name="arrow-down"></u-icon></view>
  89. </view>
  90. <view class="cate-cont">
  91. <view
  92. v-for="(item, index) in three_cate"
  93. :key="index"
  94. class="cate-li"
  95. :class="[three_id === item.id ? 'primary-btn-pain' : '']"
  96. @click.stop="threeCateChange(item)"
  97. >
  98. {{ item.title }}
  99. </view>
  100. </view>
  101. </view>
  102. </view>
  103. <view class="right-aside clearfix">
  104. <view class="three-cate" v-if="three_cate.length">
  105. <scroll-view :scroll-x="true" class="three-cate-scroll">
  106. <view
  107. v-for="(item, index) in three_cate"
  108. :key="index"
  109. :class="[three_id === item.id ? 'primary-btn-pain' : '']"
  110. class="cate-li"
  111. @click="threeCateChange(item)"
  112. >
  113. {{ item.title }}
  114. </view>
  115. </scroll-view>
  116. <view class="down-btn" @click="changeThreeCate(true)"><u-icon color="#8f8f8f" size="28" name="arrow-down"></u-icon></view>
  117. </view>
  118. <!-- 循环item出来为对象 -->
  119. <scroll-view
  120. class="right-aside-scroll"
  121. :style="goodsScrollHeight"
  122. scroll-y
  123. lower-threshold="100px"
  124. @scrolltolower="lower"
  125. v-if="shoppingList.length > 0"
  126. :scroll-top="scroll_top_num"
  127. >
  128. <view class="goods-li" v-for="(item, index) in shoppingList" :key="index">
  129. <GoodsItem :isList="true" :item="item" @addCart="addCard(item.id)"></GoodsItem>
  130. </view>
  131. <u-loadmore margin-top="20" v-if="shoppingList.length" :status="loading_status" />
  132. </scroll-view>
  133. <Aempty text="没有商品" src="https://onlineimg.qianniao.vip/search.png" v-else></Aempty>
  134. </view>
  135. </view>
  136. <AddCardModel :selAddress="selAddressD" @close="cardModelPopChange" :isShow="is_add_show" :goodsId="goods_id" />
  137. </view>
  138. </view>
  139. </template>
  140. <script>
  141. import GoodsItem from '@/components/GoodsItem.vue';
  142. import Login from '@/components/Login.vue';
  143. import AddCardModel from '@/components/AddCardModel';
  144. export default {
  145. components: {
  146. AddCardModel,
  147. GoodsItem,
  148. Login
  149. },
  150. data() {
  151. return {
  152. show_support: false,
  153. show_brand: false,
  154. show_cate: false,
  155. cate_current: 0,
  156. is_add_show: false,
  157. goods_id: 0,
  158. loading_status: 'loadmore',
  159. isShow: false,
  160. scroll_top_num: 0,
  161. sizeCalcState: false,
  162. tabScrollTop: 0,
  163. currentId: 1,
  164. flist: [],
  165. slist: [],
  166. shoppingList: [],
  167. tlist: [],
  168. priceInfo: [],
  169. before_cartNum: 0,
  170. page: 1,
  171. pageSize: 10,
  172. pageTotal: 0,
  173. selAddressD: {},
  174. three_cate: [],
  175. two_cate: '',
  176. three_id: 0,
  177. one_id: 0,
  178. brandId_zc: [],
  179. brand_list: [], // 商品品牌列表
  180. support_list: [], // 商品服务列表
  181. supplier_zc: [],
  182. support: [], //商品服务
  183. brandId: [], // 品牌多选
  184. // sort 是js保留字段,所以定义为 sortt
  185. sortt: '' // 销量 1是从大到小,2是从小到大, 默认不传
  186. };
  187. },
  188. props: {
  189. isLogin: {
  190. type: Boolean,
  191. default: true
  192. },
  193. selAddress: {
  194. type: Object,
  195. default: () => {
  196. return {};
  197. }
  198. }
  199. },
  200. computed: {
  201. cartNum() {
  202. return this.$store.state.cartNum;
  203. },
  204. // 判断手机是否有刘海
  205. isBang() {
  206. return this.$_utils.modelmes();
  207. },
  208. mainStyle() {
  209. return `paddingTop: ${this.tlist.length > 0 ? '0' : '12rpx'};height: calc(100vh - 112rpx - ${this.isBang ? '84px' : '50px'} - ${
  210. this.tlist.length > 0 ? '80rpx' : '0rpx'
  211. })`;
  212. },
  213. goodsScrollHeight() {
  214. return `height:${this.three_cate.length ? 'calc(100% - 62rpx - 90rpx)' : 'calc(100% - 62rpx)'}`;
  215. },
  216. userId() {
  217. return this.$store.state.userStatus.id;
  218. }
  219. },
  220. watch: {
  221. selAddress(val) {
  222. this.selAddressD = val;
  223. },
  224. '$store.state.locationObj'(val) {
  225. if (JSON.stringify(val) === '{}') {
  226. return;
  227. }
  228. this.shoppingList = [];
  229. this.pageSize = 10;
  230. this.getGoodsByCategory();
  231. },
  232. async isLogin(Nval) {
  233. this.tlist = [];
  234. if (Nval) {
  235. this.shoppingList = [];
  236. this.pageSize = 10;
  237. await this.getAllCategory();
  238. await this.getGoodsByCategory();
  239. }
  240. }
  241. },
  242. async created() {
  243. await this.getAllCategory();
  244. await this.getAllGoodsSupport();
  245. await this.getAllBrand();
  246. },
  247. methods: {
  248. changeSearch(tag) {
  249. if (tag === 'zh') {
  250. this.brandId = [];
  251. this.sortt = '';
  252. this.support = [];
  253. } else if (tag === 'xl') {
  254. if (this.sortt === 2) {
  255. this.sortt = 1;
  256. } else {
  257. this.sortt = 2;
  258. }
  259. }
  260. this.page = 1;
  261. this.getGoodsByCategory();
  262. },
  263. // 选择品牌
  264. brandChange(id) {
  265. const index = this.brandId_zc.indexOf(id);
  266. if (index > -1) {
  267. this.brandId_zc.splice(index, 1);
  268. } else {
  269. this.brandId_zc.push(id);
  270. }
  271. },
  272. confirmBrand() {
  273. this.brandId = this.brandId_zc;
  274. this.page = 1;
  275. this.getGoodsByCategory();
  276. this.closeKey('show_brand');
  277. },
  278. // 选择服务
  279. supportChange(id) {
  280. const index = this.supplier_zc.indexOf(id);
  281. if (index > -1) {
  282. this.supplier_zc.splice(index, 1);
  283. } else {
  284. this.supplier_zc.push(id);
  285. }
  286. },
  287. resetBrand() {
  288. this.brandId = [];
  289. this.page = 1;
  290. this.getGoodsByCategory();
  291. this.closeKey('show_brand');
  292. },
  293. resetSupport() {
  294. this.support = [];
  295. this.page = 1;
  296. this.getGoodsByCategory();
  297. this.closeKey('show_support');
  298. },
  299. confirmSupport() {
  300. this.support = this.supplier_zc;
  301. this.page = 1;
  302. this.getGoodsByCategory();
  303. this.closeKey('show_support');
  304. },
  305. openKey(key) {
  306. if (key === 'show_support') {
  307. this.supplier_zc = this.$u.deepClone(this.support);
  308. } else {
  309. this.brandId_zc = this.$u.deepClone(this.brandId);
  310. }
  311. this[key] = true;
  312. },
  313. closeKey(key) {
  314. this[key] = false;
  315. },
  316. // 打开购物车
  317. cardModelPopChange(obj) {
  318. this.is_add_show = false;
  319. },
  320. // 加入购物车
  321. addCard(id) {
  322. this.goods_id = id;
  323. this.is_add_show = true;
  324. },
  325. changeThreeCate(show) {
  326. this.show_cate = show;
  327. },
  328. // 分类列表 getAllCategory
  329. getAllCategory() {
  330. this.$u.api
  331. .getAllCategory({
  332. userCenterId: this.userId || 0
  333. })
  334. .then(data => {
  335. this.flist = data.data;
  336. if (data.data.length) {
  337. this.tlist = data.data[0].children || [];
  338. this.currentId = data.data[0].id;
  339. this.one_id = data.data[0].id;
  340. // 二级菜单添加全部按钮
  341. if (this.tlist.length) {
  342. this.tlist.unshift({
  343. title: '全部',
  344. id: data.data[0].id,
  345. pid: 0
  346. });
  347. }
  348. }
  349. this.getGoodsByCategory();
  350. });
  351. },
  352. // 上拉加载
  353. lower(e) {
  354. if (this.pageTotal / this.pageSize > this.page) {
  355. this.page += 1;
  356. this.getGoodsByCategory();
  357. }
  358. },
  359. // 获取商品列表
  360. getGoodsByCategory() {
  361. this.loading_status = 'loading';
  362. this.isShow = false;
  363. this.$u.api
  364. .getGoodsByCategory({
  365. categoryId: this.three_id || this.currentId,
  366. page: this.page,
  367. pageSize: this.pageSize,
  368. brandId: this.brandId,
  369. sort: this.sortt,
  370. support: this.support
  371. })
  372. .then(data => {
  373. this.scroll_top_num = 1;
  374. const goods = data.data.map(item => {
  375. return {
  376. ...item,
  377. isShow: false
  378. };
  379. });
  380. if (this.page === 1) {
  381. this.shoppingList = goods;
  382. } else {
  383. this.shoppingList = this.shoppingList.concat(goods);
  384. }
  385. this.pageTotal = data.pageTotal;
  386. this.loading_status = this.$_utils.loadStatus(this.page, this.pageSize, this.pageTotal);
  387. });
  388. },
  389. //一级分类点击
  390. tabtap(item, lever) {
  391. this.currentId = item.id;
  392. this.changeThreeCate(false);
  393. if (lever === 1) {
  394. this.one_id = item.id;
  395. // 一级菜单
  396. this.cate_current = 0;
  397. const tlist = this.flist.find(cate => cate.id === item.id);
  398. this.tlist = tlist.children || [];
  399. // 二级菜单添加全部按钮
  400. if (this.tlist.length && !this.tlist.find(cate => cate.title === '全部')) {
  401. this.tlist.unshift({
  402. title: '全部',
  403. id: item.id
  404. });
  405. }
  406. this.three_id = 0;
  407. this.three_cate = [];
  408. } else if (lever === 2) {
  409. // 二级菜单
  410. this.two_cate = item.title;
  411. // 三级分类
  412. this.three_cate = item.children || [];
  413. // 三级分类添加全部按钮
  414. if (this.three_cate.length && !this.three_cate.find(cate => cate.title === '全部')) {
  415. this.three_cate.unshift({
  416. title: '全部',
  417. id: item.id
  418. });
  419. }
  420. this.three_id = item.id;
  421. }
  422. this.page = 1;
  423. this.shoppingList = [];
  424. this.$nextTick(() => {
  425. this.scroll_top_num = 0;
  426. });
  427. // 商品列表的切换
  428. this.getGoodsByCategory();
  429. // 品牌列表切换
  430. this.getAllBrand();
  431. },
  432. cateChange(index) {
  433. this.cate_current = index;
  434. // 商品列表的切换
  435. this.tabtap(this.tlist[index], 2);
  436. },
  437. threeCateChange(row) {
  438. this.three_id = row.id;
  439. this.tabtap(row, 3);
  440. },
  441. // 商品服务
  442. async getAllGoodsSupport() {
  443. await this.$u.api
  444. .getAllGoodsSupport({
  445. page: 1,
  446. pageSize: 100
  447. })
  448. .then(res => {
  449. this.support_list = res.data;
  450. });
  451. },
  452. // 商品品牌
  453. async getAllBrand() {
  454. await this.$u.api
  455. .getAllBrand({
  456. page: 1,
  457. pageSize: 999,
  458. categoryId: this.three_id || this.currentId
  459. })
  460. .then(res => {
  461. this.brand_list = res.data;
  462. });
  463. }
  464. }
  465. };
  466. </script>
  467. <style lang="scss">
  468. .tabs-view {
  469. border-bottom: 1px solid #eeeeee;
  470. font-weight: 510;
  471. }
  472. .main-cont {
  473. overflow: hidden;
  474. .float_left {
  475. height: 100%;
  476. .left-aside {
  477. width: 182upx;
  478. height: 100%;
  479. background-color: #f5f6f7;
  480. .f-item {
  481. -webkit-line-clamp: 1;
  482. width: 100%;
  483. height: 80upx;
  484. line-height: 80rpx;
  485. margin: 13rpx 0;
  486. text-align: center;
  487. font-size: 28upx;
  488. color: #4b4b4b;
  489. position: relative;
  490. &.active {
  491. color: #000000;
  492. font-weight: bold;
  493. background-color: #ffffff;
  494. }
  495. .active-line {
  496. position: absolute;
  497. left: 22rpx;
  498. top: 50%;
  499. transform: translateY(-50%);
  500. height: 24upx;
  501. width: 4upx;
  502. border-radius: 4rpx;
  503. }
  504. }
  505. }
  506. }
  507. .float_right {
  508. height: 100%;
  509. position: relative;
  510. .search-view {
  511. display: flex;
  512. font-size: 24rpx;
  513. text-align: center;
  514. line-height: 60rpx;
  515. border-bottom: 1px solid #eeeeee;
  516. .search-li {
  517. flex: 4;
  518. position: relative;
  519. .arrow-icon {
  520. /* #ifdef H5 */
  521. transform: scale(0.5, 0.5);
  522. /* #endif */
  523. position: absolute;
  524. right: 20rpx;
  525. color: #6c6c6c;
  526. }
  527. .arrow-down {
  528. top: 6rpx;
  529. }
  530. .arrow-up {
  531. bottom: 14rpx;
  532. }
  533. }
  534. }
  535. .cate-down-view {
  536. width: 100%;
  537. position: absolute;
  538. top: 0;
  539. left: 0;
  540. height: 100%;
  541. background-color: rgba(0, 0, 0, 0.5);
  542. z-index: 999;
  543. .head-view {
  544. line-height: 86rpx;
  545. font-size: 24rpx;
  546. color: #666666;
  547. background-color: #ffffff;
  548. padding: 0 24rpx;
  549. }
  550. .cate-cont {
  551. display: flex;
  552. flex-wrap: wrap;
  553. max-height: 420rpx;
  554. overflow: auto;
  555. background-color: #ffffff;
  556. .cate-li {
  557. text-align: center;
  558. display: inline-block;
  559. width: 150rpx;
  560. border: 1px solid #c6c6c6;
  561. height: 48rpx;
  562. line-height: 48rpx;
  563. font-size: 24rpx;
  564. margin-left: 24rpx;
  565. border-radius: 66rpx;
  566. margin-bottom: 20rpx;
  567. -webkit-line-clamp: 1;
  568. }
  569. }
  570. }
  571. .right-aside {
  572. position: relative;
  573. height: 100%;
  574. width: 568upx;
  575. overflow: hidden;
  576. background-color: #ffffff;
  577. .three-cate {
  578. position: relative;
  579. .three-cate-scroll {
  580. padding: 20rpx 0;
  581. width: 100%;
  582. white-space: nowrap;
  583. .cate-li {
  584. padding: 0 20rpx;
  585. display: inline-block;
  586. font-size: 20rpx;
  587. margin-left: 10rpx;
  588. border: 1px solid #c6c6c6;
  589. border-radius: 50rpx;
  590. height: 50rpx;
  591. line-height: 50rpx;
  592. &:last-child {
  593. margin-right: 60rpx;
  594. }
  595. }
  596. }
  597. .down-btn {
  598. position: absolute;
  599. background-color: #ffffff;
  600. width: 60rpx;
  601. text-align: center;
  602. right: 0;
  603. top: 0;
  604. height: 90rpx;
  605. line-height: 90rpx;
  606. }
  607. }
  608. .right-aside-scroll {
  609. height: 100%;
  610. .goods-li {
  611. border-bottom: 1px solid #f4f5f6;
  612. }
  613. }
  614. .nullSty {
  615. font-size: 26upx;
  616. text-align: center;
  617. vertical-align: middle;
  618. color: #999;
  619. position: absolute;
  620. top: 50%;
  621. left: 50%;
  622. transform: translate(-50%, -50%);
  623. image {
  624. width: 240upx;
  625. height: 160upx;
  626. margin-bottom: 30upx;
  627. }
  628. }
  629. }
  630. }
  631. }
  632. .search-pop {
  633. background-color: #ffffff;
  634. padding-bottom: 20rpx;
  635. .btn-ul {
  636. display: flex;
  637. padding-top: 20rpx;
  638. .btn-li {
  639. flex: 2;
  640. margin: 0 30rpx;
  641. border: 1px solid $uni-color-primary;
  642. border-radius: 8rpx;
  643. line-height: 50rpx;
  644. font-size: 24rpx;
  645. text-align: center;
  646. }
  647. }
  648. }
  649. </style>