Forráskód Böngészése

下拉更新提交

zxl 1 éve
szülő
commit
be70e07dbb

+ 12 - 0
.hbuilderx/launch.json

@@ -1,6 +1,12 @@
+<<<<<<< HEAD
 { // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
   // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
     "version": "0.0",
+=======
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+  // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version": "0.0",
+>>>>>>> ca3471983a9fcf78f1c74dd357bf7f7471316603
     "configurations": [{
      	"default" : 
      	{
@@ -11,6 +17,12 @@
      		"launchtype" : "local"
      	},
      	"type" : "uniCloud"
+<<<<<<< HEAD
+     }
+    ]
+}
+=======
      }
     ]
 }
+>>>>>>> ca3471983a9fcf78f1c74dd357bf7f7471316603

+ 16 - 0
src/api/home.js

@@ -14,3 +14,19 @@ export function getHomePage(data) {
     },
   });
 }
+
+/**
+ * 获取当前位置
+ * @returns
+ */
+export function getCurrentLocation(data) {
+  return request({
+    url: '/maintain/location',
+    method: 'get',
+    data: data,
+    header: {
+      'content-type': 'application/x-www-form-urlencoded',
+    },
+  });
+}
+

+ 30 - 0
src/api/tabbar/home.js

@@ -0,0 +1,30 @@
+import { request } from '@/utils/request';
+
+/**
+ * 获取首页
+ * @returns
+ */
+export function getHomePageApi(data) {
+  return request({
+    url: '/maintain/customer/index',
+    method: 'get',
+    data: data,
+    header: {
+      'content-type': 'application/x-www-form-urlencoded',
+    },
+  });
+}
+
+/**
+ *@description 获取首页分类的数据
+ */
+
+export function getCategoriesApi() {
+  return request({
+    url: '/maintain/categories',
+    methods: get,
+    header: {
+      'content-type': 'application/x-www-form-urlencoded',
+    },
+  });
+}

+ 34 - 12
src/components/service/index.vue

@@ -1,16 +1,29 @@
 <template>
   <view>
     <view class="sort">
-      <u-tabs :list="list1" @click="click" lineWidth="30" lineColor="#5992bb" :activeStyle="{
-        color: '#5992bb',
-        fontWeight: 'bold',
-      }" :inactiveStyle="{
-  color: '#000',
-}" itemStyle="padding-left: 15px; padding-right: 15px; height: 40px;" />
+      <u-tabs
+        :list="list1"
+        @click="click"
+        lineWidth="30"
+        lineColor="#5992bb"
+        :activeStyle="{
+          color: '#5992bb',
+          fontWeight: 'bold',
+        }"
+        :inactiveStyle="{
+          color: '#000',
+        }"
+        itemStyle="padding-left: 15px; padding-right: 15px; height: 40px;"
+      />
       <view class="list">
-        <Image src="https://cdn.uviewui.com/uview/album/1.jpg" @tap="$Router.push('/pages/business/service/index')" />
+        <Image
+          src="https://cdn.uviewui.com/uview/album/1.jpg"
+          @tap="$Router.push('/pages/business/service/index')"
+        />
         <view>
-          <view class="item-text">【养车】标题标题标题标题标题标题标题标题……</view>
+          <view class="item-text"
+            >【养车】标题标题标题标题标题标题标题标题……</view
+          >
           <view class="item-flex">
             <view class="star">
               <u-rate :count="count" v-model="value" :size="14" />
@@ -21,7 +34,8 @@
           </view>
           <view class="list-item">
             <view>
-              <view class="price">券后价
+              <view class="price"
+                >券后价
                 <text class="price-item">¥</text>
                 <text class="price-count">19</text>
               </view>
@@ -32,14 +46,22 @@
             </view>
             <view class="appoint">
               <text class="appoint-item" @click="show = true">预约</text>
-              <text class="Buy" @tap="$Router.push('/pages/business/buy/index')">购买</text>
+              <text class="Buy" @tap="$Router.push('/pages/business/buy/index')"
+                >购买</text
+              >
             </view>
           </view>
         </view>
       </view>
 
       <!-- 预约弹出框的实现 -->
-      <u-popup :show="show" mode="center" @close="close" @open="open" :round="20">
+      <u-popup
+        :show="show"
+        mode="center"
+        @close="close"
+        @open="open"
+        :round="20"
+      >
         <view class="popupContent">
           <text class="popupItem">预约服务</text>
           <view class="server">
@@ -209,4 +231,4 @@ export default {
     margin: 20rpx 0 20rpx 30rpx;
   }
 }
-</style>
+</style>

+ 7 - 1
src/pages.json

@@ -118,7 +118,13 @@
           "style": {
             "navigationBarTitleText": "养车"
           }
-        }
+        },
+		{
+			"path" : "classfication/classfication",
+			"style" :{
+				"navigationBarTitleText": "分类"
+			}
+	    }
       ]
     },
     {

+ 345 - 0
src/pages/business/classfication/classfication.vue

@@ -0,0 +1,345 @@
+<template>
+  <view class="u-wrap">
+    <view class="u-menu-wrap">
+      <scroll-view
+        scroll-y
+        scroll-with-animation
+        class="u-tab-view menu-scroll-view"
+        :scroll-top="scrollTop"
+        :scroll-into-view="itemId"
+      >
+        <view
+          v-for="(item, index) in cateList"
+          :key="index"
+          class="u-tab-item"
+          :class="[current == index ? 'u-tab-item-active' : '']"
+          @tap.stop="handleLeftMenuClick(index)"
+        >
+          <text class="u-line-1">{{ item.description }}</text>
+        </view>
+      </scroll-view>
+      <scroll-view
+        :scroll-top="scrollRightTop"
+        scroll-y
+        scroll-with-animation
+        class="right-box"
+        @scroll="rightScroll"
+      >
+        <view class="page-view">
+          <view
+            class="class-item"
+            :id="'item' + index"
+            v-for="(item, index) in cateList"
+            :key="index"
+          >
+            <view class="item-title">
+              <text>{{ item.description }}</text>
+            </view>
+            <view class="item-container">
+              <view
+                class="thumb-box"
+                v-for="(child, childIndex) in item.children"
+                :key="childIndex"
+                @click="featureC(child.id, child.name)"
+              >
+                <image
+                  v-if="child.icon != ''"
+                  class="item-menu-image"
+                  :src="child.icon"
+                  mode=""
+                ></image>
+                <view
+                  v-else
+                  class="item-menu-image row-c"
+                  style="background-color: #f4f6f8"
+                  ><text style="font-size: 20rpx; color: #d0d0d0"
+                    >加载失败</text
+                  ></view
+                >
+                <view class="item-menu-name">{{ child.name }}</view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </scroll-view>
+    </view>
+  </view>
+</template>
+
+<script>
+import { buildTree } from '@/utils/tools.js';
+export default {
+  data() {
+    return {
+      scrollTop: 0, //tab标题的滚动条位置
+      oldScrollTop: 0, // tab标题的滚动条旧位置
+      current: 0, // 预设当前项的值
+      menuHeight: 0, // 左边菜单的高度
+      menuItemHeight: 0, // 左边菜单item的高度
+      itemId: '', // 栏目右边scroll-view用于滚动的id
+      cateList: [], // 渲染的数据
+      arr: [], // 储存距离顶部高度的数组
+      scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
+      timer: null, // 定时器
+    };
+  },
+  onLoad() {
+    this.cateList = buildTree(this.getCache('categories'));
+  },
+  onReady() {
+    this.getMenuItemTop();
+  },
+  methods: {
+    /**
+     * 获取一个目标元素的高度
+     * @elClass 元素的类名
+     * @dataVal 储存高度的对象
+     */
+    getElRect(elClass, dataVal) {
+      new Promise((resolve, reject) => {
+        const query = uni.createSelectorQuery().in(this);
+        query
+          .select('.' + elClass)
+          .fields(
+            {
+              size: true,
+            },
+            res => {
+              // 如果节点尚未生成,res值为null,循环调用执行
+              if (!res) {
+                setTimeout(() => {
+                  this.getElRect(elClass);
+                }, 10);
+                return;
+              }
+              this[dataVal] = res.height;
+              resolve();
+            },
+          )
+          .exec();
+      });
+    },
+    /**
+     * 获取右边菜单每个item到顶部的距离
+     * 储存到 arr 数组里面用于后面滚动判断
+     */
+    getMenuItemTop() {
+      new Promise(resolve => {
+        let selectorQuery = uni.createSelectorQuery();
+        selectorQuery
+          .selectAll('.class-item')
+          .boundingClientRect(rects => {
+            // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
+            if (!rects.length) {
+              setTimeout(() => {
+                this.getMenuItemTop();
+              }, 10);
+              return;
+            }
+            rects.forEach(rect => {
+              // 视情况而定,这里减去rects[0].top,是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
+              // this.arr.push(rect.top - rects[0].top);
+              this.arr.push(rect.top);
+              resolve();
+            });
+          })
+          .exec();
+      });
+    },
+    /**
+     * 观测元素相交状态
+     * 检测右边scroll-view的id为itemxx的元素与right-box的相交状态
+     * 如果跟.right-box底部相交,就动态设置左边栏目的活动状态
+     */
+    async observer() {
+      this.cateList.map((val, index) => {
+        let observer = uni.createIntersectionObserver(this);
+        observer
+          .relativeTo('.right-box', {
+            top: 0,
+          })
+          .observe('#item' + index, res => {
+            if (res.intersectionRatio > 0) {
+              let id = res.id.substring(4);
+              this.leftMenuStatus(id);
+            }
+          });
+      });
+    },
+    /**
+     * 设置左边菜单的滚动状态
+     * @index 传入的 ID
+     */
+    async leftMenuStatus(index) {
+      this.current = index;
+      // 如果为0,意味着尚未初始化
+      if (this.menuHeight == 0 || this.menuItemHeight == 0) {
+        await this.getElRect('menu-scroll-view', 'menuHeight');
+        await this.getElRect('u-tab-item', 'menuItemHeight');
+      }
+      // 将菜单活动item垂直居中
+      this.scrollTop =
+        index * this.menuItemHeight +
+        this.menuItemHeight / 2 -
+        this.menuHeight / 2;
+    },
+    /**
+     * 点击左边的栏目切换
+     * @index 传入的 ID
+     */
+    async handleLeftMenuClick(index) {
+      if (this.arr.length == 0) {
+        await this.getMenuItemTop();
+      }
+      if (index == this.current) return;
+      this.scrollRightTop = this.oldScrollTop;
+      this.$nextTick(function () {
+        this.scrollRightTop = this.arr[index];
+        this.current = index;
+        this.leftMenuStatus(index);
+      });
+    },
+    /**
+     * 右边菜单滚动
+     * 如果不存在height2,意味着数据循环已经到了最后一个,设置左边菜单为最后一项即可
+     */
+    async rightScroll(e) {
+      this.oldScrollTop = e.detail.scrollTop;
+      if (this.arr.length == 0) {
+        await this.getMenuItemTop();
+      }
+      if (this.timer) return;
+      if (!this.menuHeight) {
+        await this.getElRect('menu-scroll-view', 'menuHeight');
+      }
+      setTimeout(() => {
+        // 节流
+        this.timer = null;
+        // scrollHeight为右边菜单垂直中点位置
+        // let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
+        // scrollHeight为右边菜单头部位置
+        let scrollHeight = e.detail.scrollTop + 20;
+        for (let i = 0; i < this.arr.length; i++) {
+          let height1 = this.arr[i];
+          let height2 = this.arr[i + 1];
+          if (!height2 || (scrollHeight >= height1 && scrollHeight < height2)) {
+            this.leftMenuStatus(i);
+            return;
+          }
+        }
+      }, 10);
+    },
+  },
+};
+</script>
+
+<style scoped>
+.u-wrap {
+  /* #ifdef H5 */
+  height: calc(100vh - var(--window-top));
+  /* #endif */
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+}
+
+.u-search-box {
+  padding: 18rpx 30rpx;
+}
+
+.u-menu-wrap {
+  flex: 1;
+  display: flex;
+  overflow: hidden;
+}
+
+.u-tab-view {
+  width: 200rpx;
+  height: 100%;
+}
+
+.u-tab-item {
+  height: 110rpx;
+  background: #f6f6f6;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 26rpx;
+  color: #444;
+  font-weight: 400;
+  line-height: 1;
+}
+
+.u-tab-item-active {
+  position: relative;
+  color: #06a446;
+  font-size: 30rpx;
+  font-weight: 500;
+  background: #d6ffe7;
+}
+
+.u-tab-item-active::before {
+  content: '';
+  position: absolute;
+  border-left: 4px solid #06a446;
+  height: 52rpx;
+  left: 0;
+  top: 29rpx;
+}
+
+.u-tab-view {
+  height: 100%;
+}
+
+.right-box {
+  background-color: rgb(250, 250, 250);
+}
+
+.page-view {
+  padding: 16rpx;
+}
+
+.class-item {
+  margin-bottom: 30rpx;
+  background-color: #fff;
+  padding: 16rpx;
+  border-radius: 8rpx;
+}
+
+.class-item:last-child {
+  min-height: 100vh;
+}
+
+.item-title {
+  font-size: 26rpx;
+  color: #06a446;
+  font-weight: bold;
+}
+
+.item-menu-name {
+  margin-top: 8rpx;
+  font-weight: normal;
+  font-size: 24rpx;
+  color: #06a446;
+}
+
+.item-container {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.thumb-box {
+  width: 33.333333%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  margin-top: 20rpx;
+}
+
+.item-menu-image {
+  width: 120rpx;
+  height: 120rpx;
+}
+</style>

+ 17 - 7
src/pages/login/index.vue

@@ -2,8 +2,15 @@
   <view class="container">
     <u-image src="@/static/logo.png" mode="widthFix"></u-image>
     <view class="login-btn-wrap">
-      <u-button shape="circle" type="primary" :loading="loading" @tap="login">微信用户一键登录</u-button>
-      <u-button shape="circle" :customStyle="{ 'margin-top': '20rpx' }" @tap="$Router.push('/pages/login/phoneLogin')">手机号登录/注册</u-button>
+      <u-button shape="circle" type="primary" :loading="loading" @tap="login"
+        >微信用户一键登录</u-button
+      >
+      <u-button
+        shape="circle"
+        :customStyle="{ 'margin-top': '20rpx' }"
+        @tap="$Router.push('/pages/login/phoneLogin')"
+        >手机号登录/注册</u-button
+      >
     </view>
     <view>
       我已阅读并同意
@@ -37,11 +44,14 @@ export default {
         .then(() => {
           this.loading = false;
           uni.$u.toast('登录成功');
-          this.$store.dispatch('GetUserInfo').then(()=>{
-            this.$Router.pushTab('/pages/tabbar/home/index');
-          }).catch(err=>{
-            console.log(err);
-          })
+          this.$store
+            .dispatch('GetUserInfo')
+            .then(() => {
+              this.$Router.pushTab('/pages/tabbar/home/index');
+            })
+            .catch(err => {
+              console.log(err);
+            });
         })
         .catch(() => {
           this.loading = false;

+ 53 - 76
src/pages/tabbar/home/index.vue

@@ -43,16 +43,16 @@
     <view class="home-list">
       <u-grid :border="false" col="5">
         <u-grid-item
-          v-for="(listItem, listIndex) in list1"
-          :key="listIndex"
-          @tap="$Router.push(listItem.url)"
+          v-for="(item, index) in categories"
+          :key="item.id"
+          @tap="handleMenuClick(item)"
         >
           <u-icon
             :customStyle="{ paddingTop: 20 + 'rpx' }"
-            :name="listItem.name"
+            :name="item.icon"
             :size="25"
           ></u-icon>
-          <text class="grid-text">{{ listItem.title }}</text>
+          <text class="grid-text">{{ item.name }}</text>
         </u-grid-item>
       </u-grid>
       <u-toast ref="uToast" />
@@ -67,7 +67,7 @@
       >
         <view slot="title" class="hot-title"> 热门推荐 </view>
       </u-cell>
-      <block v-if="homeData.recommends&&homeData.recommends.length > 0">
+      <block v-if="homeData.recommends && homeData.recommends.length > 0">
         <view>
           <u-grid :border="false" col="2">
             <u-grid-item
@@ -99,7 +99,7 @@
       >
         <view slot="title" class="near-title"> 附近商家 </view>
       </u-cell>
-      <block v-if="homeData.nears&&homeData.nears.length > 0">
+      <block v-if="homeData.nears && homeData.nears.length > 0">
         <view>
           <u-grid :border="false" col="2">
             <u-grid-item
@@ -125,10 +125,11 @@
 </template>
 
 <script>
-import { getHomePage } from '@/api/home';
+import { getHomePage, getCurrentLocation } from '@/api/home';
 import { mapGetters } from 'vuex';
 import RecommendItem from '@/components/merchant/RecommendItem.vue';
 import HotItem from '@/components/merchant/HotItem.vue';
+import { getHomePageApi, getCategoriesApi } from '@/api/tabbar/home';
 
 export default {
   components: {
@@ -144,71 +145,8 @@ export default {
         'https://cdn.uviewui.com/uview/swiper/swiper2.png',
         'https://cdn.uviewui.com/uview/swiper/swiper3.png',
       ],
-      list1: [
-        {
-          name: 'photo',
-          title: '养车',
-          url: '/pages/business/classify/index',
-        },
-        {
-          name: 'lock',
-          title: '福利',
-        },
-        {
-          name: 'star',
-          title: '分类',
-        },
-        {
-          name: 'hourglass',
-          title: '自驾游',
-        },
-        {
-          name: 'home',
-          title: '门店',
-        },
-        {
-          name: 'photo',
-          title: '养车',
-        },
-        {
-          name: 'lock',
-          title: '福利',
-        },
-        {
-          name: 'star',
-          title: '分类',
-        },
-        {
-          name: 'hourglass',
-          title: '自驾游',
-        },
-        {
-          name: 'home',
-          title: '门店',
-        },
-        {
-          name: 'photo',
-          title: '养车',
-        },
-        {
-          name: 'lock',
-          title: '福利',
-        },
-        {
-          name: 'star',
-          title: '分类',
-        },
-        {
-          name: 'hourglass',
-          title: '自驾游',
-        },
-        {
-          name: 'home',
-          title: '门店',
-        },
-      ],
       homeData: {
-        categories:[],
+        categories: [],
         nears: [],
         recommends: [],
       },
@@ -229,6 +167,28 @@ export default {
       }
       return 1;
     },
+    categories() {
+      let initData = this.homeData.categories.map(item => {
+        if (!item.icon) {
+          item.icon = 'level';
+        }
+        return item;
+      });
+      let result =
+        initData.length > 14
+          ? initData
+              .splice(0, 14)
+              .concat([
+                {
+				  id:'all',
+                  icon: 'grid-fill',
+                  name: '全部',
+                  type: { code: 'ALL', description: '全部' }
+                },
+              ])
+          : initData.push({ id:'all', icon: 'grid-fill', name: '全部' });
+      return result;
+    },
   },
   onPageScroll(e) {
     this.scrollTop = e.scrollTop;
@@ -257,17 +217,19 @@ export default {
     click(name) {
       this.$refs.uToast.success(`点击了第${name}个`);
     },
+    // 获取首页数据
     getHomeData(location) {
-      getHomePage(location)
+      getHomePageApi(location)
         .then(res => {
           this.homeData = res.data;
           // 将分类数据做缓存处理
-          this.$store.commit('SET_CATEGORIES',this.homeData.categories)
+          this.$store.commit('SET_CATEGORIES', this.homeData.categories);
         })
         .catch(err => {
           console.log(err);
         });
     },
+    // 手动选择城市
     manualGetLocation() {
       uni.chooseLocation({
         success: res => {
@@ -278,11 +240,25 @@ export default {
         },
       });
     },
+    // 点击菜单
+    handleMenuClick(item){
+		if(item.id==='all'){
+			uni.navigateTo({
+				url:'pages/business/classfication/classfication'
+			})
+		}
+      uni.showToast({
+        title:'跳转至分类页面',
+        icon:'none'
+      })
+    }
   },
   watch: {
     location: {
-      handler: function (newVal, oldVal) {
-        this.getHomeData(newVal);
+      handler: async function (newVal, oldVal) {
+        const result = await getCurrentLocation(newVal);
+        const param = Object.assign({}, { region: result.data.id }, newVal);
+        this.getHomeData(param);
       },
     },
   },
@@ -333,6 +309,7 @@ export default {
   background-color: #ffffff;
   height: 360rpx;
   margin: 0 20rpx 20rpx 20rpx;
+  padding: 20rpx 0;
   border-radius: 10rpx;
 
   .grid-text {

+ 82 - 14
src/pages/tabbar/mine/index.vue

@@ -2,7 +2,10 @@
   <view class="container">
     <view class="head-wrap">
       <view class="content">
-        <view class="avatar-wrap" @tap="$Router.push('/pages/my/personalCenter/index')">
+        <view
+          class="avatar-wrap"
+          @tap="$Router.push('/pages/my/personalCenter/index')"
+        >
           <u-avatar :src="user_info.avatar" size="80"></u-avatar>
         </view>
         <view>
@@ -10,13 +13,21 @@
           <view class="user-base" v-if="user_info.nickname">
             <view class="user-nickname">{{ user_info.nickname }}</view>
             <view class="btn-wrap">
-              <view class="btn-content" @tap="$Router.push('/pages/my/settings/index')">设置</view>
+              <view
+                class="btn-content"
+                @tap="$Router.push('/pages/my/settings/index')"
+                >设置</view
+              >
               <view class="btn-content">认证</view>
             </view>
           </view>
 
           <!-- 未登录 -->
-          <view class="clickLogin" v-else @tap="$Router.push('/pages/login/index')">
+          <view
+            class="clickLogin"
+            v-else
+            @tap="$Router.push('/pages/login/index')"
+          >
             点击登录
           </view>
         </view>
@@ -25,19 +36,38 @@
       <!-- 收藏 -->
       <view class="Collect">
         <u-grid :border="false" col="4">
-          <u-grid-item v-for="(listItem, listIndex) in list1" :key="listIndex" @tap="$Router.push(listItem.url)">
-            <u-icon :customStyle="{ paddingTop: 20 + 'rpx' }" :name="listItem.name" :size="24" color="#fff" />
+          <u-grid-item
+            v-for="(listItem, listIndex) in list1"
+            :key="listIndex"
+            @tap="$Router.push(listItem.url)"
+          >
+            <u-icon
+              :customStyle="{ paddingTop: 20 + 'rpx' }"
+              :name="listItem.name"
+              :size="24"
+              color="#fff"
+            />
             <text class="grid-text">{{ listItem.title }}</text>
           </u-grid-item>
         </u-grid>
       </view>
 
       <!-- 我的订单 -->
-      <view class="order-out-box" @tap="$Router.push('/pages/my/myOrder/index')">
+      <view
+        class="order-out-box"
+        @tap="$Router.push('/pages/my/myOrder/index')"
+      >
         <view class="order-inner-box">
           <u-grid :border="false" col="4" style="background-color: #fff">
-            <u-grid-item v-for="(listItem, listIndex) in list2" :key="listIndex">
-              <u-icon :customStyle="{ paddingTop: 20 + 'rpx' }" :name="listItem.name" :size="34"></u-icon>
+            <u-grid-item
+              v-for="(listItem, listIndex) in list2"
+              :key="listIndex"
+            >
+              <u-icon
+                :customStyle="{ paddingTop: 20 + 'rpx' }"
+                :name="listItem.name"
+                :size="34"
+              ></u-icon>
               <text class="grid-text">{{ listItem.title }}</text>
             </u-grid-item>
           </u-grid>
@@ -54,7 +84,10 @@
         </view>
         <view class="income-content">
           <u-grid :border="false" col="4" bgColor="#fff">
-            <u-grid-item v-for="(listItem, listIndex) in incomeList" :key="listIndex">
+            <u-grid-item
+              v-for="(listItem, listIndex) in incomeList"
+              :key="listIndex"
+            >
               <view class="num-box">{{ listItem.num }}元</view>
               <view class="num-title">{{ listItem.title }}</view>
             </u-grid-item>
@@ -65,16 +98,49 @@
 
     <!-- 预约列表 -->
     <view class="appointList">
-      <u-cell icon="setting-fill" title="预约列表" isLink url="/pages/my/appoint/index" />
+      <u-cell
+        icon="setting-fill"
+        title="预约列表"
+        isLink
+        url="/pages/my/appoint/index"
+      />
     </view>
 
     <view class="other-out-box">
       <view class="other-inner-box">
         <u-cell-group :border="false">
-          <u-cell size="large" :border="false" icon="setting-fill" title="我的团队" isLink url=""></u-cell>
-          <u-cell size="large" :border="false" icon="setting-fill" title="关于我们" isLink url=""></u-cell>
-          <u-cell size="large" :border="false" icon="setting-fill" title="隐私条款" isLink url=""></u-cell>
-          <u-cell size="large" :border="false" icon="setting-fill" title="客服中心" isLink url=""></u-cell>
+          <u-cell
+            size="large"
+            :border="false"
+            icon="setting-fill"
+            title="我的团队"
+            isLink
+            url=""
+          ></u-cell>
+          <u-cell
+            size="large"
+            :border="false"
+            icon="setting-fill"
+            title="关于我们"
+            isLink
+            url=""
+          ></u-cell>
+          <u-cell
+            size="large"
+            :border="false"
+            icon="setting-fill"
+            title="隐私条款"
+            isLink
+            url=""
+          ></u-cell>
+          <u-cell
+            size="large"
+            :border="false"
+            icon="setting-fill"
+            title="客服中心"
+            isLink
+            url=""
+          ></u-cell>
         </u-cell-group>
       </view>
     </view>
@@ -170,6 +236,8 @@ export default {
     .clickLogin {
       font-size: 48rpx;
       color: #ffffff;
+      margin-top: 40rpx;
+      margin-left: 20rpx;
     }
 
     .avatar-wrap {

+ 16 - 0
src/utils/tools.js

@@ -0,0 +1,16 @@
+export function buildTree(data) {
+  const tree = {};
+
+  data.forEach(item => {
+    const code = item.type.code;
+    const node = { icon: item.icon, id: item.id, name: item.name };
+
+    if (!tree[code]) {
+      tree[code] = { code: code, description: item.type.description, children: [node] };
+    } else {
+      tree[code].children.push(node);
+    }
+  });
+
+  return Object.values(tree);
+}