category.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. // pages/category/category.js
  2. var http = require("../../utils/http.js");
  3. var util = require('../../utils/util.js');
  4. var config = require("../../utils/config.js");
  5. import eventBus from '../../utils/eventBus';
  6. Page({
  7. /**
  8. * 页面的初始数据
  9. */
  10. data: {
  11. showTabbar:true,
  12. showLoading:false,
  13. rightView:'',
  14. paramsObj:{
  15. sort:0,
  16. orderBy:0
  17. },
  18. type:'bottom',
  19. toViewId:'test1',
  20. topHeight:300,
  21. sort:0,
  22. imgUrl:'',
  23. testShopId:0,//109
  24. totalInfo:{"totalMoney":0,"finalMoney":0,"subtractMoney":0.0,"count":0},
  25. shopId:0,
  26. show:false,
  27. showCar:false,
  28. selIndex: 0,
  29. selCategory:0,
  30. subIndex:0,
  31. thridIndex:-1,
  32. subCategoryId:0,
  33. categoryList: [],
  34. categoryImg: '',
  35. subCategoryList: [],
  36. thridCategoryList:[],
  37. pageTopHeight: wx.getWindowInfo().statusBarHeight,
  38. hotList: [],
  39. topCurrentIndex: 0,
  40. productList:[],
  41. carData:[],//购物车数据
  42. animateInfo:{
  43. startX:99999,
  44. startY:0,
  45. endX:0,
  46. endY:0,
  47. },
  48. move:false
  49. },
  50. /**
  51. * 生命周期函数--监听页面加载
  52. */
  53. onLoad: function (options) {
  54. this.getRecommended()
  55. this.get_neighborShop()
  56. // this.get_categoryInfo()
  57. },
  58. scroll(){
  59. },
  60. scrollTop(){
  61. console.log('top',);
  62. if(this.data.subIndex==0||this.data.subCategoryList.length==0||this.data.productList.length == 0) return
  63. this.setData({
  64. type:'top'
  65. })
  66. let data = {currentTarget:{
  67. dataset:{
  68. index:this.data.subIndex-1
  69. }
  70. }}
  71. this.onleftMenuTab(data)
  72. // this.setData({
  73. // topHeight:0
  74. // })
  75. },
  76. scrollBottom(){
  77. // this.data.productList 新增判断 避免为空自动滚动
  78. if(this.data.subIndex==(this.data.subCategoryList.length-1)||this.data.subCategoryList.length==0||this.data.productList.length == 0) return
  79. this.setData({
  80. type:'bottom'
  81. })
  82. let data = {currentTarget:{
  83. dataset:{
  84. index:this.data.subIndex+1
  85. }
  86. }}
  87. this.setData({
  88. topHeight:15
  89. },() => {
  90. // 3. 延迟恢复样式(避免视觉闪烁)
  91. setTimeout(() => {
  92. this.onleftMenuTab(data)
  93. }, 0);
  94. })
  95. },
  96. handleSale(){
  97. this.setData({
  98. sort:1,
  99. paramsObj:{sort:1,orderBy:0}
  100. })
  101. this.getData(this.data.subCategoryList[this.data.subIndex])
  102. },
  103. handlePrice(){
  104. // 没点击价格
  105. if(this.data.sort !=2&&this.data.sort!=3){
  106. this.setData({
  107. sort:2,
  108. paramsObj:{sort:2,orderBy:0}
  109. })
  110. }else{
  111. let sort = this.data.sort ==2?3:2
  112. this.setData({
  113. sort,
  114. paramsObj:{sort:2,orderBy:this.data.sort ==2?0:1}
  115. })
  116. }
  117. this.getData(this.data.subCategoryList[this.data.subIndex])
  118. },
  119. resetData(){
  120. this.setData({
  121. subIndex:0,
  122. thridIndex:-1,
  123. subCategoryId:0,
  124. })
  125. },
  126. // 点击购物车内加减按钮
  127. handleNum(e){
  128. // 查看是否授权
  129. util.checkAuthInfo(()=>{
  130. let {num,item,type,index} = e.currentTarget.dataset
  131. let data = {
  132. "basketId": item.basketId||0,
  133. "count": num,
  134. "distributionCardNo": item.distributionCardNo||'',
  135. "prodId": item.prodId,
  136. "shopId": item.shopId,
  137. "skuId": item.skuId||item.skuList[0].skuId,
  138. channelId:wx.getStorageSync('channelId')||3
  139. }
  140. this.changeCar(data)
  141. if(type == 'add'){
  142. this.addAnimate(e)
  143. }
  144. })
  145. },
  146. addAnimate(e){
  147. let startX = e.touches[0].clientX-10
  148. let startY = e.touches[0].clientY-10
  149. const query = wx.createSelectorQuery().in(this);
  150. query.select('.bottom-box .left .icon').boundingClientRect(cartRect => {
  151. console.log(222222,cartRect);
  152. if (!cartRect) return;
  153. let animateInfo = {
  154. startX,
  155. startY,
  156. endX:cartRect.left,
  157. endY:cartRect.bottom,
  158. }
  159. this.setData({
  160. move:true,
  161. animateInfo
  162. })
  163. console.log(animateInfo);
  164. }).exec();
  165. },
  166. endAnimate(){
  167. console.log('ddddd');
  168. let animateInfo = {
  169. startX:9999,
  170. startY:0,
  171. endX:0,
  172. endY:0,
  173. }
  174. this.setData({
  175. move:false,
  176. animateInfo
  177. })
  178. },
  179. // 获取点击位置和购物车位置
  180. getNodePositions(index) {
  181. const query = wx.createSelectorQuery().in(this);
  182. // 1. 获取"加入购物车"按钮的位置(动画起始点)
  183. query.select(`.product-item:nth-child(${index + 1}) .info .price-box .test`).boundingClientRect(btnRect => {
  184. if (!btnRect) return; // 容错:防止节点未找到
  185. const startX = btnRect.left + btnRect.width / 2 - 20; // 20 = 40rpx/2(图标宽高)
  186. const startY = btnRect.top + btnRect.height / 2 - 20;
  187. // 2. 获取购物车位置(动画结束点)
  188. query.select('.bottom-box .left .icon').boundingClientRect(cartRect => {
  189. if (!cartRect) return;
  190. const endX = cartRect.left + cartRect.width / 2 - 20;
  191. const endY = cartRect.top + cartRect.height / 2 - 20;
  192. // 3. 计算抛物线中间点(控制弧度)
  193. const midX = (startX + endX) / 2;
  194. const midY = startY - 80; // 向上凸起80px,可调整弧度
  195. // 4. 创建动画图标
  196. this.createAnimationIcon(startX, startY, midX, midY, endX, endY);
  197. }).exec();
  198. }).exec();
  199. },
  200. // 创建抛物线动画(数据驱动,无DOM操作)
  201. createAnimationIcon(startX, startY, midX, midY, endX, endY) {
  202. // 生成唯一ID,避免key冲突
  203. const iconId = Date.now() + Math.floor(Math.random() * 1000);
  204. const newIcon = {
  205. id: iconId,
  206. startX,
  207. startY,
  208. midX,
  209. midY,
  210. endX,
  211. endY
  212. };
  213. // 添加动画图标到数组(自动渲染)
  214. this.setData({
  215. animationIcons: [...this.data.animationIcons, newIcon]
  216. });
  217. // 动画结束后移除图标+更新购物车
  218. setTimeout(() => {
  219. this.setData({
  220. animationIcons: this.data.animationIcons.filter(icon => icon.id !== iconId),
  221. });
  222. }, 700); // 与动画时长保持一致(0.7s)
  223. },
  224. handleAll(){
  225. this.setData({
  226. show:true
  227. })
  228. },
  229. onClose(){
  230. this.setData({
  231. show:false
  232. })
  233. },
  234. openCar(){
  235. console.log(111111);
  236. this.setData({
  237. showCar:true
  238. })
  239. },
  240. onCarClose(){
  241. this.setData({
  242. showCar:false
  243. })
  244. },
  245. /**
  246. * 获取距离最近店铺id
  247. * @param {*} e
  248. */
  249. get_neighborShop: function () {
  250. var params = {
  251. url: "/shop/neighborShop",
  252. method: "GET",
  253. data: {
  254. lat: wx.getStorageSync('LATITUDE'),
  255. lon: wx.getStorageSync('LONGITUDE'),
  256. channelId:wx.getStorageSync('channelId')||3
  257. },
  258. callBack: (res) => {
  259. // this.get_categoryInfo(res)
  260. wx.setStorageSync('shopInfo', res)
  261. this.setData({
  262. shopId:res.shopId
  263. })
  264. this.get_categoryInfo(res.shopId)
  265. this.getCarData(this.data.shopId)
  266. }
  267. };
  268. http.request(params);
  269. },
  270. get_categoryInfo: function (shopid) {
  271. var ths = this;
  272. let that = this
  273. //加载分类列表
  274. var params = {
  275. // url: "/category/categoryInfo",
  276. url: "/category/listCategoryForUser/"+(this.data.testShopId||shopid),
  277. method: "GET",
  278. callBack: function (res) {
  279. ths.setData({
  280. categoryList: res,
  281. subCategoryList: res[ths.data.selIndex].children
  282. });
  283. let categoryId =wx.getStorageSync('categoryId')
  284. if(categoryId){
  285. that.data.categoryList.map((item,index)=>{
  286. if(item.categoryId == categoryId){
  287. that.setData({
  288. selCategory:categoryId,
  289. selIndex:index,
  290. subCategoryList:res[index].children
  291. })
  292. }
  293. })
  294. wx.removeStorageSync('categoryId')
  295. }
  296. // eventBus.on('categoryId', (data) => {
  297. // eventBus.clear()
  298. // that.data.categoryList.map((item,index)=>{
  299. // if(item.categoryId == data){
  300. // that.setData({
  301. // selCategory:data,
  302. // selIndex:index,
  303. // subCategoryList:res[index].children
  304. // })
  305. // }
  306. // })
  307. // });
  308. ths.getData(ths.data.subCategoryList[0])
  309. }
  310. };
  311. http.request(params);
  312. },
  313. getData(data){
  314. console.log(data);
  315. if(!data){
  316. return this.setData({
  317. thridCategoryList:[],
  318. showLoading:false
  319. })
  320. }
  321. this.setData({
  322. thridCategoryList:[],
  323. showLoading:true
  324. })
  325. // 二级分类有商品
  326. if(data.productBeBound == 1){
  327. this.getAllProList(data.categoryId)
  328. // this.getProdList(data.categoryId)
  329. }else{//二级分类有三级分类
  330. this.getAllProList(data.categoryId)
  331. this.setData({
  332. thridCategoryList:data.children,
  333. subCategoryId:data.categoryId
  334. })
  335. }
  336. },
  337. /**
  338. * 选择定位后更新列表
  339. */
  340. go_update() {
  341. this.get_neighborShop()
  342. },
  343. /**
  344. * 生命周期函数--监听页面初次渲染完成
  345. */
  346. onReady: function () {
  347. },
  348. /**
  349. * 生命周期函数--监听页面显示
  350. */
  351. onShow: function () {
  352. console.log('show');
  353. if(this.data.shopId){
  354. this.getCarData(this.data.shopId)
  355. }
  356. // if (getApp().globalData.categoryId) {
  357. // let categoryId = getApp().globalData.categoryId
  358. // let index = getApp().globalData.index
  359. // let pic = getApp().globalData.pic
  360. // this.setData({
  361. // categoryImg: pic,
  362. // selIndex: index
  363. // });
  364. // }else{
  365. // this.get_neighborShop()
  366. // }
  367. // 之前逻辑 每次重新加载
  368. // this.resetData()
  369. // this.get_neighborShop()
  370. },
  371. /**
  372. * 生命周期函数--监听页面隐藏
  373. */
  374. onHide: function () {},
  375. /**
  376. * 生命周期函数--监听页面卸载
  377. */
  378. onUnload: function () {
  379. },
  380. /**
  381. * 页面相关事件处理函数--监听用户下拉动作
  382. */
  383. onPullDownRefresh: function () {
  384. },
  385. /**
  386. * 页面上拉触底事件的处理函数
  387. */
  388. onReachBottom: function () {
  389. },
  390. /**
  391. * 用户点击右上角分享
  392. */
  393. onShareAppMessage: function () {
  394. },
  395. /**
  396. * 分类点击事件,获取子分类
  397. */
  398. onMenuTab: function (e) {
  399. var id = e.currentTarget.dataset.id;
  400. var index = e.currentTarget.dataset.index;
  401. // if(this.data.categoryList[index].children.length == 0){
  402. // return
  403. // }
  404. this.setData({
  405. show:false,
  406. categoryImg: this.data.categoryList[index].pic,
  407. subCategoryList:this.data.categoryList[index].children,
  408. selIndex: index,
  409. selCategory:id,
  410. productList:[],
  411. subIndex:0,
  412. paramsObj:{sort:0,orderBy:0},
  413. sort:0
  414. });
  415. // this.getProdList(this.data.subCategoryList[0].categoryId)
  416. this.getData(this.data.subCategoryList[0])
  417. getApp().globalData.categoryId = ''
  418. getApp().globalData.index = ''
  419. getApp().globalData.pic = ''
  420. },
  421. /**
  422. * 推荐词,type:1关键词,2热门搜索词,3推荐搜索词
  423. */
  424. getRecommended: function () {
  425. var params = {
  426. url: "/keyword/list",
  427. method: "GET",
  428. data: {
  429. type: 2
  430. },
  431. callBack: (res) => {
  432. let reslut = res.filter(item => item.status !== 2) //过滤下线词
  433. let timeReslut = reslut.filter(e => util.dateToTimestamp(e.effectiveTime) < new Date().getTime()) //过滤未生效词
  434. this.setData({
  435. hotList: timeReslut
  436. })
  437. }
  438. };
  439. http.request(params);
  440. },
  441. /**
  442. * 推荐词搜索
  443. */
  444. topSwiperChange: function (e) {
  445. this.setData({
  446. topCurrentIndex: e.detail.current // 获取当前滚动到的swiper-item的索引并更新到data中
  447. })
  448. },
  449. topHotSearch: function () {
  450. const topname = this.data.hotList[this.data.topCurrentIndex].name
  451. wx.navigateTo({
  452. url: `/pages/search-prod-show/search-prod-show?prodName=${topname}&shopId=${this.data.shopId}`,
  453. })
  454. },
  455. // 跳转搜索页
  456. toSearchPage: function () {
  457. wx.navigateTo({
  458. url: `/pages/search-page/search-page?shopId=${this.data.shopId}`,
  459. })
  460. },
  461. /**
  462. * 跳转到定位页面
  463. */
  464. toLocationPage: function () {
  465. wx.navigateTo({
  466. url: '/pages/locationAdd/locationAdd',
  467. })
  468. },
  469. // 点击二级分类
  470. onleftMenuTab(e){
  471. const {
  472. index,
  473. id
  474. } = e.currentTarget.dataset
  475. if(id){
  476. this.setData({
  477. type:'click'
  478. })
  479. console.log('click');
  480. }
  481. this.setData({
  482. subIndex:index,
  483. paramsObj:{sort:0,orderBy:0},
  484. sort:0
  485. })
  486. // this.getProdList(this.data.subCategoryList[index].categoryId)
  487. this.getData(this.data.subCategoryList[index])
  488. },
  489. // 根据分类id获取商品数据
  490. getProdList(categoryId) {
  491. var params = {
  492. url: "/search/searchProdPage",
  493. method: "GET",
  494. data: {
  495. categoryId,
  496. current: 1,
  497. size: 999999,
  498. orderBy:this.data.paramsObj.orderBy,
  499. sort:this.data.paramsObj.sort,
  500. isAllProdType: true,
  501. channelId:wx.getStorageSync('channelId')||3,
  502. // lat: wx.getStorageSync('LATITUDE'),
  503. // lon: wx.getStorageSync('LONGITUDE'),
  504. // distance: wx.getStorageSync('DISTANCE') || 0
  505. },
  506. callBack: (res) => {
  507. setTimeout(() => {
  508. this.setData({
  509. showLoading:false
  510. })
  511. }, 500);
  512. console.log(res);
  513. let productList = res.records
  514. let img = ''
  515. productList.map(e => {
  516. img = e.pic.split(',')
  517. e.pic = img[0]
  518. })
  519. this.setData({
  520. productList,
  521. topHeight:15
  522. })
  523. if(productList.length == 0){
  524. if(this.data.type == 'top'){
  525. this.scrollTop()
  526. }else{
  527. this.scrollBottom()
  528. }
  529. }
  530. this.addParmasProduct()
  531. }
  532. };
  533. http.request(params);
  534. },
  535. // 根据分类id获取所有三级商品数据
  536. getAllProList(categoryId) {
  537. var params = {
  538. url: "/prod/listProdByCategoryIdAndShopId",
  539. method: "post",
  540. data: {
  541. orderBy:this.data.paramsObj.orderBy,
  542. sort:this.data.paramsObj.sort,
  543. categoryId,
  544. current: 1,
  545. size: 999999,
  546. channelId:wx.getStorageSync('channelId')||3,
  547. shopId:this.data.testShopId||this.data.shopId
  548. },
  549. callBack: (res) => {
  550. setTimeout(() => {
  551. this.setData({
  552. showLoading:false
  553. })
  554. }, 500);
  555. let productList = res.records
  556. let img = ''
  557. productList.map(e => {
  558. img = e.pic.split(',')
  559. e.pic = img[0]
  560. })
  561. this.setData({
  562. productList,
  563. topHeight:15
  564. })
  565. if(productList.length == 0){
  566. if(this.data.type == 'top'){
  567. this.scrollTop()
  568. }else if(this.data.type == 'bottom'){
  569. this.scrollBottom()
  570. }
  571. }
  572. this.addParmasProduct()
  573. }
  574. };
  575. http.request(params);
  576. },
  577. // 点击三级分类
  578. handleThrid(e){
  579. let {
  580. index,
  581. categoryid
  582. } = e.currentTarget.dataset
  583. console.log(33333333333,e.currentTarget.dataset);
  584. this.setData({
  585. thridIndex:index
  586. })
  587. if(index == -1){
  588. categoryid = this.data.subCategoryId
  589. }
  590. this.getAllProList(categoryid)
  591. },
  592. // 除了产品列表数据 给产品列表添加显示和数量 同步购物车数据
  593. addParmasProduct(){
  594. if(this.data.productList.length >0){
  595. let productList = JSON.parse(JSON.stringify( this.data.productList))
  596. productList.map(i=>{
  597. i.show = false
  598. this.data.carData.map(item=>{
  599. if(item.prodId == i.prodId){
  600. i.prodCount = item.prodCount
  601. i.show = true
  602. }
  603. })
  604. })
  605. this.setData({
  606. productList
  607. })
  608. }
  609. },
  610. // 获取购物车数据
  611. getCarData() {
  612. var params = {
  613. url: "/p/shopCart/info/1",
  614. method: "post",
  615. data: [{
  616. "basketId": 0,
  617. "discountId": 0,
  618. "shopId":this.data.testShopId||this.data.shopId
  619. }],
  620. callBack: (res) => {
  621. if(res.length){
  622. let carData = res[0].shopCartItemDiscounts[0].shopCartItems
  623. let img = ''
  624. carData.map(e => {
  625. img = e.pic.split(',')
  626. e.pic = img[0]
  627. })
  628. this.setData({
  629. carData
  630. },()=>{
  631. this.getCarTotal()
  632. })
  633. }else{
  634. this.setData({
  635. carData:[]
  636. },()=>{
  637. this.getCarTotal()
  638. })
  639. }
  640. // 给产品列表添加显示和数量 同步购物车数据
  641. this.addParmasProduct()
  642. }
  643. };
  644. http.request(params);
  645. },
  646. // 获取购物车数量和总价
  647. getCarTotal() {
  648. let basketIds = this.data.carData.map(item=>{
  649. return item.basketId
  650. })
  651. var params = {
  652. url: "/p/shopCart/totalPay?t="+new Date().getTime(),
  653. method: "post",
  654. data: basketIds,
  655. callBack: (res) => {
  656. this.setData({
  657. totalInfo:res
  658. })
  659. }
  660. };
  661. http.request(params);
  662. http.getCartCount(); //重新计算购物车总数量
  663. },
  664. // 添加修改购物车数量
  665. changeCar(data) {
  666. var params = {
  667. url: "/p/shopCart/changeItem?t="+new Date().getTime(),
  668. method: "post",
  669. data,
  670. callBack: (res) => {
  671. if(res.code == 500){
  672. wx.showToast({
  673. title: res.msg,
  674. icon:'none'
  675. })
  676. }else{
  677. this.getCarData()
  678. }
  679. }
  680. };
  681. http.request(params);
  682. },
  683. /**
  684. * 跳转到商品详情页
  685. */
  686. toProdPage: function (e) {
  687. var prodid = e.currentTarget.dataset.prodid;
  688. var shopid = e.currentTarget.dataset.shopid;
  689. console.log(22222222,e);
  690. if (prodid) {
  691. wx.navigateTo({
  692. url: `/pages/prod/prod?prodid=${prodid}&shopid=${shopid}`,
  693. })
  694. }
  695. },
  696. handleBuy(){
  697. if(this.data.carData.length == 0){
  698. return
  699. }
  700. let basketIds = this.data.carData.map(item=>{
  701. return item.basketId
  702. })
  703. wx.setStorageSync("basketIds", JSON.stringify(basketIds));
  704. wx.navigateTo({
  705. url: '/pages/submit-order/submit-order?orderEntry=0&shopId='+this.data.carData[0].shopId,
  706. })
  707. }
  708. })