xiansin 2 роки тому
батько
коміт
1c24dae5cc
37 змінених файлів з 1578 додано та 22 видалено
  1. 4 1
      mini/api/index.js
  2. 35 0
      mini/api/share/index.js
  3. 16 0
      mini/api/share/order.js
  4. 16 0
      mini/api/share/team.js
  5. 24 0
      mini/api/share/withdraw.js
  6. 49 0
      mini/pages.json
  7. 2 1
      mini/pages/my/index.vue
  8. 145 0
      mini/pages/share/income.vue
  9. 185 0
      mini/pages/share/index.vue
  10. 166 0
      mini/pages/share/order.vue
  11. 129 0
      mini/pages/share/team.vue
  12. 34 0
      mini/pages/share/tips.vue
  13. 269 0
      mini/pages/share/withdraw.vue
  14. 151 0
      mini/pages/share/withdrawDetail.vue
  15. BIN
      mini/static/image/share/alipay.png
  16. BIN
      mini/static/image/share/bank.png
  17. BIN
      mini/static/image/share/detail.png
  18. BIN
      mini/static/image/share/income.png
  19. BIN
      mini/static/image/share/order.png
  20. BIN
      mini/static/image/share/team.png
  21. BIN
      mini/static/image/share/wechat.png
  22. 14 1
      mini/utils/index.js
  23. 1 1
      server/_ide_helper_models.php
  24. 8 0
      server/app/Admin/Actions/Form/WithdrawReview.php
  25. 1 1
      server/app/Admin/Controllers/Share/ShareConfigController.php
  26. 1 1
      server/app/Admin/Controllers/Share/UserWithdrawController.php
  27. 48 0
      server/app/Http/Controllers/V1/Share/OrderController.php
  28. 43 0
      server/app/Http/Controllers/V1/Share/ShareController.php
  29. 45 0
      server/app/Http/Controllers/V1/Share/TeamController.php
  30. 87 0
      server/app/Http/Controllers/V1/Share/WithdrawController.php
  31. 1 1
      server/app/Http/Controllers/V1/UserController.php
  32. 11 0
      server/app/Models/User.php
  33. 54 1
      server/app/Models/UserShare.php
  34. 14 0
      server/app/Models/UserWithdraw.php
  35. 5 1
      server/config/global.php
  36. 1 1
      server/resources/lang/zh/user-withdraw.php
  37. 19 12
      server/routes/api.php

+ 4 - 1
mini/api/index.js

xqd
@@ -3,12 +3,15 @@ import setting from './setting'
 import episode from './episode'
 import sign from './sign'
 import pay from './pay'
+import share from './share'
+
 const api = {
   user,
   setting,
   episode,
   sign,
-  pay
+  pay,
+  share
 }
 
 export default api

+ 35 - 0
mini/api/share/index.js

xqd
@@ -0,0 +1,35 @@
+/**
+ * Created by JianJia.Zhou<jianjia.zhou> on 2022/8/14.
+ */
+const request = uni.$u.http
+
+import order from './order'
+import team from './team'
+import withdraw from './withdraw'
+
+export function income() {
+  return request.get(
+    'share/income'
+  )
+}
+
+export function tips() {
+  return request.get(
+    'share/tips'
+  )
+}
+
+export function setting() {
+  return request.get(
+    'share/setting'
+  )
+}
+
+export default {
+  order,
+  withdraw,
+  team,
+  income,
+  tips,
+  setting
+}

+ 16 - 0
mini/api/share/order.js

xqd
@@ -0,0 +1,16 @@
+
+/**
+ * Created by JianJia.Zhou<jianjia.zhou> on 2022/11/5.
+ */
+const request = uni.$u.http
+
+export function lists(params) {
+  return request.get(
+    'share/order/lists',
+    { params }
+  )
+}
+
+export default {
+  lists
+}

+ 16 - 0
mini/api/share/team.js

xqd
@@ -0,0 +1,16 @@
+
+/**
+ * Created by JianJia.Zhou<jianjia.zhou> on 2022/11/5.
+ */
+const request = uni.$u.http
+
+export function lists(params) {
+  return request.get(
+    'share/team/lists',
+    { params }
+  )
+}
+
+export default {
+  lists
+}

+ 24 - 0
mini/api/share/withdraw.js

xqd
@@ -0,0 +1,24 @@
+
+/**
+ * Created by JianJia.Zhou<jianjia.zhou> on 2022/8/22.
+ */
+const request = uni.$u.http
+
+export function lists(params) {
+  return request.get(
+    `share/withdraw/lists`,
+    { params }
+  )
+}
+
+export function create(data) {
+  return request.post(
+    `share/withdraw/create`,
+    data
+  )
+}
+
+export default {
+  lists,
+  create
+}

+ 49 - 0
mini/pages.json

xqd
@@ -133,6 +133,55 @@
         "navigationBarTitleText": "播放",
         "enablePullDownRefresh": false
       }
+    },
+    {
+      "path": "pages/share/index",
+      "style": {
+        "navigationBarTitleText": "分销中心",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/share/income",
+      "style": {
+        "navigationBarTitleText": "分销佣金",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/share/order",
+      "style": {
+        "navigationBarTitleText": "分销订单",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/share/team",
+      "style": {
+        "navigationBarTitleText": "我的团队",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/share/withdraw",
+      "style": {
+        "navigationBarTitleText": "提现",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/share/withdrawDetail",
+      "style": {
+        "navigationBarTitleText": "提现明细",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
+      "path": "pages/share/tips",
+      "style": {
+        "navigationBarTitleText": "用户须知",
+        "enablePullDownRefresh": false
+      }
     }
   ],
   "globalStyle": {

+ 2 - 1
mini/pages/my/index.vue

xqd xqd
@@ -107,6 +107,7 @@ export default {
         { icon: '/static/image/my-page/recharge.png', name: '充值记录', href: '/pages/my/recharge' },
         { icon: '/static/image/my-page/share.png', name: '分享好友', type: 'share' },
         { icon: '/static/image/my-page/contact.png', name: '联系客服', type: 'contact' },
+        { icon: '/static/image/my-page/share.png', name: '分销中心', href: '/pages/share/index' },
         { icon: '/static/image/my-page/protocol.png', name: '用户协议', href: '/pages/my/protocol' }
       ],
       recharge: {
@@ -231,7 +232,7 @@ export default {
 
 <style lang="scss" scoped>
   .container {
-    padding: 20px 20rpx 0;
+    padding: 20px 20rpx 180rpx;
     font-size: 30rpx;
     >.header{
       .user-box{

+ 145 - 0
mini/pages/share/income.vue

xqd
@@ -0,0 +1,145 @@
+<template>
+  <view class="share-income">
+    <view class="head-box main-between cross-center">
+      <view class="left-box">
+        <text>分销佣金</text>
+        <view class="price main-left cross-bottom">{{ userInfo.total_income }}
+          <view class="unit">元</view>
+        </view>
+      </view>
+      <view
+        class="right-box"
+        @click="$u.route('/pages/share/withdrawDetail')"
+      >提现明细
+      </view>
+    </view>
+    <view class="menu-group">
+      <button
+        v-for="(menu,index) in menus"
+        :key="index"
+        class="menu-item main-between cross-center"
+        @click="handleMenu(menu)"
+      >
+        <view class="left-box dir-left-nowrap cross-center">
+          <text>{{ menu.name }}</text>
+        </view>
+        <view class="right-box main-left cross-center">
+          <text v-if="menu.showNumber">{{ menu.number }} 元</text>
+          <u-icon name="arrow-right" :color="$colors.infoColor" bold top="1" />
+        </view>
+      </button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+export default {
+  name: 'ShareIncome',
+  data() {
+    return {
+      menus: [
+        { name: '可提现佣金', href: '/pages/share/withdraw', showNumber: true, number: 0 },
+        { name: '已提现佣金', href: '/pages/share/withdrawDetail?active=3', showNumber: true, number: 0 },
+        { name: '待打款佣金', href: '/pages/share/withdrawDetail?active=2', showNumber: true, number: 0 },
+        { name: '用户须知', href: '/pages/share/tips', showNumber: false }
+      ]
+    }
+  },
+  computed: {
+    ...mapState({
+      userInfo: seate => seate.user.info
+    })
+  },
+  methods: {
+    handleMenu(menu) {
+      if (menu.href) {
+        this.$u.route(menu.href)
+      }
+    },
+    getIncome() {
+      this.$api.share.income().then(res => {
+        this.menus[0].number = this.userInfo.income
+        this.menus[1].number = res.data.been
+        this.menus[2].number = res.data.wait
+      })
+    }
+  },
+  onLoad() {
+    this.getIncome()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.share-income {
+  padding: 30rpx 30rpx 80rpx;
+  .head-box{
+    background: #1C203B;
+    color: #6eebe8;
+    padding: 50rpx 30rpx;
+    border-radius: 20rpx;
+    .left-box{
+      text{
+        font-size: 26rpx;
+      }
+      .price{
+        margin-top: 12rpx;
+        font-size: 42rpx;
+        font-weight: bold;
+        .unit{
+          font-weight: normal;
+          font-size: 28rpx;
+          margin-bottom: 5rpx;
+          margin-left: 2rpx;
+        }
+      }
+    }
+    .right-box{
+      border: 1rpx solid #6eebe8;
+      border-radius: 30rpx;
+      padding: 6rpx 20rpx;
+      font-size: 26rpx;
+    }
+  }
+
+  .menu-group{
+    .menu-item{
+      padding: 20rpx 0;
+      background: transparent;
+      border: none;
+      text-align: unset;
+      width: 100%;
+      line-height: initial;
+      font-size: initial;
+      justify-content: space-between;
+      border-bottom: 1rpx solid #232849;
+      border-radius: 0;
+      color: #fff;
+      margin-top: 40rpx;
+      &:after{
+        content: unset;
+      }
+      .left-box{
+        flex: 1;
+        .icon{
+          transform: translateY(4rpx);
+          image{
+            width: 55rpx;
+            height: 55rpx;
+          }
+        }
+        text{
+          color: #fff;
+          margin-left: 10rpx;
+        }
+      }
+      .right-box{
+        text{
+          margin-right: 20rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 185 - 0
mini/pages/share/index.vue

xqd
@@ -0,0 +1,185 @@
+<template>
+  <view class="share-index">
+    <view class="head-box">
+      <view class="user-info dir-left-nowrap">
+        <view class="head-img">
+          <image :src="userInfo.avatar" alt="" />
+        </view>
+        <view class="base-info dir-top-wrap main-center">
+          <view class="nickname">{{ userInfo.nickname }}</view>
+          <view class="parent">推荐人: {{ userInfo.parent ? userInfo.parent.nickname : '' }}</view>
+        </view>
+      </view>
+      <view class="withdraw-box main-between cross-center">
+        <view class="withdraw-item dir-top-wrap main-center" @click="$u.route('/pages/share/withdraw')">
+          <view class="static-txt main-left cross-center">
+            可提现佣金
+            <view class="badge">提现</view>
+          </view>
+          <view class="price main-left cross-center">
+            {{ userInfo.income }}
+            <view class="unit">元</view>
+          </view>
+        </view>
+        <view class="withdraw-item dir-top-wrap main-center">
+          <view class="static-txt">
+            已提现佣金
+          </view>
+          <view class="price main-left cross-center">
+            {{ parseFloat(userInfo.total_income - userInfo.income).toFixed(2) }}
+            <view class="unit">元</view>
+          </view>
+        </view>
+      </view>
+    </view>
+    <!--菜单-->
+    <view class="menu-group">
+      <button
+        v-for="(menu,index) in menus"
+        :key="index"
+        class="menu-item main-between cross-center"
+        :open-type="menu.type ? menu.type : ''"
+        @click="handleMenu(menu)"
+      >
+        <view class="left-box dir-left-nowrap cross-center">
+          <view class="icon">
+            <image :src="menu.icon" />
+          </view>
+          <text>{{ menu.name }}</text>
+        </view>
+        <u-icon name="arrow-right" :color="$colors.infoColor" bold />
+      </button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+export default {
+  data() {
+    return {
+      menus: [
+        { icon: '/static/image/share/income.png', name: '分销佣金', href: '/pages/share/income' },
+        { icon: '/static/image/share/order.png', name: '分销订单', href: '/pages/share/order' },
+        { icon: '/static/image/share/detail.png', name: '提现明细', href: '/pages/share/withdrawDetail' },
+        { icon: '/static/image/share/team.png', name: '我的团队', href: '/pages/share/team' }
+      ]
+    }
+  },
+  computed: {
+    ...mapState({
+      userInfo: seate => seate.user.info
+    })
+  },
+  methods: {
+    handleMenu(menu) {
+      if (menu.href) {
+        this.$u.route(menu.href)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.share-index {
+  color: #6eebe8;
+  font-size: 32rpx;
+  padding: 40rpx 30rpx 80rpx;
+  .head-box{
+    background: #1C203B;
+    border-radius: 20rpx;
+    padding: 40rpx 0;
+    margin-bottom: 50rpx;
+    .user-info{
+      padding: 0 30rpx 40rpx;
+      border-bottom: 1rpx #232849 solid;
+      .head-img{
+        width: 120rpx;
+        height: 120rpx;
+        border-radius: 50%;
+        overflow: hidden;
+        image{
+          width: 100%;
+          height: 100%;
+        }
+      }
+      .base-info{
+        margin-left: 30rpx;
+        .parent{
+          font-size: 26rpx;
+        }
+      }
+    }
+    .withdraw-box{
+      padding: 40rpx 0 0;
+      .withdraw-item{
+        flex: 1;
+        position: relative;
+        padding: 0 40rpx;
+        &:first-child{
+          &:after{
+            content: "";
+            position: absolute;
+            background: #232849;
+            right: 0;
+            top: 50%;
+            height: 60%;
+            width: 1rpx;
+            transform: translateY(-50%);
+          }
+        }
+        .static-txt{
+          font-size: 26rpx;
+          .badge{
+            font-size: 18rpx;
+            border: 1rpx solid #6eebe8;
+            border-radius: 30rpx;
+            padding: 2rpx 20rpx;
+            margin-left: 30rpx;
+          }
+        }
+        .price{
+          margin-top: 10rpx;
+          font-size: 48rpx;
+          .unit{
+            font-size: 34rpx;
+            margin-left: 4rpx;
+          }
+        }
+      }
+    }
+  }
+  .menu-group{
+    .menu-item{
+      padding: 20rpx 0;
+      background: transparent;
+      border: none;
+      text-align: unset;
+      width: 100%;
+      line-height: initial;
+      font-size: initial;
+      justify-content: space-between;
+      border-bottom: 1rpx solid #232849;
+      border-radius: 0;
+      &:after{
+        content: unset;
+      }
+      .left-box{
+        flex: 1;
+        .icon{
+          transform: translateY(4rpx);
+          image{
+            width: 55rpx;
+            height: 55rpx;
+          }
+        }
+        text{
+          color: #fff;
+          margin-left: 10rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 166 - 0
mini/pages/share/order.vue

xqd
@@ -0,0 +1,166 @@
+<template>
+  <view class="share-order">
+    <view
+      v-for="(item, index) in order"
+      :key="index"
+      class="order-box"
+    >
+      <view class="order-num">
+        订单号: {{ item.order_id }}
+      </view>
+      <view class="child-info main-between cross-center">
+        <view class="base main-left cross-center">
+          <view class="head-img">
+            <image :src="item.order.user.avatar" />
+          </view>
+          <view class="nickname main-left cross-center">
+            <view class="nickname">
+              <u-text :text="item.order.user.nickname" :lines="1" color="#ffffff" size="28rpx" />
+            </view>
+            <view class="level">1级</view>
+          </view>
+        </view>
+        <view class="income-info main-left cross-center">
+          <text>已得佣金:{{ item.income }}元</text>
+          <u-icon :name="item.showDetail?'arrow-up':'arrow-down'" top="1" @click="handleShow(item)" />
+        </view>
+      </view>
+      <view v-show="item.showDetail" class="detail main-between cross-center">
+        <view class="goods-info main-left cross-center">
+          <view class="cover-img">
+            <image />
+          </view>
+          <view class="combo dir-top-wrap main-center">
+            <text class="type">{{ item.type_name }}</text>
+            <text>{{ item.order.combo.name }}</text>
+          </view>
+        </view>
+        <view class="income dir-top-wrap">
+          <view class="num">x1</view>
+          <view class="price">¥{{ item.order.combo.price }}</view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'ShareOrder',
+  components: {},
+
+  data() {
+    return {
+      limit: 10,
+      page: 1,
+      isMore: true,
+      order: []
+    }
+  },
+  computed: {},
+  methods: {
+    handleShow(item) {
+      item.showDetail = !item.showDetail
+    },
+    getOrder() {
+      this.$loading()
+      this.$api.share.order.lists({ limit: this.limit, page: this.page }).then(res => {
+        this.$hideLoading()
+        if (res.data.length) {
+          res.data.forEach(obj => {
+            obj.showDetail = false
+          })
+          this.order = this.order.concat(res.data)
+        } else {
+          this.isMore = false
+        }
+      })
+    }
+  },
+  onLoad() {
+    this.getOrder()
+  },
+  onReachBottom(e) {
+    if (!this.isMore) return
+    this.page += 1
+    this.getOrder()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.share-order {
+  padding: 40rpx 30rpx;
+  font-size: 28rpx;
+  .order-box{
+    background: #1C203B;
+    color: #ffffff;
+    padding: 30rpx 0;
+    border-radius: 20rpx;
+    margin-bottom: 30px;
+    .order-num{
+      padding: 0 30rpx 30rpx;
+      border-bottom: 1rpx #232849 solid;
+    }
+    .child-info{
+      padding: 30rpx 30rpx;
+      .base{
+        .head-img{
+          width: 70rpx;
+          height: 70rpx;
+          border-radius: 50%;
+          overflow: hidden;
+          background: #ccc;
+          image{
+            width: 100%;
+            height: 100%;
+          }
+        }
+        .nickname{
+          margin-left: 10rpx;
+          flex: 1;
+          .level{
+            color: #6eebe8;
+          }
+        }
+      }
+      .income-info{
+        text{
+          margin-right: 18rpx;
+        }
+      }
+    }
+    .detail{
+      padding: 30rpx 30rpx 0;
+      border-top: 1rpx #232849 solid;
+      .goods-info{
+        .cover-img{
+          width: 80rpx;
+          height: 80rpx;
+          border-radius: 8rpx;
+          overflow: hidden;
+          background: #ccc;
+          image{
+            width: 100%;
+            height: 100%;
+          }
+        }
+        .combo{
+          margin-left: 20rpx;
+          .type{
+            margin-bottom: 6rpx;
+          }
+        }
+      }
+      .income{
+        color: #6eebe8;
+        text-align: right;
+        .num{
+          font-size: 24rpx;
+          margin-bottom: 6rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 129 - 0
mini/pages/share/team.vue

xqd
@@ -0,0 +1,129 @@
+<template>
+  <view class="share-team">
+    <view class="title">
+      <text>一级分销名称(1)</text>
+    </view>
+
+    <view
+      v-for="(item,index) in data"
+      :key="index"
+      class="child-info"
+    >
+      <view class="head-box main-between cross-center">
+        <view class="base-info dir-left-nowrap">
+          <view class="head-img">
+            <image :src="item.avatar" />
+          </view>
+          <view class="nickname-box dir-top-wrap main-center">
+            <view class="nickname">
+              {{ item.nickname }}
+            </view>
+            <view class="bind-at">
+              绑定时间:{{ item.become_child_at }}
+            </view>
+          </view>
+        </view>
+        <view class="child-num">
+          推广{{ item.child_count }}人
+        </view>
+      </view>
+      <view class="price-box main-between cross-center">
+        <view>{{ item.child_order_sum_income }}元</view>
+        <view>{{ item.child_order_count }}个订单</view>
+      </view>
+    </view>
+  </view></template>
+
+<script>
+export default {
+  name: 'ShareTeam',
+  data() {
+    return {
+      limit: 10,
+      page: 1,
+      isMore: true,
+      data: []
+    }
+  },
+  computed: {},
+  methods: {
+    getTeam() {
+      this.$loading()
+      this.$api.share.team.lists({ limit: this.limit, page: this.page }).then(res => {
+        this.$hideLoading()
+        if (res.data.length) {
+          this.data = this.data.concat(res.data)
+        } else {
+          this.isMore = false
+        }
+      })
+    }
+  },
+  onLoad() {
+    this.getTeam()
+  },
+  onReachBottom(e) {
+    if (!this.isMore) return
+    this.page += 1
+    this.getTeam()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.share-team {
+  padding: 20rpx 30rpx 80rpx;
+  font-size: 28rpx;
+  .title{
+    text-align: center;
+    color: #6eebe8;
+    margin-bottom: 30rpx;
+    text{
+      padding-bottom: 10rpx;
+      border-bottom: 4rpx solid #6eebe8;
+    }
+  }
+  .child-info{
+    background: #1C203B;
+    color: #ffffff;
+    padding: 30rpx 0;
+    border-radius: 20rpx;
+    margin-bottom: 30px;
+    .head-box{
+      padding: 0 30rpx 30rpx;
+      border-bottom: 1rpx #232849 solid;
+      .base-info{
+        .head-img{
+          width: 80rpx;
+          height: 80rpx;
+          border-radius: 50%;
+          overflow: hidden;
+          background: #ccc;
+          image{
+            width: 100%;
+            height: 100%;
+          }
+        }
+        .nickname-box{
+          margin-left: 10rpx;
+          .nickname{
+            font-size: 30rpx;
+            margin-bottom: 4rpx;
+          }
+          .bind-at{
+            font-size: 24rpx;
+          }
+        }
+      }
+      .child-num{
+        color: #6eebe8;
+        font-size: 32rpx;
+        margin-top: -20rpx;
+      }
+    }
+    .price-box{
+      padding: 30rpx 30rpx 0;
+    }
+  }
+}
+</style>

+ 34 - 0
mini/pages/share/tips.vue

xqd
@@ -0,0 +1,34 @@
+<template>
+  <view class="withdraw-tips">
+    <u-parse :content="tips" />
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'Withdraw',
+  data() {
+    return {
+      tips: ''
+    }
+  },
+  computed: {},
+  methods: {
+    getTips() {
+      this.$api.share.tips().then(res => {
+        this.tips = res.data
+      })
+    }
+  },
+  onLoad() {
+    this.getTips()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.withdraw-tips {
+  color: #fff;
+  padding: 30rpx 30rpx 80rpx;
+}
+</style>

+ 269 - 0
mini/pages/share/withdraw.vue

xqd
@@ -0,0 +1,269 @@
+<template>
+  <view class="withdraw">
+    <view class="overage">
+      账户剩余金额:<text class="number">{{ userInfo.income }}元</text>
+    </view>
+    <view class="input-box main-left cross-center">
+      <view class="left">姓名</view>
+      <view class="center">
+        <input v-model="name" type="text" placeholder="请输入姓名">
+      </view>
+    </view>
+    <view class="input-box main-left cross-center">
+      <view class="left">手机号</view>
+      <view class="center">
+        <input v-model="phone_num" type="number" placeholder="请输入手机号">
+      </view>
+    </view>
+    <view class="input-box main-left cross-center">
+      <view class="left">提现账号</view>
+      <view class="center">
+        <input v-model="account" type="text" placeholder="请输入提现账号">
+      </view>
+    </view>
+    <view class="input-box main-left cross-center">
+      <view class="left">¥</view>
+      <view class="center">
+        <input v-model="price" type="text" placeholder="请输入提现金额">
+      </view>
+      <view class="right" @click="handleAll">全部</view>
+    </view>
+
+    <view class="tips">
+      <view>提现金额不能小于{{ setting.withdraw_min }}元</view>
+      <view>提现需要加收{{ setting.withdraw_discount }}%手续费</view>
+    </view>
+    <view class="type-box main-between cross-center" @click="show = true">
+      <view>提现方式</view>
+      <view class="main-left cross-center">
+        <text>{{ selectType.name }}</text>
+        <u-icon name="arrow-right" :color="$colors.infoColor" bold top="1" />
+      </view>
+    </view>
+
+    <view class="btn" @click="handleConfirm">提交申请</view>
+    <!--   选择提现方式 -->
+    <u-popup
+      :show="show"
+      :round="20"
+      closeable
+      @close="handleClose"
+    >
+      <view class="popup-content">
+        <view
+          v-for="(type, index) in types"
+          :key="index"
+          class="type-item main-between cross-center"
+          @click="handleSelect(type, index)"
+        >
+          <view class="left-box dir-left-nowrap cross-center">
+            <view class="icon" :class="{bank: index === 2}">
+              <image :src="type.icon" />
+            </view>
+            <text>{{ type.name }}</text>
+          </view>
+          <u-icon v-if="selectIndex === index" name="checkmark" color="#68EBE9" size="24" />
+        </view>
+      </view>
+    </u-popup>
+  </view>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+export default {
+  name: 'Withdraw',
+  data() {
+    return {
+      price: '',
+      account: '',
+      name: '',
+      phone_num: '',
+      setting: { withdraw_min: 0, withdraw_discount: 0 },
+      show: false,
+      types: [
+        { icon: '/static/image/share/wechat.png', value: 1, name: '微信线下打款' },
+        { icon: '/static/image/share/alipay.png', value: 2, name: '支付宝线下打款' },
+        { icon: '/static/image/share/bank.png', value: 3, name: '银联线下打款' }
+      ],
+      selectIndex: 0,
+      selectType: {}
+    }
+  },
+  computed: {
+    ...mapState({
+      userInfo: seate => seate.user.info
+    })
+  },
+  methods: {
+    handleConfirm() {
+      if (!this.name) {
+        this.$u.toast(`请输入姓名`)
+        return
+      }
+      if (!this.phone_num) {
+        this.$u.toast(`请输入手机号`)
+        return
+      }
+      if (!this.account) {
+        this.$u.toast(`请输入账号`)
+        return
+      }
+      if (Object.keys(this.selectType).length === 0) {
+        this.$u.toast(`请选择提现方式`)
+        return
+      }
+      if (parseFloat(this.price) < parseFloat(this.setting.withdraw_min)) {
+        this.$u.toast(`提现金额不能小于${this.setting.withdraw_min}元`)
+        return
+      }
+      if (parseFloat(this.price) > this.userInfo.income) {
+        this.$u.toast(`提现金额不能大于可提现余额`)
+        return
+      }
+      if (Object.keys(this.selectType).length === 0) {
+        this.$u.toast(`请选择提现方式`)
+        return
+      }
+
+      const params = {
+        price: this.price,
+        type: this.selectType.value,
+        account: this.account,
+        name: this.name,
+        phone_num: this.phone_num
+      }
+      this.$loading()
+      this.$api.share.withdraw.create(params).then(res => {
+        this.$hideLoading()
+        this.$u.toast(`提交成功`)
+        this.$api.user.info().then(res => {
+          this.$store.dispatch('user/info', res.data)
+          setTimeout(() => {
+            this.$u.route({ type: 'redirect', url: '/pages/share/withdrawDetail?active=1' })
+          }, 500)
+        })
+      }).catch(() => {
+        this.$hideLoading()
+      })
+    },
+    handleAll() {
+      this.price = this.userInfo.income
+    },
+    handleSelect(item, index) {
+      this.selectIndex = index
+      this.selectType = item
+      this.handleClose()
+    },
+    handleClose() {
+      this.show = false
+    },
+    getSetting() {
+      this.$loading()
+      this.$api.share.setting().then(res => {
+        this.$hideLoading()
+        this.setting = res.data
+      })
+    }
+  },
+  onLoad() {
+    this.getSetting()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.withdraw {
+  padding: 30rpx 30rpx 80rpx;
+  color: #FFFFFF;
+  font-size: 38rpx;
+  .overage{
+    font-weight: bold;
+    padding-bottom: 30rpx;
+    border-bottom: 1rpx solid #232849;
+    .number{
+      color: #6eebe8;
+    }
+  }
+  .input-box{
+    padding: 30rpx 0;
+    border-bottom: 1rpx solid #232849;
+    .left{
+      width: 180rpx;
+    }
+    .center{
+      flex: 1;
+      margin-left: 10rpx;
+    }
+    .right{
+      font-size: 28rpx;
+      color: #6eebe8;
+    }
+  }
+  .tips{
+    background: #1c203b;
+    border-radius: 20rpx;
+    padding: 30rpx 20rpx;
+    color: #ccc;
+    margin: 30rpx 0;
+    font-size: 24rpx;
+  }
+  .type-box{
+    border-bottom: 1rpx solid #232849;
+    padding: 30rpx 0;
+    text{
+      margin-right: 10rpx;
+      font-size: 32rpx;
+    }
+  }
+  .btn{
+    background: linear-gradient(270deg, #6EEBE8 0%, #FF74B9 100%);
+    text-align: center;
+    padding: 26rpx 0;
+    width: 90%;
+    margin: 60rpx auto;
+    border-radius: 50rpx;
+    font-size: 32rpx;
+  }
+  .popup-content{
+    padding: 120rpx 0 40rpx;
+    .type-item{
+      padding: 20rpx 40rpx;
+      background: transparent;
+      border: none;
+      text-align: unset;
+      width: 100%;
+      line-height: initial;
+      font-size: initial;
+      justify-content: space-between;
+      border-top: 1rpx solid #CECFD1;
+      border-radius: 0;
+      &:first-child{
+
+      }
+      .left-box{
+        flex: 1;
+        .icon{
+          width: 60rpx;
+          height: 48rpx;
+          transform: translateY(4rpx);
+          image{
+            width: 48rpx;
+            height: 48rpx;
+          }
+          &.bank{
+            image{
+              width: 56rpx;
+              height: 38rpx;
+            }
+          }
+        }
+        text{
+          color: #777777;
+          margin-left: 10rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 151 - 0
mini/pages/share/withdrawDetail.vue

xqd
@@ -0,0 +1,151 @@
+<template>
+  <view class="withdraw-detail">
+    <u-sticky bg-color="#151728">
+      <u-tabs
+        :list="tabs"
+        line-color="#6EEBE8"
+        :active-style="{color: '#6EEBE8'}"
+        :inactive-style="{color: '#ffffff'}"
+        :item-style="{width: 'calc(750rpx / 5)', height: '44px'}"
+        :current="activeIndex"
+        @click="handleTabClick"
+      />
+    </u-sticky>
+    <template v-for="(tab, index) in tabs">
+      <view
+        v-if="activeIndex === index"
+        :key="index"
+        class="detail-box"
+      >
+        <view
+          v-for="(data, dataIndex) in tab.data"
+          :key="dataIndex"
+          class="detail-item"
+        >
+          <view class="date">
+            {{ data.created_at }}
+          </view>
+          <view class="info">
+            <view class="type main-left cross-center">
+              {{ data.type_name }}
+              <view class="status">{{ data.status_name }}</view>
+            </view>
+            <view class="withdraw-box main-between cross-center">
+              <view class="item">
+                <view>提现账户:{{ data.account }}</view>
+                <view>提现时间: {{ data.created_at }}</view>
+              </view>
+              <view class="item price-box">
+                <view class="price">{{ data.price }}</view>
+                <view class="discount">手续费: {{ data.discount }}</view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+    </template>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      tabs: [
+        { name: '全部', status: -1, data: [], limit: 10, page: 1, isMore: true },
+        { name: '待审核', status: 0, data: [], limit: 10, page: 1, isMore: true },
+        { name: '待打款', status: 1, data: [], limit: 10, page: 1, isMore: true },
+        { name: '已打款', status: 2, data: [], limit: 10, page: 1, isMore: true },
+        { name: '无效', status: 3, data: [], limit: 10, page: 1, isMore: true }
+      ],
+      activeIndex: 0
+    }
+  },
+  computed: {},
+  methods: {
+    handleTabClick(item) {
+      this.activeIndex = item.index
+      const tab = this.tabs[this.activeIndex]
+      if (tab.data.length === 0 && tab.isMore) {
+        this.getData()
+      }
+    },
+    getData() {
+      this.$loading()
+      const item = this.tabs[this.activeIndex]
+      const params = { limit: item.limit, page: item.page, status: item.status }
+      this.$api.share.withdraw.lists(params).then(res => {
+        this.$hideLoading()
+        if (res.data.length) {
+          item.data = item.data.concat(res.data)
+        } else {
+          item.isMore = false
+        }
+      })
+    }
+  },
+  onLoad(options) {
+    this.activeIndex = typeof options.active !== 'undefined' ? parseInt(options.active) : 0
+    this.getData()
+  },
+  onReachBottom(e) {
+    const item = this.tabs[this.activeIndex]
+    if (!item.isMore) return
+    item.page += 1
+    this.getData()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.withdraw-detail {
+  font-size: 28rpx;
+  padding: 30rpx 0 80rpx;
+  .detail-box{
+    padding: 0 30rpx;
+    margin-top: 30rpx;
+    .detail-item{
+      background: #1C203B;
+      color: #ffffff;
+      border-radius: 10rpx;
+      padding: 30rpx 0;
+      margin-bottom: 20rpx;
+      .date{
+        border-bottom: 1rpx #232849 solid;
+        padding: 0 30rpx 30rpx;
+      }
+      .info{
+        padding: 30rpx 30rpx 0;
+        .type{
+          font-size: 32rpx;
+          .status{
+            font-size: 20rpx;
+            color: #ff74b9;
+            border: 1rpx solid #FF74B9;
+            border-radius: 30rpx;
+            padding: 2rpx 20rpx;
+            margin-left: 20rpx;
+          }
+        }
+        .withdraw-box{
+          margin-top: 20rpx;
+          .item{
+            >view:first-child{
+              margin-bottom: 10rpx;
+            }
+            &.price-box{
+              color: #6eebe8;
+              font-size: 36rpx;
+              font-weight: bold;
+              .discount{
+                font-size: 24rpx;
+                font-weight: normal;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>

BIN
mini/static/image/share/alipay.png


BIN
mini/static/image/share/bank.png


BIN
mini/static/image/share/detail.png


BIN
mini/static/image/share/income.png


BIN
mini/static/image/share/order.png


BIN
mini/static/image/share/team.png


BIN
mini/static/image/share/wechat.png


+ 14 - 1
mini/utils/index.js

xqd
@@ -29,7 +29,20 @@ export function checkOS() {
   return true
 }
 
+const shareMessage = user => {
+  return {
+    path: '/pages/index/index',
+    params: {
+      user_id: user.id
+    },
+    title: '张四爷剧场',
+    desc: '张四爷剧场'
+    // imageUrl: ''
+  }
+}
+
 export default {
   copyText,
-  checkOS
+  checkOS,
+  shareMessage
 }

+ 1 - 1
server/_ide_helper_models.php

xqd
@@ -77,6 +77,6 @@ namespace App\Models{
  * @method static \Illuminate\Database\Eloquent\Builder|User whereBecomeShareAt($value)
  * @property-read User|null $child
  */
-	class User extends \Eloquent implements \PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject {}
+//	class User extends \Eloquent implements \PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject {}
 }
 

+ 8 - 0
server/app/Admin/Actions/Form/WithdrawReview.php

xqd xqd
@@ -2,6 +2,7 @@
 
 namespace App\Admin\Actions\Form;
 
+use App\Models\User;
 use App\Models\UserEpisodesRecord;
 use App\Models\UserWithdraw;
 use Dcat\Admin\Contracts\LazyRenderable;
@@ -22,6 +23,13 @@ class WithdrawReview extends Form implements LazyRenderable
                 $withdraw->status = $status;
                 $withdraw->save();
             }
+
+            // 驳回返还收益
+            if($withdraw->status == 3){
+                $user = User::find($withdraw->user_id);
+                $user->income = $user->income + $withdraw->price;
+                $user->save();
+            }
         } catch (\Exception $exception) {
             return $this->response()->error($exception->getMessage());
         }

+ 1 - 1
server/app/Admin/Controllers/Share/ShareConfigController.php

xqd
@@ -58,7 +58,7 @@ class ShareConfigController extends AdminController
                     $form->number('withdraw_min','最少提现额度')->required();
                     $form->number('withdraw_max','每日提现上限')->required();
                     $form->number('withdraw_discount','提现手续费')->required();
-                    $form->textarea('withdraw_desc','提现说明')->value($config->withdraw_desc);
+                    $form->editor('withdraw_desc','提现说明')->value($config->withdraw_desc);
 
                     $form->action('share/setting/save');
                     $column->append(Box::make(trans('admin.edit'), $form));

+ 1 - 1
server/app/Admin/Controllers/Share/UserWithdrawController.php

xqd
@@ -33,7 +33,7 @@ class UserWithdrawController extends AdminController
             $grid->column('name');
             $grid->column('phone_num');
             $grid->column('type')->using(config('global.withdraw_type'))
-                ->label(['primary','success','danger']);
+                ->label(['default','primary','success','info']);
             $grid->column('account');
             $grid->column('price');
             $grid->column('discount');

+ 48 - 0
server/app/Http/Controllers/V1/Share/OrderController.php

xqd
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Created by PhpStorm
+ * DateTime: 2022/11/5 0:31
+ *
+ * @description
+ */
+namespace App\Http\Controllers\V1\Share;
+
+use App\Http\Controllers\V1\Controller;
+use App\Models\User;
+use App\Models\UserShare;
+use Dingo\Api\Http\Request;
+use Illuminate\Http\JsonResponse;
+
+class OrderController extends Controller
+{
+    public function lists(Request $request): JsonResponse
+    {
+        $limit = $request->input('limit', 10);
+        $page = $request->input('page', 1);
+        $offset = ($page - 1) * 10;
+        $user = \user();
+
+        $lists = UserShare::with([
+            'vipOrder:id,user_id,combo_id,pay_id,status,created_at',
+            'vipOrder.user:id,nickname,avatar',
+            'vipOrder.combo:id,name,price',
+            'rechargeOrder:id,user_id,combo_id,price,gold,pay_id,status,created_at',
+            'rechargeOrder.user:id,nickname,avatar',
+            'rechargeOrder.combo:id,name,price',
+        ])->where('user_id', $user->id)
+            ->limit($limit)
+            ->offset($offset)
+            ->get();
+
+        /* @var UserShare $list*/
+        foreach ($lists as $list){
+            $list->order = $list;
+            $list->type_name = $list->order_type;
+            unset($list->vipOrder);
+            unset($list->rechargeOrder);
+        }
+
+        return $this->success($lists);
+    }
+
+}

+ 43 - 0
server/app/Http/Controllers/V1/Share/ShareController.php

xqd
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Created by PhpStorm
+ * DateTime: 2022/11/5 0:31
+ *
+ * @description
+ */
+namespace App\Http\Controllers\V1\Share;
+
+use App\Http\Controllers\V1\Controller;
+use App\Models\ShareConfig;
+use App\Models\UserWithdraw;
+
+class ShareController extends Controller
+{
+    public function income()
+    {
+        // 已提现
+        $been = UserWithdraw::where('user_id', \user()->id)
+            ->where('status', 2)
+            ->sum('price');
+        // 待打款
+        $wait = UserWithdraw::where('user_id', \user()->id)
+            ->where('status', 1)
+            ->sum('price');
+        return $this->success([
+            'been' =>$been,
+            'wait' =>$wait,
+        ]);
+    }
+
+    public function tips()
+    {
+        $config = ShareConfig::first();
+        return $this->success($config->withdraw_desc);
+    }
+
+    public function setting()
+    {
+        $config = ShareConfig::first();
+        return $this->success($config);
+    }
+}

+ 45 - 0
server/app/Http/Controllers/V1/Share/TeamController.php

xqd
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Created by PhpStorm
+ * DateTime: 2022/11/5 0:31
+ *
+ * @description
+ */
+namespace App\Http\Controllers\V1\Share;
+
+use App\Http\Controllers\V1\Controller;
+use App\Models\User;
+use App\Models\UserShare;
+use Carbon\Carbon;
+use Dingo\Api\Http\Request;
+use Illuminate\Http\JsonResponse;
+
+class TeamController extends Controller
+{
+    public function lists(Request $request): JsonResponse
+    {
+        $limit = $request->input('limit', 10);
+        $page = $request->input('page', 1);
+        $offset = ($page - 1) * 10;
+        $user = \user();
+
+        $lists = User::withCount('child')
+            ->withCount('childOrder')
+            ->withSum('childOrder','income')
+            ->where('parent_id', $user->id)
+            ->limit($limit)
+            ->offset($offset)
+            ->get();
+
+        /* @var User $list*/
+        foreach ($lists as $list){
+            $list->become_child_at = Carbon::parse($list->become_child_at)->toDateString();
+            $list->child_order_sum_income = $list->child_order_sum_income ? : 0;
+            $list->child_order_count = $list->child_order_count ? : 0;
+        }
+
+
+        return $this->success($lists);
+    }
+
+}

+ 87 - 0
server/app/Http/Controllers/V1/Share/WithdrawController.php

xqd
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Created by PhpStorm
+ * DateTime: 2022/11/5 0:31
+ *
+ * @description
+ */
+namespace App\Http\Controllers\V1\Share;
+
+use App\Http\Controllers\V1\Controller;
+use App\Models\ShareConfig;
+use App\Models\User;
+use App\Models\UserShare;
+use App\Models\UserWithdraw;
+use Carbon\Carbon;
+use Dingo\Api\Http\Request;
+use Illuminate\Http\JsonResponse;
+
+class WithdrawController extends Controller
+{
+    public function lists(Request $request): JsonResponse
+    {
+        $limit = $request->input('limit', 10);
+        $page = $request->input('page', 1);
+        $status = $request->input('status', -1);
+        $offset = ($page - 1) * 10;
+        $user = \user();
+
+        $lists = UserWithdraw::where('user_id', $user->id)
+            ->when($status != -1, function ($query) use ($status){
+                $query->where('status', $status);
+            })
+            ->limit($limit)
+            ->offset($offset)
+            ->get();
+
+        /* @var UserWithdraw $list*/
+        foreach ($lists as $list){
+            $list->status_name = $list->status;
+            $list->type_name = $list->type;
+        }
+
+        return $this->success($lists);
+    }
+
+    public function create(Request $request): JsonResponse
+    {
+
+        try {
+            $config = ShareConfig::first();
+            $price = $request->input('price');
+            $account = $request->input('account');
+            $phoneNum = $request->input('phone_num');
+            $type = $request->input('type');
+            $name = $request->input('name');
+            $user  = \user();
+            if($price < $config->withdraw_min){
+                return  $this->error("提现金额不能小于{$config->withdraw_min}元");
+            }
+            if($price > $user->income){
+                return  $this->error("提现金额不能小于{$config->withdraw_min}元");
+            }
+            \DB::beginTransaction();
+
+            $withdraw = new UserWithdraw();
+            $withdraw->user_id = $user->id;
+            $withdraw->name = $name;
+            $withdraw->account = $account;
+            $withdraw->phone_num = $phoneNum;
+            $withdraw->price = $price;
+            $withdraw->type = $type;
+            $withdraw->discount = $price * $config->withdraw_discount / 100;
+            $withdraw->save();
+
+            $user->income = $user->income - $price;
+            $user->save();
+
+            \DB::commit();
+
+            return $this->success();
+        }catch (\Exception $e){
+            \DB::rollBack();
+            return $this->error('提交失败',$e->getMessage());
+        }
+    }
+
+}

+ 1 - 1
server/app/Http/Controllers/V1/UserController.php

xqd
@@ -83,7 +83,7 @@ class UserController extends Controller
             $info->save();
         }
 
-        $user = User::with(['info'])->where('id', $user->id)->first();
+        $user = User::with(['info','parent'])->where('id', $user->id)->first();
 
         return $this->success($user);
     }

+ 11 - 0
server/app/Models/User.php

xqd xqd xqd
@@ -73,6 +73,7 @@ use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
  * @property string|null $become_share_at 成为分销商时间
  * @method static \Illuminate\Database\Eloquent\Builder|User whereBecomeShareAt($value)
  * @property-read User|null $child
+ * @property-read \App\Models\UserShare|null $childOrder
  */
 class User extends Authenticatable implements JWTSubject
 {
@@ -101,6 +102,11 @@ class User extends Authenticatable implements JWTSubject
         'deleted_at',
     ];
 
+    protected $casts = [
+        'total_income' => 'decimal:2',
+        'income' => 'decimal:2'
+    ];
+
     public function getJWTIdentifier()
     {
         return $this->getKey(); // TODO: Implement getJWTIdentifier() method.
@@ -140,6 +146,11 @@ class User extends Authenticatable implements JWTSubject
         return $this->belongsTo(User::class,'id', 'parent_id');
     }
 
+    public function childOrder()
+    {
+        return $this->hasMany(UserShare::class,'child_id', 'id');
+    }
+
     public function info()
     {
         return $this->belongsTo(UserInfo::class,'id','user_id');

+ 54 - 1
server/app/Models/UserShare.php

xqd
@@ -6,9 +6,62 @@ use Dcat\Admin\Traits\HasDateTimeFormatter;
 
 use Illuminate\Database\Eloquent\Model;
 
+/**
+ * App\Models\UserShare
+ *
+ * @property int $id
+ * @property int $user_id 用户
+ * @property int $child_id 二级ID
+ * @property int $order_type 1-充值VIP 2-充值金币
+ * @property string $order_id 订单号
+ * @property string $income 收入
+ * @property \Illuminate\Support\Carbon|null $created_at
+ * @property \Illuminate\Support\Carbon|null $updated_at
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare newModelQuery()
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare newQuery()
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare query()
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereChildId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereCreatedAt($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereIncome($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereOrderId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereOrderType($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereUpdatedAt($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|UserShare whereUserId($value)
+ * @mixin \Eloquent
+ * @property-read \App\Models\UserRechargeRecord|null $rechargeOrder
+ * @property-read \App\Models\UserVipRecord|null $vipOrder
+ * @property-write mixed $order
+ * @property-write mixed $type_name
+ */
 class UserShare extends Model
 {
 	use HasDateTimeFormatter;
     protected $table = 'user_share';
-    
+
+    protected $hidden = [
+        'updated_at'
+    ];
+
+    public function vipOrder()
+    {
+        return $this->belongsTo(UserVipRecord::class,'order_id','pay_id');
+    }
+
+    public function rechargeOrder()
+    {
+        return $this->belongsTo(UserRechargeRecord::class,'order_id','pay_id');
+    }
+
+    public function setTypeNameAttribute($type)
+    {
+        $config = config('global.income_type');
+        $this->attributes['type_name'] = $config[$type]??'未知';
+    }
+
+    public function setOrderAttribute(UserShare $share)
+    {
+        $order = $share->order_type == 1 ? $share->vipOrder : $share->rechargeOrder;
+        $this->attributes['order'] = $order;
+    }
 }

+ 14 - 0
server/app/Models/UserWithdraw.php

xqd xqd
@@ -42,6 +42,8 @@ use Illuminate\Database\Eloquent\Model;
  * @method static \Illuminate\Database\Eloquent\Builder|UserWithdraw whereWithdrawAt($value)
  * @mixin \Eloquent
  * @property-read \App\Models\User|null $user
+ * @property-write mixed $status_name
+ * @property-write mixed $type_name
  */
 class UserWithdraw extends Model
 {
@@ -53,4 +55,16 @@ class UserWithdraw extends Model
         return $this->belongsTo(User::class,'user_id');
     }
 
+    public function setStatusNameAttribute($status)
+    {
+        $config = config('global.withdraw_status');
+        $this->attributes['status_name'] = $config[$status]??'未知';
+    }
+
+    public function setTypeNameAttribute($status)
+    {
+        $config = config('global.withdraw_type');
+        $this->attributes['type_name'] = $config[$status]??'未知';
+    }
+
 }

+ 5 - 1
server/config/global.php

xqd
@@ -56,6 +56,10 @@ return [
     ],
     // 提现类型
     'withdraw_type' => [
-        1 => '微信',2 => '支付宝',3 => '银行转行',
+        1 => '微信线下打款', 2 => '支付宝线下打款',3 => '银联线下打款',
+    ],
+    // 分销收入类型
+    'income_type' => [
+        1 => '会员充值', 2 => '充值金币',
     ],
 ];

+ 1 - 1
server/resources/lang/zh/user-withdraw.php

xqd
@@ -10,7 +10,7 @@ return [
         'user_id' => '用户',
         'name' => '姓名',
         'phone_num' => '手机号',
-        'type' => '类型 1-微信',
+        'type' => '类型',
         'account' => '提现账号',
         'price' => '用户申请金额',
         'discount' => '手续费',

+ 19 - 12
server/routes/api.php

xqd
@@ -152,19 +152,26 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\V1'], function ($api)
             $api->get('rechargeCombo', 'SettingController@rechargeCombo'); // 充值
         });
 
-        // 短剧
-        $api->group(['prefix' => 'episode'],function ($api){
+        // 相关设置
+        $api->group(['prefix' => 'setting'],function ($api){
+            /* @var Dingo\Api\Routing\Router $api*/
+            $api->get('tabBar', 'SettingController@tabBar'); // 底部导航
+            $api->get('navBar', 'SettingController@navBar'); // 首页顶部分类
+            $api->get('banner', 'SettingController@banner'); // banner
+            $api->get('homeColumn', 'SettingController@homeColumn'); // homeColumn
+            $api->get('rechargeCombo', 'SettingController@rechargeCombo'); // 充值
+        });
+
+        // 分销
+        $api->group(['namespace' => 'Share', 'prefix' => 'share'],function ($api){
             /* @var Dingo\Api\Routing\Router $api*/
-            $api->get('recommend', 'EpisodeController@recommend'); // 推荐
-            $api->get('today/recommend', 'EpisodeController@todayRecommend'); // 今日推荐
-            $api->get('news', 'EpisodeController@news'); // 最新
-            $api->get('rank', 'EpisodeController@rank'); // 排行
-            $api->get('trace', 'EpisodeController@trace'); // 追剧
-            $api->get('list', 'EpisodeController@list'); // 列表
-            $api->get('search', 'EpisodeController@search'); // 搜索
-            $api->get('vip/free', 'EpisodeController@vipFree'); // banner
-            $api->get('{id}/detail', 'EpisodeController@detail'); // 详情
-            $api->get('/list/{listId}/buyNum', 'EpisodeController@listBuyNum'); // 详情
+            $api->get('order/lists', 'OrderController@lists'); // 分销订单
+            $api->get('team/lists', 'TeamController@lists'); // 分销订单
+            $api->get('withdraw/lists', 'WithdrawController@lists'); // 分销订单
+            $api->post('withdraw/create', 'WithdrawController@create'); // 分销订单
+            $api->get('income', 'ShareController@income'); // 分销明细
+            $api->get('tips', 'ShareController@tips'); // 用户需知
+            $api->get('setting', 'ShareController@setting'); // 设置
         });
 
     });