category.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. <template>
  2. <view class="rf-category">
  3. <!--顶部搜索导航栏-->
  4. <view class="input-box">
  5. <view class="iconfont iconzhuyedefuben" :class="'text-'+themeColor.name" @tap.stop="toHome"></view>
  6. <input
  7. @tap.stop="toSearch"
  8. disabled
  9. :value="hotSearchDefault || '请输入关键字'"
  10. style="color:#888;"
  11. placeholder-style="color:#ccc;"
  12. />
  13. <view class="iconfont iconsousuo2" @tap.stop="toSearch"></view>
  14. </view>
  15. <view>
  16. <img src="@/static/missing-face.png" alt="" class="introduceItemImg">
  17. </view>
  18. </view>
  19. </template>
  20. <script>
  21. /**
  22. * @des 分类
  23. *
  24. * @author stav stavyan@qq.com
  25. * @date 2020-03-10 18:19
  26. * @copyright 2019
  27. */
  28. import { productCate, productList, productDetail, cartItemCount, cartItemCreate } from '@/api/product';
  29. import rfSearchBar from '@/components/rf-search-bar';
  30. import rfAttrContent from '@/components/rf-attr-content';
  31. import { advList } from '@/api/basic';
  32. import { mapMutations } from 'vuex';
  33. export default {
  34. components: {
  35. rfSearchBar,
  36. rfAttrContent
  37. },
  38. data() {
  39. return {
  40. hotSearchDefault: '请输入关键字', // 搜索默认关键字
  41. showCategoryIndex: 0, // 一级菜单高亮显示序号
  42. categoryList: [], // 分类列表
  43. specClass: 'none', // 规格弹窗
  44. productDetail: {}, // 礼品详情
  45. search: {},
  46. cateTop: {}, // 分类通用广告图
  47. loading: true,
  48. styleCateType: this.$mSettingConfig.styleCateType,
  49. errorImage: this.$mAssetsPath.errorImage,
  50. currentCateId: '',
  51. categoryProductList: [],
  52. price: '',
  53. total_sales: '',
  54. loadingType: 'more',
  55. page: 1,
  56. moneySymbol: this.moneySymbol,
  57. productLoading: true,
  58. currentSecondCategoryList: [],
  59. categoryInvertedIndex: 0
  60. };
  61. },
  62. computed: {
  63. bottom () {
  64. let bottom = 0;
  65. /* #ifdef H5 */
  66. bottom = 90;
  67. /* #endif */
  68. return bottom;
  69. }
  70. },
  71. filters: {
  72. filterTotalSales(val) {
  73. if (val > 10000) {
  74. val = `${(val / 10000).toFixed(2)}w`;
  75. }
  76. return val;
  77. }
  78. },
  79. // 每次页面显示 执行该方法
  80. onLoad() {
  81. this.initData();
  82. },
  83. methods: {
  84. moveHandle() {
  85. },
  86. ...mapMutations(['setCartNum']),
  87. // 监听二级分类变化
  88. handleCategoryInvertedChange(item, index) {
  89. this.categoryInvertedIndex = index;
  90. this.currentCateId = item.id;
  91. this.price = '';
  92. this.total_sales = '';
  93. this.page = 1;
  94. this.categoryProductList = [];
  95. this.getProductList();
  96. },
  97. stopPrevent() {},
  98. // 规格弹窗开关
  99. toggleSpec(row) {
  100. if (parseInt(row.status, 10) === 0) return;
  101. if (this.specClass === 'show') {
  102. this.specClass = 'hide';
  103. if (row.stock === 0) {
  104. this.$mHelper.toast('库存不足');
  105. return;
  106. }
  107. if (row.type.toString() === '1') {
  108. // 加入购物车
  109. this.handleCartItemCreate(row.skuId, row.cartCount);
  110. } else if (row.type.toString() === '2') {
  111. // 立即购买
  112. const list = {};
  113. const data = {};
  114. data.sku_id = row.skuId;
  115. data.num = row.cartCount;
  116. if (
  117. this.productDetail.point_exchange_type.toString() === '2' ||
  118. this.productDetail.point_exchange_type.toString() === '4' ||
  119. (this.productDetail.point_exchange_type.toString() === '3' &&
  120. this.isPointExchange)
  121. ) {
  122. list.type = 'point_exchange';
  123. } else {
  124. list.type = 'buy_now';
  125. }
  126. list.data = JSON.stringify(data);
  127. this.navTo(`/pages/order/create/order?data=${JSON.stringify(list)}`);
  128. }
  129. setTimeout(() => {
  130. this.specClass = 'none';
  131. }, 250);
  132. } else if (this.specClass === 'none') {
  133. this.getProductDetail(row);
  134. }
  135. },
  136. // 添加礼品至购物车
  137. async handleCartItemCreate(skuId, cartCount) {
  138. await this.$http
  139. .post(`${cartItemCreate}`, {
  140. sku_id: skuId,
  141. num: cartCount
  142. })
  143. .then(async () => {
  144. await this.$http.get(`${cartItemCount}`).then(async r => {
  145. this.setCartNum(r.data);
  146. });
  147. this.$mHelper.toast('添加成功,在购物车等');
  148. });
  149. },
  150. hideSpec() {
  151. this.specClass = 'hide';
  152. setTimeout(() => {
  153. this.specClass = 'none';
  154. }, 250);
  155. },
  156. // 获取产品详情
  157. async getProductDetail(row) {
  158. await this.$http
  159. .get(`${productDetail}`, {
  160. id: row.id
  161. })
  162. .then(async r => {
  163. this.productDetail = r.data;
  164. this.specClass = 'show';
  165. });
  166. },
  167. // 跳转至礼品列表
  168. navTo(route) {
  169. this.$mRouter.push({ route });
  170. },
  171. // 数据初始化
  172. async initData() {
  173. this.search = uni.getStorageSync('search') || {};
  174. this.hotSearchDefault = this.search.hot_search_default || '请输入关键字';
  175. this.categoryList = [];
  176. this.categoryProductList = [];
  177. await this.getProductCate();
  178. await this.initCartItemCount();
  179. },
  180. // 设置购物车数量角标
  181. async initCartItemCount() {
  182. if (
  183. this.$mStore.getters.hasLogin &&
  184. parseInt(uni.getStorageSync('cartNum'), 10) > 0
  185. ) {
  186. uni.setTabBarBadge({
  187. index: this.$mConstDataConfig.cartIndex,
  188. text: uni.getStorageSync('cartNum').toString()
  189. });
  190. } else {
  191. uni.removeStorageSync('cartNum');
  192. uni.removeTabBarBadge({ index: this.$mConstDataConfig.cartIndex });
  193. }
  194. },
  195. // 获取礼品分类列表
  196. async getProductCate(type) {
  197. await this.$http
  198. .get(`${productCate}`)
  199. .then(async r => {
  200. if (type === 'refresh') {
  201. uni.stopPullDownRefresh();
  202. }
  203. // 获取分类广告图 注:广告图不是一级分类图
  204. await this.getAdvList();
  205. // 过滤掉没有二级菜单的一级菜单
  206. // r.data.forEach(item => {
  207. // if (item.child.length > 0) {
  208. // this.categoryList.push(item);
  209. // }
  210. // });
  211. this.categoryList = r.data;
  212. let cateId = uni.getStorageSync('indexToCateId');
  213. if (cateId) {
  214. this.categoryList.forEach((item, index) => {
  215. if (cateId === item.id) {
  216. this.showCategoryIndex = index;
  217. }
  218. });
  219. } else {
  220. if (this.styleCateType === 'one_two_product' && r.data[0].child.length > 0) {
  221. this.currentCateId = r.data[0].child[0].id;
  222. } else {
  223. this.showCategoryIndex = 0;
  224. this.currentCateId = this.categoryList && this.categoryList[0].id;
  225. }
  226. }
  227. if (r.data.length > 0) {
  228. this.currentSecondCategoryList = r.data[0].child;
  229. }
  230. this.page = 1;
  231. this.categoryProductList = [];
  232. await this.getProductList();
  233. this.loading = false;
  234. })
  235. .catch(() => {
  236. if (type === 'refresh') {
  237. uni.stopPullDownRefresh();
  238. }
  239. this.loading = false;
  240. });
  241. },
  242. // 获取广告列表
  243. async getAdvList() {
  244. await this.$http
  245. .get(`${advList}`, {
  246. location: 'cate_top'
  247. })
  248. .then(r => {
  249. this.cateTop = r.data.cate_top[0];
  250. });
  251. },
  252. // 分类切换显示
  253. showCategory(index) {
  254. this.showCategoryIndex = index;
  255. },
  256. showProduct(item, index) {
  257. this.categoryInvertedIndex = 0;
  258. this.currentSecondCategoryList = item.child;
  259. this.showCategoryIndex = index;
  260. if (this.styleCateType === 'one_two_product' && item.child.length > 0) {
  261. this.currentCateId = item.child[0].id;
  262. } else {
  263. this.currentCateId = item.id;
  264. }
  265. this.price = '';
  266. this.total_sales = '';
  267. this.page = 1;
  268. this.categoryProductList = [];
  269. this.getProductList();
  270. },
  271. handleSalesOrderByChange () {
  272. if (this.categoryProductList.length === 0) return;
  273. this.price = '';
  274. this.total_sales = this.total_sales === 'asc' ? 'desc' : 'asc';
  275. this.page = 1;
  276. this.categoryProductList = [];
  277. this.getProductList();
  278. },
  279. handlePriceOrderByChange () {
  280. if (this.categoryProductList.length === 0) return;
  281. this.total_sales = '';
  282. this.price = this.price === 'asc' ? 'desc' : 'asc';
  283. this.page = 1;
  284. this.categoryProductList = [];
  285. this.getProductList();
  286. },
  287. // 获取产品列表
  288. async getProductList() {
  289. this.productLoading = true;
  290. const params = {};
  291. if (this.total_sales) {
  292. params.total_sales = this.total_sales;
  293. }
  294. if (this.price) {
  295. params.price = this.price;
  296. }
  297. params.page = this.page;
  298. await this.$http
  299. .get(`${productList}`, {
  300. cate_id: this.currentCateId,
  301. ...params
  302. })
  303. .then(async r => {
  304. this.productLoading = false;
  305. this.loadingType = r.data.length === 10 ? 'more' : 'nomore';
  306. this.categoryProductList = [...this.categoryProductList, ...r.data];
  307. uni.removeStorageSync('indexToCateId');
  308. });
  309. },
  310. // 跳转至搜索详情页
  311. toSearch() {
  312. this.$mRouter.push({
  313. route: `/pages/index/search/search?data=${JSON.stringify(this.search)}`
  314. });
  315. },
  316. // 跳至广告图指定页面
  317. indexTopToDetailPage(item) {
  318. this.$mHelper.handleBannerNavTo(item.jump_type, item.jump_link, item.id);
  319. },
  320. getMoreProductList () {
  321. if (this.loadingType === 'nomore' || this.categoryProductList.length === 0) return;
  322. this.page++;
  323. this.getProductList();
  324. }
  325. }
  326. };
  327. </script>
  328. <style lang="scss">
  329. page {
  330. background-color: $color-white;
  331. }
  332. .rf-category {
  333. background-color: $color-white;
  334. /* #ifdef APP-PLUS */
  335. margin-top: calc(20upx + var(--status-bar-height));
  336. /* #endif */
  337. /*模块分类*/
  338. .category-list {
  339. width: 100%;
  340. background-color: #fff;
  341. display: flex;
  342. .left,
  343. .right {
  344. position: absolute;
  345. top: 80upx;
  346. /* #ifdef APP-PLUS */
  347. top: calc(80upx + var(--status-bar-height));
  348. /* #endif */
  349. bottom: 0upx;
  350. }
  351. .left {
  352. width: 24%;
  353. left: 0upx;
  354. background-color: $page-color-base;
  355. .row {
  356. width: 100%;
  357. height: 90upx;
  358. display: flex;
  359. align-items: center;
  360. .text {
  361. width: 100%;
  362. position: relative;
  363. font-size: 28upx;
  364. display: flex;
  365. justify-content: center;
  366. color: #3c3c3c;
  367. .block {
  368. position: absolute;
  369. width: 0upx;
  370. left: 0;
  371. }
  372. }
  373. &.on {
  374. height: 100upx;
  375. background-color: #fff;
  376. .text {
  377. font-size: 30upx;
  378. font-weight: 600;
  379. color: #2d2d2d;
  380. .block {
  381. width: 6upx;
  382. height: 120%;
  383. left: 10upx;
  384. }
  385. }
  386. }
  387. }
  388. }
  389. .right {
  390. width: 76%;
  391. left: 24%;
  392. background-color: #fff;
  393. .second-category {
  394. z-index: 10;
  395. white-space: nowrap;
  396. width: 100%;
  397. margin: $spacing-sm $spacing-sm $spacing-base;
  398. .second-category-tag {
  399. margin-right: $spacing-base;
  400. padding: 5upx $spacing-lg;
  401. display: inline-block;
  402. border-radius: 8upx;
  403. font-size: $font-sm + 2upx;
  404. }
  405. .second-category-normal {
  406. color: $font-color-dark;
  407. border: none;
  408. background-color: $page-color-light;
  409. }
  410. }
  411. .category {
  412. width: 100%;
  413. padding: 0 15upx $spacing-base;
  414. .banner {
  415. width: 96%;
  416. margin: 10upx auto 30upx;
  417. height: 24.262vw;
  418. border-radius: 10upx;
  419. overflow: hidden;
  420. box-shadow: 0upx 5upx 20upx rgba(0, 0, 0, 0.05);
  421. image {
  422. width: 100%;
  423. height: 24.262vw;
  424. }
  425. }
  426. .order-by-wrapper {
  427. height: 48upx;
  428. line-height: 48upx;
  429. display: flex;
  430. justify-content: space-between;
  431. margin: $spacing-sm 0;
  432. font-size: $font-sm + 2upx;
  433. .order-by {
  434. display: flex;
  435. justify-content: center;
  436. align-items: center;
  437. .order-by-item {
  438. display: flex;
  439. justify-content: center;
  440. align-items: center;
  441. font-size: $font-sm + 2upx;
  442. margin: 0 $spacing-base 0 $spacing-sm;
  443. color: $font-color-light;
  444. .iconfont-group {
  445. margin-top: -2upx;
  446. }
  447. .iconfont {
  448. height: 16upx;
  449. line-height: 16upx;
  450. display: block;
  451. margin-left: 6upx;
  452. font-weight: 550;
  453. font-size: $font-sm - 4upx;
  454. }
  455. }
  456. }
  457. }
  458. .list {
  459. margin-top: $spacing-base;
  460. width: 100%;
  461. display: flex;
  462. flex-wrap: wrap;
  463. .box {
  464. width: calc(71.44vw / 3);
  465. margin-bottom: $spacing-lg;
  466. display: flex;
  467. justify-content: center;
  468. align-items: center;
  469. flex-wrap: wrap;
  470. image {
  471. width: 64%;
  472. height: calc(71.44vw / 3 * 0.64);
  473. }
  474. .text {
  475. margin-top: 8upx;
  476. width: 100%;
  477. display: flex;
  478. justify-content: center;
  479. font-size: 26upx;
  480. }
  481. .category-tag {
  482. width: 100%;
  483. display: flex;
  484. justify-content: center;
  485. align-items: center;
  486. padding: $spacing-sm;
  487. font-size: $font-sm + 2upx;
  488. margin-right: $spacing-base;
  489. color: $font-color-dark;
  490. background-color: $page-color-base;
  491. border-radius: 6upx;
  492. }
  493. }
  494. }
  495. .second-category-text {
  496. display: flex;
  497. justify-content: space-between;
  498. }
  499. .no-data {
  500. margin: 48upx 0;
  501. color: $font-color-light;
  502. display: flex;
  503. justify-content: center;
  504. align-items: center;
  505. .iconfont {
  506. margin-right: 20upx;
  507. font-size: $font-lg + 16upx;
  508. }
  509. }
  510. }
  511. }
  512. }
  513. .one-cover-category {
  514. margin-top: $spacing-base;
  515. width: 100%;
  516. display: flex;
  517. flex-wrap: wrap;
  518. .box {
  519. width: calc(71.44vw / 3);
  520. margin-bottom: $spacing-lg;
  521. display: flex;
  522. justify-content: center;
  523. align-items: center;
  524. flex-wrap: wrap;
  525. image {
  526. width: 64%;
  527. height: calc(71.44vw / 3 * 0.64);
  528. }
  529. .text {
  530. margin-top: 8upx;
  531. width: 100%;
  532. display: flex;
  533. justify-content: center;
  534. font-size: 26upx;
  535. }
  536. .category-tag {
  537. width: 100%;
  538. display: flex;
  539. justify-content: center;
  540. align-items: center;
  541. padding: $spacing-sm;
  542. font-size: $font-sm + 2upx;
  543. margin-right: $spacing-base;
  544. color: $font-color-dark;
  545. background-color: $page-color-base;
  546. border-radius: 6upx;
  547. }
  548. }
  549. }
  550. .tui-product-container {
  551. flex: 1;
  552. margin-right: 10upx;
  553. }
  554. .tui-product-container:last-child {
  555. margin-right: 0;
  556. }
  557. .category-product-list {
  558. margin-bottom: 15upx;
  559. padding-bottom: 15upx;
  560. border-bottom: 1upx solid rgba(0, 0, 0, 0.08);
  561. }
  562. .category-product-list:last-child {
  563. border-bottom: none;
  564. background-color: #007aff;
  565. }
  566. .tui-pro-item {
  567. width: 100%;
  568. margin-bottom: 20upx;
  569. background: $color-white;
  570. box-sizing: border-box;
  571. border-radius: 12upx;
  572. overflow: hidden;
  573. transition: all 0.15s ease-in-out;
  574. }
  575. .tui-flex-list {
  576. display: flex;
  577. margin-bottom: 1upx !important;
  578. }
  579. .tui-pro-img {
  580. width: 100%;
  581. display: block;
  582. }
  583. .tui-proimg-list {
  584. width: 160upx;
  585. height: 160upx !important;
  586. flex-shrink: 0;
  587. border-radius: 12upx;
  588. }
  589. .tui-pro-content {
  590. width: 100%;
  591. display: flex;
  592. flex-direction: column;
  593. justify-content: space-between;
  594. box-sizing: border-box;
  595. padding: 0 20upx;
  596. }
  597. .tui-pro-tit {
  598. color: #2e2e2e;
  599. font-size: 26upx;
  600. word-break: break-all;
  601. overflow: hidden;
  602. text-overflow: ellipsis;
  603. display: -webkit-box;
  604. -webkit-box-orient: vertical;
  605. -webkit-line-clamp: 2;
  606. }
  607. .tui-sale-price {
  608. font-size: 34upx;
  609. font-weight: 500;
  610. }
  611. .tui-factory-price {
  612. font-size: 24upx;
  613. color: #a0a0a0;
  614. text-decoration: line-through;
  615. padding-left: 12upx;
  616. }
  617. .tui-pro-pay {
  618. display: flex;
  619. justify-content: space-between;
  620. align-items: center;
  621. font-size: 24upx;
  622. color: #656565;
  623. .iconfont {
  624. font-size: $font-lg + 6upx;
  625. padding: 0 $spacing-sm;
  626. }
  627. }
  628. .popup .layer {
  629. // #ifndef H5
  630. bottom: 0;
  631. // #endif
  632. }
  633. .input-box {
  634. height: 60upx;
  635. position: relative;
  636. display: flex;
  637. align-items: center;
  638. margin: 10upx 20upx;
  639. .iconfont {
  640. width: 60upx;
  641. font-size: 48upx;
  642. font-weight: 500;
  643. }
  644. .iconsousuo2 {
  645. z-index: 999;
  646. display: flex;
  647. align-items: center;
  648. position: absolute;
  649. top: 0;
  650. right: 0;
  651. width: 60upx;
  652. height: 60upx;
  653. font-size: 34upx;
  654. color: #c0c0c0;
  655. }
  656. input {
  657. flex: 1;
  658. height: 60upx;
  659. background-color: #f5f5f5;
  660. padding-left: 28upx;
  661. border-radius: 30upx;
  662. color: #888;
  663. font-size: 28upx;
  664. }
  665. }
  666. }
  667. </style>