Bladeren bron

Merge branch 'master' of http://39.101.143.165:8090/hxl13994548489/LocalLivingServicesUniapp

caiyuqin 5 maanden geleden
bovenliggende
commit
608bf42d99
36 gewijzigde bestanden met toevoegingen van 3146 en 13 verwijderingen
  1. 45 0
      api/account.js
  2. 70 0
      common/router/modules/routes.js
  3. 14 0
      common/util/util.js
  4. 3 3
      components/dengrq-datetime-picker/dateSelector/index.vue
  5. 19 1
      components/list-scroll-view/index.vue
  6. 1 1
      components/mescroll-uni/components/mescroll-up.css
  7. 2 2
      components/mescroll-uni/mescroll-uni-option.js
  8. 4 1
      components/mescroll-uni/mescroll-uni.vue
  9. 0 2
      components/yzhua006-update/app-update.vue
  10. 71 2
      pages.json
  11. 279 0
      pages/finance/accountRecord.vue
  12. 316 0
      pages/finance/balance.vue
  13. 109 0
      pages/finance/components/account-list.vue
  14. 72 0
      pages/finance/components/group-meal-list.vue
  15. 80 0
      pages/finance/components/order-list.vue
  16. 134 0
      pages/finance/dictionary.js
  17. 280 0
      pages/finance/groupMealDetails.vue
  18. 416 0
      pages/finance/index.vue
  19. 258 0
      pages/finance/orderDetails.vue
  20. 219 0
      pages/finance/settlementDetails.vue
  21. 114 0
      pages/finance/submitted.vue
  22. 429 0
      pages/finance/withdrawal.vue
  23. 210 0
      pages/finance/withdrawalDetails.vue
  24. 1 1
      pages/index/index.vue
  25. BIN
      static/finance/account/auditing.png
  26. BIN
      static/finance/account/cash.png
  27. BIN
      static/finance/account/completed.png
  28. BIN
      static/finance/account/icon-list.png
  29. BIN
      static/finance/account/pending.png
  30. BIN
      static/finance/account/settlement.png
  31. BIN
      static/finance/status/fail.png
  32. BIN
      static/finance/status/icon-remind.png
  33. BIN
      static/finance/status/processing.png
  34. BIN
      static/finance/status/success.png
  35. BIN
      static/tabbar/finance_select_tab.png
  36. BIN
      static/tabbar/finance_tab.png

+ 45 - 0
api/account.js

@@ -0,0 +1,45 @@
+import { http } from '@/common/service/service.js' 
+
+const apiService = {
+  // 获取当前账户余额
+	getAccountInfo() {
+		return http.get('/merchant/account/index');
+	},
+
+  // 获取财务订单统计
+	getFinanceStats(params) {
+		return http.get('/merchant/account/orderStats',{params});
+	},
+
+  // 获取账户明细
+	getAccountList(params) {
+		return http.get('/merchant/account/flowList',{params});
+	},
+
+  // 初始化提现数据
+	initWithdrawalData() {
+		return http.get('/merchant/withdraw/initApply');
+	},
+
+  // 申请提现
+	applyWithdrawal(params) {
+		return http.post('/merchant/withdraw/apply',params);
+	},
+
+  // 提现详情
+	getWithdrawalDetails(id) {
+		return http.get(`/merchant/withdraw/detail?withdrawNo=${id}`);
+	},
+
+  // 结算详情
+	settlementDetail(id) {
+		return http.get(`/merchant/account/settlementDetail?settlementId=${id}`);
+	},
+
+  // 结算订单详情
+	orderClearDetail(id) {
+		return http.get(`/merchant/account/orderClearDetail?orderId=${id}`);
+	},
+};
+
+export default apiService;

+ 70 - 0
common/router/modules/routes.js

@@ -706,5 +706,75 @@ const routes = [{
 		name: 'details',
 		meta: {},
 	},
+  {
+		path: '/pages/finance/index',
+		name: 'Finance',
+		meta: {
+			title: '财务',
+		},
+	},
+  {
+		path: '/pages/finance/balance',
+		name: 'Balance',
+		meta: {
+			title: '账户余额',
+		},
+	},
+  {
+		path: '/pages/finance/withdrawal',
+		name: 'Withdrawal',
+		meta: {
+			title: '提现',
+		},
+	},
+  {
+		path: '/pages/finance/submitted',
+		name: 'Submitted',
+		meta: {
+			title: '已提交',
+		},
+	},
+  {
+		path: '/pages/finance/accountRecord',
+		name: 'AccountRecord',
+		meta: {
+			title: '账户明细',
+		},
+	},
+  {
+		path: '/pages/finance/accountRecord',
+		name: 'AccountRecord',
+		meta: {
+			title: '账户明细',
+		},
+	},
+  {
+		path: '/pages/finance/settlementDetails',
+		name: 'SettlementDetails',
+		meta: {
+			title: '结算详情',
+		},
+	},
+  {
+		path: '/pages/finance/groupMealDetails',
+		name: 'GroupMealDetails',
+		meta: {
+			title: '团餐结算详情',
+		},
+	},
+  {
+		path: '/pages/finance/orderDetails',
+		name: 'OrderDetails',
+		meta: {
+			title: '订单详情',
+		},
+	},
+  {
+		path: '/pages/finance/withdrawalDetails',
+		name: 'WithdrawalDetails',
+		meta: {
+			title: '提现详情',
+		},
+	},
 ]
 export default routes

+ 14 - 0
common/util/util.js

@@ -25,4 +25,18 @@ export const getUrlParams = (url) => {
         });
     }
     return result;
+};
+
+// 格式化金额,添加千位分隔符
+export const formatAmount = (amount, type) => {
+  if (type === 'quantity') {
+    if (amount === null || amount === undefined) return '0';
+    return String(amount).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+  } else {
+    if (amount === null || amount === undefined) return '0.00';
+    return parseFloat(amount)
+      .toFixed(2)
+      .replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+  }
+  
 };

+ 3 - 3
components/dengrq-datetime-picker/dateSelector/index.vue

@@ -17,12 +17,12 @@
       <view class="select-date-wrapper">
         <view class="select-date" :class="{ active: activeDate == 'startDate' }" @tap="onTapStartDate">
           <view class="select-date-value" v-if="startDate">{{ startDate }}</view>
-          <view class="select-date-placeholder" v-else>请选择时间</view>
+          <view class="select-date-placeholder" v-else>开始时间</view>
         </view>
-        <view style="margin: 0 16px">~</view>
+        <view style="margin: 0 16px"></view>
         <view class="select-date" :class="{ active: activeDate == 'endDate' }" @tap="onTapEndDate">
           <view class="select-date-value" v-if="endDate">{{ endDate }}</view>
-          <view class="select-date-placeholder" v-else>请选择时间</view>
+          <view class="select-date-placeholder" v-else>结束时间</view>
         </view>
       </view>
 

+ 19 - 1
components/list-scroll-view/index.vue

@@ -11,6 +11,10 @@
 			@scroll="onScroll">
 			<view class="lsv-list">
 				<slot name="list" :data="dataList" :is-scrolling="isScrolling"></slot>
+				<!-- 始终显示的底部提示 -->
+				<view class="lsv-footer">
+					{{ hasMoreData ? '上拉加载更多' : '-- 暂无更多数据 --' }}
+				</view>
 			</view>
 		</mescroll-uni>
 	</view>
@@ -58,6 +62,8 @@ export default {
 		return {
 			params: {},
 			dataList: [],
+			// 是否有更多数据
+			hasMoreData: true,
 			// 下拉刷新的配置
 			downOption: {
 				
@@ -73,6 +79,7 @@ export default {
 			let obj = {
 				// noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于5条才显示无更多数据;
 				onScroll: true,
+				textLoading: '上拉加载更多...',
 				textNoMore: '-- 暂无更多数据 --', 
 				page: {
 					size: this.pageSize // 每页数据的数量,默认10
@@ -103,6 +110,7 @@ export default {
 		},
 		// 下拉刷新
 		downCallback() {
+			this.hasMoreData = true; // 下拉刷新时重置为有更多数据
 			this.mescroll.resetUpScroll();
 		},
 		// 上拉加载
@@ -143,6 +151,8 @@ export default {
 					this.$emit('afterFetch', result);
 					// 数据
 					this.dataList = this.dataList.concat(records);
+					// 判断是否还有更多数据
+					this.hasMoreData = this.dataList.length < (result.total || result[this.keyName].total);
 					this.mescroll.endBySize(records.length, result.total || result[this.keyName].total);
 				} else {
 					this.$tip.error('数据请求发生错误');
@@ -154,6 +164,7 @@ export default {
 		},
 		reloadList(p) {
 			this.params = p;
+			this.hasMoreData = true; // 重新加载时重置为有更多数据
 			this.mescroll.resetUpScroll();
 		}
 	}
@@ -166,6 +177,13 @@ export default {
 	position: relative;
 	.lsv-list {
 		min-height: 100%;
+		.lsv-footer {
+			text-align: center;
+			padding: 20rpx 0;
+			font-size: 26rpx;
+			color: #999;
+			border-top: 1rpx solid #f7f8fc;
+		}
 	}
 }
-</style>
+</style>

+ 1 - 1
components/mescroll-uni/components/mescroll-up.css

@@ -1,7 +1,7 @@
 /* 上拉加载区域 */
 .mescroll-upwarp {
 	min-height: 60rpx;
-	padding: 30rpx 0;
+	padding: 10rpx 0;
 	text-align: center;
 	clear: both;
 }

+ 2 - 2
components/mescroll-uni/mescroll-uni-option.js

@@ -6,14 +6,14 @@ const GlobalOption = {
 		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
 		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
 		textLoading: '加载中 ...', // 加载中的提示文本
-		offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+		offset: 160, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
 		native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
 	},
 	up: {
 		// 其他up的配置参数也可以写,这里只展示了常用的配置:
 		textLoading: '加载中 ...', // 加载中的提示文本
 		textNoMore: '-- END --', // 没有更多数据的提示文本
-		offset: 80, // 距底部多远时,触发upCallback
+		offset: 50, // 距底部多远时,触发upCallback
 		isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
 		toTop: {
 			// 回到顶部按钮,需配置src才显示

+ 4 - 1
components/mescroll-uni/mescroll-uni.vue

@@ -19,7 +19,10 @@
 
 				<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
 				<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
-				<view v-if="mescroll.optUp.use && !isDownLoading" class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+				<view v-if="mescroll.optUp.use && !isDownLoading && !isShowEmpty" class="mescroll-upwarp" :style="{'background-color':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+          <view v-show="upLoadType===0">
+						<view class="upwarp-tip">上拉加载更多...</view>
+					</view>
 					<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
 					<view v-show="upLoadType===1">
 						<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>

+ 0 - 2
components/yzhua006-update/app-update.vue

@@ -89,8 +89,6 @@ export default {
   methods: {
     // 检查更新
     update() {
-
-      console.log('-----------')
       // alert(plus.runtime.appid)
       // 获取手机系统信息
       uni.getSystemInfo({

+ 71 - 2
pages.json

@@ -74,7 +74,69 @@
 			"path": "pages/order/record",
 			"style": {}
 		},
-
+		{
+			"path": "pages/finance/index",
+			"style": {
+				"navigationBarTitleText": "财务",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/balance",
+			"style": {
+				"navigationBarTitleText": "账户余额",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/accountRecord",
+			"style": {
+				"navigationBarTitleText": "账户明细",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/withdrawal",
+			"style": {
+				"navigationBarTitleText": "提现",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/submitted",
+			"style": {
+				"navigationBarTitleText": "已提交",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/settlementDetails",
+			"style": {
+				"navigationBarTitleText": "结算详情",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/groupMealDetails",
+			"style": {
+				"navigationBarTitleText": "团餐结算详情",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/orderDetails",
+			"style": {
+				"navigationBarTitleText": "订单详情",
+				"navigationStyle": "custom"
+			}
+		},
+    {
+			"path": "pages/finance/withdrawalDetails",
+			"style": {
+				"navigationBarTitleText": "提现详情",
+				"navigationStyle": "custom"
+			}
+		},
 		{
 			"path": "pages/index/full",
 			"style": {}
@@ -496,7 +558,8 @@
 			"transparentTitle": "always",
 			"allowsBounceVertical": "NO"
 		},
-		"navigationBarBackgroundColor": "#0081ff",
+		"navigationBarBackgroundColor": "#ffffff",
+    "navigationBarTitleColor": "#333333",
 		"navigationBarTitleText": "JEECG BOOT",
 		"navigationStyle": "custom",
 		"navigationBarTextStyle": "black"
@@ -522,6 +585,12 @@
 				"pagePath": "pages/order/index",
 				"iconPath": "static/tabbar/order_tab.png",
 				"selectedIconPath": "static/tabbar/order_select_tab.png"
+			},
+      {
+				"text": "财务",
+				"pagePath": "pages/finance/index",
+				"iconPath": "static/tabbar/finance_tab.png",
+				"selectedIconPath": "static/tabbar/finance_select_tab.png"
 			}
 			
 			// {

+ 279 - 0
pages/finance/accountRecord.vue

@@ -0,0 +1,279 @@
+<template>
+  <view class="account-record">
+    <view class="fix">
+      <view class="top"></view>
+      <view class="head">
+        <span class="cuIcon-back" @click="back"></span>
+        <view class="case"> {{ navTitle }} </view>
+      </view>
+
+      <!-- 当type为all或settlement时展示Tab -->
+      <view v-if="showTab" class="tab-container">
+        <view
+          class="tab-item"
+          v-for="(tab, index) in settlementTabs"
+          :key="index"
+          :class="{ active: currentTab === index }"
+          @click="switchTab(index)"
+        >
+          {{ tab }}
+        </view>
+      </view>
+    </view>
+
+    <!-- 列表区域 -->
+    <mescroll-uni
+      class="list-box"
+      ref="mescrollRef"
+      :fixed="false"
+      @up="getList"
+      @down="downCallback"
+      @init="mescrollInit"
+      :use="false"
+    >
+      <AccountList :list="accountData"></AccountList>
+    </mescroll-uni>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+import AccountList from './components/account-list.vue';
+
+export default {
+  name: 'AccountRecord',
+  components: {
+    AccountList,
+  },
+  computed: {
+    navTitle() {
+      switch (this.type) {
+        case 'all':
+          return '账户明细';
+        case 'pending':
+          return '待结算明细';
+        case 'auditing':
+          return '提现审核中';
+        case 'completed':
+          return '已提现明细';
+        default:
+          return '账户明细';
+      }
+    },
+  },
+  data() {
+    return {
+      settlementTabs: ['全部', '结算', '提现'],
+      params: {},
+      currentTab: 0,
+      type: '',
+      showTab: false,
+      accountData: [],
+    };
+  },
+  onLoad(options) {
+    if (options.type) {
+      this.type = options.type;
+
+      if (this.type === 'all' || this.type === 'settlement') {
+        this.showTab = true;
+        this.currentTab = this.type === 'all' ? 0 : 1;
+      } else {
+        this.showTab = false;
+      }
+    }
+    this.mescroll && this.mescroll.triggerUpScroll();
+  },
+  onShow() {
+    if (this.accountData.length === 0) {
+      this.mescroll && this.mescroll.triggerUpScroll();
+    }
+  },
+  methods: {
+    mescrollInit(mescroll) {
+      this.mescroll = mescroll;
+    },
+    // 下拉刷新
+    downCallback() {
+      this.mescroll.resetUpScroll();
+      this.accountData = [];
+    },
+    // 切换Tab
+    switchTab(index) {
+      this.currentTab = index;
+      this.params.mainType = index === 0 ? '' : index === 1 ? 'SETTLE' : 'WITHDRAW';
+      this.getList({ num: 1, size: 10, ...this.params });
+    },
+    // 获取列表数据
+    getList(page) {
+      let params = this.buildParams(page);
+      api
+        .getAccountList(params)
+        .then((res) => {
+          if (res.data.code === 200) {
+            const records = res.data.result.records;
+            const total = res.data.result.total;
+
+            if (page.num === 1) {
+              this.accountData = records;
+            } else {
+              this.accountData = this.accountData.concat(records);
+            }
+            this.mescroll.endSuccess(records.length, total);
+            if (this.accountData.length < 5) {
+              this.$refs.mescrollRef.upLoadType = 'NO_DATA';
+            }
+          } else {
+            this.accountData = [];
+            this.mescroll.endErr();
+          }
+        })
+        .catch(() => {
+          this.mescroll.endErr();
+        });
+    },
+    // 请求参数
+    buildParams(page) {
+      let params = {
+        pageSize: page.size,
+        pageNo: page.num,
+      };
+
+      if (this.type === 'all' || this.type === 'settlement') {
+        switch (this.currentTab) {
+          case 0: // 全部
+            params.mainType = '';
+            break;
+          case 1: // 结算
+            params.mainType = 'SETTLE';
+            break;
+          case 2: // 提现
+            params.mainType = 'WITHDRAW';
+            break;
+        }
+      } else if (this.type === 'pending') {
+        params.mainType = 'SETTLE';
+        params.subType = 'PENDING';
+      } else if (this.type === 'auditing') {
+        params.mainType = 'WITHDRAW';
+        params.subType = 'PENDING';
+      } else if (this.type === 'completed') {
+        params.mainType = 'WITHDRAW';
+        params.subType = 'DONE';
+      }
+
+      return params;
+    },
+    resetList() {
+      // 重置页码
+      if (this.mescroll) {
+        this.mescroll.resetUpScroll();
+      }
+      this.accountData = [];
+    },
+    back() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.account-record {
+  width: 100vw;
+  height: 100vh;
+  position: fixed;
+  background: #f7f8fc;
+
+  .fix {
+    width: 100%;
+    height: auto;
+    background: #ffffff;
+    position: sticky;
+    top: 0px;
+
+    /*#ifdef APP-PLUS*/
+    .top {
+      width: 100%;
+      height: var(--status-bar-height);
+      background: #fff;
+    }
+
+    /*#endif*/
+
+    .head {
+      width: 100%;
+      height: 112rpx;
+      padding: 20rpx;
+      display: flex;
+      align-items: center;
+      background: #fff;
+      position: relative;
+      border-bottom: 1rpx solid #eeeeee;
+
+      .cuIcon-back {
+        font-size: 40rpx;
+        margin-right: 40rpx;
+      }
+
+      .case {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        font-weight: 500;
+        font-size: 38rpx;
+        color: #333333;
+      }
+    }
+  }
+
+  .tab-container {
+    display: flex;
+    width: 100%;
+    height: 80rpx;
+    line-height: 80rpx;
+    background: #fff;
+
+    .tab-item {
+      flex: 1;
+      text-align: center;
+      font-weight: 400;
+      font-size: 29rpx;
+      color: #333333;
+      position: relative;
+
+      &.active {
+        font-weight: 500;
+        font-size: 31rpx;
+        color: #449aff;
+
+        &::after {
+          content: '';
+          position: absolute;
+          bottom: 5rpx;
+          left: 50%;
+          transform: translateX(-50%);
+          width: 50rpx;
+          height: 6rpx;
+          background: #449aff;
+          border-radius: 7rpx;
+        }
+      }
+    }
+  }
+
+  .list-box {
+    height: 80vh;
+    flex: 1;
+    overflow-y: auto;
+    padding: 10rpx 31rpx;
+    font-size: 28rpx;
+    color: #333;
+    margin: 17rpx 31rpx;
+    background: #fff;
+    border-radius: 10rpx;
+  }
+}
+</style>

+ 316 - 0
pages/finance/balance.vue

@@ -0,0 +1,316 @@
+<template>
+  <view class="container">
+    <view class="top"></view>
+    <view class="head">
+      <span class="cuIcon-back" @click="back"></span>
+      <view class="case"> 账户余额 </view>
+    </view>
+
+    <view class="main-box">
+      <view class="one-box">
+        <view>
+          <view class="title">账户余额(元)</view>
+          <view class="money">{{ formatAmount(balance) }}</view>
+        </view>
+        <view v-if="1">
+          <view class="btn-cash" @click="toPage('withdrawal')">
+            <image src="/static/finance/account/cash.png" mode="aspectFit" class="btn-img"></image>
+            <view>提现</view>
+          </view>
+        </view>
+      </view>
+      <view class="two-box">
+        <u-grid :col="4" :border="false">
+          <u-grid-item
+            v-for="(item, k) in accountMenus"
+            :key="k"
+            :customStyle="{
+              paddingTop: '21rpx',
+              paddingBottom: '21rpx',
+            }"
+            style="background: 'none'"
+            @click="toPage(item.type)"
+          >
+            <image class="icon" :src="item.icon" mode="aspectFit"></image>
+            <text class="desc">{{ item.title }}</text>
+          </u-grid-item>
+        </u-grid>
+      </view>
+
+      <view class="thr-box">
+        <u-sticky :offset-top="20" :customNavHeight="54">
+          <view class="section-title">
+            <view>
+              <text>账户明细</text>
+            </view>
+
+            <view class="action" @click="toPage('all')">
+              <text>全部</text>
+              <u-icon name="arrow-right" color="#999" size="26" top="1"></u-icon>
+            </view>
+          </view>
+        </u-sticky>
+        <!-- 账户列表 -->
+        <mescroll-uni
+          class="list-box"
+          ref="mescrollRef"
+          :fixed="false"
+          @up="getList"
+          @down="downCallback"
+          @init="mescrollInit"
+          :use="{ up: true, down: true }"
+        >
+          <AccountList :list="accountData"></AccountList>
+        </mescroll-uni>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+import { formatAmount } from '@/common/util/util';
+import { accountMenus } from './dictionary';
+import AccountList from './components/account-list.vue';
+
+export default {
+  name: 'Finance',
+  components: {
+    AccountList,
+  },
+  data() {
+    return {
+      accountMenus,
+      formatAmount,
+      accountData: [],
+      mescroll: null,
+      balance: 0,
+    };
+  },
+  onShow() {
+    if (!this.balance) {
+      this.getFinanceInfo();
+    }
+  },
+  onLoad(options) {
+    this.balance = options.balance;
+  },
+  methods: {
+    getFinanceInfo() {
+      api.getAccountInfo().then((res) => {
+        if (res.data.code === 200 && res.data.result) {
+          this.balance = res.data.result.availableAmount;
+        }
+      });
+    },
+    // 账户列表
+    getList(page) {
+      let params = {
+        pageNo: page.num,
+        pageSize: page.size,
+      };
+      api
+        .getAccountList(params)
+        .then((res) => {
+          if (res.data.code === 200) {
+            const records = res.data.result.records;
+            const total = res.data.result.total;
+            if (records == null && page.num === 1) {
+              this.accountData = [];
+            } else {
+              this.accountData = records ? this.accountData.concat(records) : this.accountData;
+            }
+            this.mescroll.endSuccess(records.length, total);
+            if (this.accountData.length < 5) {
+              this.$refs.mescrollRef.upLoadType = 'NO_DATA';
+            }
+          } else {
+            this.accountData = [];
+            this.mescroll.endErr();
+          }
+        })
+        .catch(() => {
+          this.mescroll.endErr();
+        });
+    },
+    // 跳转账户明细
+    toPage(type) {
+      let path = type === 'withdrawal' ? type : `accountRecord?type=${type}`;
+      uni.navigateTo({
+        url: `/pages/finance/${path}`,
+      });
+    },
+    mescrollInit(mescroll) {
+      this.mescroll = mescroll;
+    },
+    // 下拉刷新
+    downCallback() {
+      this.mescroll.resetUpScroll();
+      this.accountData = [];
+    },
+    back() {
+      uni.switchTab({
+        url: '/pages/finance/index',
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.container {
+  width: 100%;
+  height: 100vh;
+  background: #f7f8fc;
+  font-family: Source Han Sans SC;
+  position: fixed;
+  overflow: hidden;
+
+  /*#ifdef APP-PLUS*/
+  .top {
+    width: 100%;
+    height: var(--status-bar-height);
+    background: #fff;
+  }
+
+  /*#endif*/
+
+  .head {
+    width: 100%;
+    height: 112rpx;
+    padding: 20rpx;
+    display: flex;
+    align-items: center;
+    background: #fff;
+    position: fixed;
+    z-index: 999;
+    border-bottom: 1rpx solid #eeeeee;
+
+    .cuIcon-back {
+      font-size: 40rpx;
+      margin-right: 40rpx;
+    }
+
+    .case {
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      font-weight: 500;
+      font-size: 38rpx;
+      color: #333333;
+    }
+  }
+
+  .main-box {
+    border-top: 1rpx solid #eeeeee;
+    padding-top: 112rpx;
+
+    .one-box {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin: 22rpx 31rpx 0;
+      padding: 21rpx 19rpx 19rpx 31rpx;
+      background: linear-gradient(286deg, #34bbff 0%, #4496fb 100%);
+      box-shadow: 0rpx 4rpx 10rpx 0rpx #dae3f4;
+      border-radius: 21rpx 21rpx 0rpx 0rpx;
+
+      .title {
+        font-family: Source Han Sans CN;
+        font-weight: 400;
+        font-size: 25rpx;
+        color: #ffffff;
+      }
+      .money {
+        font-family: DIN Alternate;
+        font-weight: bold;
+        font-size: 63rpx;
+        color: #ffffff;
+      }
+      .item {
+        font-weight: 400;
+        font-size: 26rpx;
+        color: #666666;
+      }
+      .btn-cash {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 144rpx;
+        height: 63rpx;
+        background: #ffffff;
+        border-radius: 8rpx 8rpx 8rpx 8rpx;
+        font-family: Source Han Sans SC;
+        font-weight: 500;
+        font-size: 29rpx;
+        color: #38b2fe;
+
+        .btn-img {
+          width: 33rpx;
+          height: 33rpx;
+          margin-right: 10rpx;
+        }
+      }
+    }
+    .two-box {
+      height: 151rpx;
+      background: linear-gradient(180deg, #c3ebff 0%, #f7f8fc 100%);
+      box-shadow: inset 0rpx 2rpx 0rpx 0rpx rgba(255, 255, 255, 0.4);
+      border-radius: 21rpx 21rpx 0rpx 0rpx;
+
+      .icon {
+        width: 62rpx;
+        height: 62rpx;
+      }
+      .desc {
+        font-weight: 400;
+        font-size: 25rpx;
+        color: #7a7f89;
+        margin-top: 10rpx;
+      }
+    }
+
+    .thr-box {
+      margin: 10rpx 31rpx 40rpx;
+      padding: 0 31rpx 31rpx;
+      background: #ffffff;
+      border-radius: 10rpx 10rpx 10rpx 10rpx;
+      max-height: 65vh;
+      overflow-y: auto;
+      display: flex;
+      flex-direction: column;
+
+      .section-title {
+        width: 100%;
+        height: 80rpx;
+        font-weight: 500;
+        font-size: 31rpx;
+        color: #333333;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        background: #fff;
+        border-bottom: 1rpx solid #eeeeee;
+      }
+
+      .list-box {
+        flex: 1;
+        overflow-y: auto;
+      }
+
+      .action {
+        font-weight: 400;
+        font-size: 27rpx;
+        color: #666666;
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
+}
+::v-deep {
+  .u-grid-item {
+    background: none;
+  }
+}
+</style>

+ 109 - 0
pages/finance/components/account-list.vue

@@ -0,0 +1,109 @@
+<template>
+  <view class="list">
+    <view class="list_item" v-for="(item, index) in list" :key="index" @click="goDetails(item)">
+      <view class="left" v-if="item.jumpType !== 'PENDING_SETTLE'">
+        <image src="/static/finance/account/icon-list.png" mode="aspectFit"></image>
+      </view>
+      <view class="center">
+        <view class="name">{{ item.title }}</view>
+        <view class="value">{{ item.occurTime }}</view>
+      </view>
+      <view class="right">
+        <view class="money">{{ item.amountText }}</view>
+        <view class="value" v-if="item.jumpType !== 'PENDING_SETTLE'">余额{{ item.balanceAfter || 0 }}</view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  props: {
+    list: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  methods: {
+    goDetails(item) {
+      let pathName = '';
+      switch (item.jumpType) {
+        case 'SETTLE_NORMAL':
+          pathName = 'settlementDetails';
+          break;
+        case 'PENDING_SETTLE':
+          pathName = 'orderDetails';
+          break;
+        case 'WITHDRAW':
+          pathName = 'withdrawalDetails';
+          break;
+        case 'SETTLE_GROUP_MEAL':
+          pathName = 'groupMealDetails';
+          break;
+      }
+      uni.navigateTo({
+        url: `/pages/finance/${pathName}?id=${item.bizId}`,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.list {
+  .list_item {
+    width: 100%;
+    padding: 22rpx 0;
+    overflow: auto;
+    display: flex;
+    align-items: center;
+    border-bottom: 1rpx solid #eeeeee;
+    font-weight: 400;
+
+    &:last-child {
+      border-bottom: none;
+    }
+
+    .left {
+      width: 68rpx;
+      height: 68rpx;
+      margin-right: 16rpx;
+
+      image {
+        width: 68rpx;
+        height: 68rpx;
+      }
+    }
+
+    .center {
+      flex: 1;
+      margin-right: 16rpx;
+
+      .name {
+        font-size: 29rpx;
+        color: #333333;
+        margin-bottom: 5rpx;
+      }
+    }
+
+    .right {
+      width: auto;
+      text-align: right;
+      display: flex;
+      flex-direction: column;
+
+      .money {
+        font-weight: 500;
+        font-size: 31rpx;
+        color: #333333;
+        margin-bottom: 5rpx;
+      }
+    }
+
+    .value {
+      font-size: 21rpx;
+      color: #999999;
+    }
+  }
+}
+</style>

+ 72 - 0
pages/finance/components/group-meal-list.vue

@@ -0,0 +1,72 @@
+<template>
+  <uni-table class="table" border :empty-text="'暂无数据'">
+    <uni-tr>
+      <uni-th align="center">商品名称/数量</uni-th>
+      <uni-th align="center">商品总价</uni-th>
+    </uni-tr>
+    <uni-tr v-for="(item, index) in list" :key="index">
+      <uni-td>
+        <view class="info">
+          <text class="name">{{ item.productName }}</text>
+          <text>x{{ item.quantity }}</text>
+        </view>
+      </uni-td>
+      <uni-td v-if="item.orderPrice">¥{{ item.orderPrice.toFixed(2) }}</uni-td>
+    </uni-tr>
+  </uni-table>
+</template>
+
+<script>
+export default {
+  props: {
+    list: {
+      type: Array,
+      default: () => [],
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.table {
+  border-radius: 8rpx;
+  overflow: hidden;
+  font-family: PingFang SC;
+  font-weight: 400;
+  border-color: #dbebff;
+
+  .info {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 28rpx;
+
+    .name {
+      max-width: 367rpx;
+      margin-right: 10rpx;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      flex: 1;
+    }
+  }
+}
+
+::v-deep {
+  .uni-table-th {
+    height: 67rpx !important;
+    background: #f5faff;
+    font-size: 29rpx;
+    color: #333333;
+  }
+  .uni-table-td {
+    height: 54rpx !important;
+    text-align: center !important;
+    font-size: 27rpx !important;
+    color: #666666 !important;
+  }
+  .table--border {
+    border-color: #dbebff !important;
+  }
+}
+</style>

+ 80 - 0
pages/finance/components/order-list.vue

@@ -0,0 +1,80 @@
+<template>
+  <view class="list">
+    <view class="list_item" v-for="(item, index) in list" :key="index" @click="goDetails(item)">
+      <view class="left">
+        <view class="name">订单号:{{ item.orderId }}</view>
+        <view class="value">{{ item.buyTime }}</view>
+      </view>
+      <view class="right">
+        <view>+{{ item.orderPrice }}</view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  props: {
+    list: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  methods: {
+    goDetails(item) {
+      uni.navigateTo({
+        url: `/pages/finance/orderDetails?id=${item.orderId}`,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.list {
+  border: 1rpx solid #f7f8fc;
+  .list_item {
+    width: 100%;
+    padding: 21rpx;
+    overflow: auto;
+    display: flex;
+    align-items: center;
+    border-bottom: 1rpx solid #EEEEEE;
+    font-weight: 400;
+
+    &:last-child {
+      border-bottom: none;
+    }
+
+    .left {
+      flex: 1;
+      margin-right: 16rpx;
+
+      .name {
+        width: 463rpx;
+        font-size: 29rpx;
+        color: #333333;
+        margin-bottom: 5rpx;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+
+      .value {
+        font-size: 21rpx;
+        color: #999999;
+      }
+    }
+
+    .right {
+      width: auto;
+      text-align: right;
+      display: flex;
+      flex-direction: column;
+      font-weight: 500;
+      font-size: 31rpx;
+      color: #333333;
+    }
+  }
+}
+</style>

+ 134 - 0
pages/finance/dictionary.js

@@ -0,0 +1,134 @@
+export const accountMenus = [
+  {
+    type: 'settlement',
+    title: '结算记录',
+    icon: '/static/finance/account/settlement.png',
+    path: '/packageC/pages/mine/settlementRecord/index',
+  },
+  {
+    type: 'pending',
+    title: '待结算明细',
+    icon: '/static/finance/account/pending.png',
+    path: '/packageC/pages/mine/settlementRecord/index',
+  },
+  {
+    type: 'auditing',
+    title: '提现审核中',
+    icon: '/static/finance/account/auditing.png',
+    path: '/packageC/pages/mine/settlementRecord/index',
+  },
+  {
+    type: 'completed',
+    title: '已提现明细',
+    icon: '/static/finance/account/completed.png',
+    path: '/packageC/pages/mine/settlementRecord/index',
+  },
+];
+
+export const orderFields = [
+  {
+    title: '订单编号',
+    valueField: 'orderId',
+    isShowTip: false,
+  },
+  {
+    title: '商品名称',
+    valueField: 'productName',
+    isShowTip: false,
+  },
+  {
+    title: '下单时间',
+    valueField: 'buyTime',
+    isShowTip: false,
+  },
+  {
+    title: '核销时间',
+    valueField: 'writeOffTime',
+    isShowTip: false,
+  },
+  {
+    title: '订单金额',
+    valueField: 'orderPrice',
+    isShowTip: false,
+  },
+  {
+    title: '实付金额',
+    valueField: 'actualPayAmount',
+    isShowTip: false,
+  },
+  {
+    title: '应收金额',
+    valueField: 'payableToMerchant',
+    isShowTip: false,
+  },
+  {
+    title: '邀新分佣成本',
+    valueField: 'inviteNewUserCommissionMerchantCost',
+    rateField: 'inviteNewUserCommissionMerchantRate',
+    isShowTip: true,
+    key: 'inviteNew',
+  },
+  {
+    title: '优惠券成本',
+    valueField: 'couponMerchantCost',
+    rateField: 'couponMerchantRate',
+    isShowTip: true,
+    key: 'coupon',
+  },
+  {
+    title: '会员折扣成本',
+    valueField: 'memberDiscountMerchantCost',
+    rateField: 'memberDiscountMerchantRate',
+    isShowTip: true,
+    key: 'member',
+  },
+  {
+    title: '金豆抵扣成本',
+    valueField: 'jinbiMerchantCost',
+    rateField: 'jinbiMerchantRate',
+    isShowTip: true,
+    key: 'jinbi',
+  },
+  {
+    title: '推广分佣成本',
+    valueField: 'distributorCommissionMerchantCost',
+    rateField: 'distributorCommissionMerchantRate',
+    isShowTip: true,
+    key: 'distributor',
+  },
+]
+
+export const groupMealFields = [
+  {
+    title: '订单编号',
+    valueField: 'statementNumber',
+    isShowTip: false,
+  },
+  {
+    title: '下单时间',
+    valueField: 'createTime',
+    isShowTip: false,
+  },
+  {
+    title: '成团时间',
+    valueField: 'groupMealTime',
+    isShowTip: false,
+  },
+  {
+    title: '成团价',
+    valueField: 'groupMealPrice',
+    isShowTip: false,
+  },
+  {
+    title: '应收金额',
+    valueField: 'amountPayable',
+    isShowTip: false,
+  },
+  {
+    title: '拉新分佣成本',
+    valueField: 'newUserCommission',
+    rateField: 'newUserCommissionRate',
+    isShowTip: true,
+    key: 'newUser',
+  }
+]

+ 280 - 0
pages/finance/groupMealDetails.vue

@@ -0,0 +1,280 @@
+<template>
+  <view class="settle">
+    <view class="fix">
+      <view class="top"></view>
+      <view class="head">
+        <span class="cuIcon-back" @click="back"></span>
+        <view class="case"> 结算详情-团餐 </view>
+      </view>
+    </view>
+
+    <view class="settle-card">
+      <view class="settle-header">
+        <view class="amount">¥{{ settlementInfo.amountPayable }}</view>
+      </view>
+      <view class="settle-info">
+        <view v-for="(item, index) in groupMealFields" :key="index" class="info">
+          <view class="label">
+            {{ item.title }}
+            <image
+              v-if="item.isShowTip"
+              src="/static/finance/status/icon-remind.png"
+              mode="aspectFit"
+              style="width: 33rpx; height: 33rpx; margin-left: 8rpx"
+              @click.stop="toggleTooltip(item.key)"
+            ></image>
+            <view class="tooltip" v-show="showTooltip === item.key">
+              商户占比{{ settlementInfo[item.rateField] }}%
+            </view>
+          </view>
+          <view class="value">{{ settlementInfo[item.valueField] }}</view>
+        </view>
+        <view class="remark"> 注:应收金额=成团价*商家分佣占比-拉新分佣成本</view>
+      </view>
+      <!-- 订单列表 -->
+      <view class="settle-list">
+        <GroupMealList :list="orderList"></GroupMealList>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+import { groupMealFields } from './dictionary';
+import GroupMealList from './components/group-meal-list.vue';
+
+export default {
+  name: 'SettlementDetails',
+  components: {
+    GroupMealList,
+  },
+  data() {
+    return {
+      orderId: '',
+      settlementInfo: {},
+      orderList: [],
+      groupMealFields,
+      showTooltip: null,
+      tooltipTimer: null,
+    };
+  },
+  mounted() {
+    // 点击其他区域隐藏提示
+    document.addEventListener('click', this.handleClickOutside);
+  },
+  beforeUnmount() {
+    // 移除事件监听
+    document.removeEventListener('click', this.handleClickOutside);
+    // 清除定时器
+    if (this.tooltipTimer) {
+      clearTimeout(this.tooltipTimer);
+    }
+  },
+  onLoad(options) {
+    if (options.id) {
+      this.orderId = options.id;
+    }
+  },
+  onShow() {
+    this.getDetails(this.orderId);
+  },
+  methods: {
+    getDetails(id) {
+      api
+        .settlementDetail(id)
+        .then((res) => {
+          if (res.data.code === 200) {
+            this.settlementInfo = res.data.result || {};
+            this.orderList = res.data.result.orderList || [];
+          } else {
+            uni.showToast({
+              title: res.data.msg || '获取结算详情失败',
+              icon: 'none',
+            });
+          }
+        })
+        .catch(() => {
+          uni.showToast({
+            title: '获取结算详情失败',
+            icon: 'none',
+          });
+        });
+    },
+    // 处理点击事件,显示提示并设置10秒自动隐藏
+    toggleTooltip(key) {
+      // 清除之前的定时器
+      if (this.tooltipTimer) {
+        clearTimeout(this.tooltipTimer);
+      }
+      // 显示当前提示,隐藏其他提示
+      this.showTooltip = this.showTooltip === key ? null : key;
+
+      // 如果是显示状态,设置10秒后自动隐藏
+      if (this.showTooltip) {
+        this.tooltipTimer = setTimeout(() => {
+          this.showTooltip = null;
+        }, 10000); // 10秒自动隐藏
+      }
+    },
+    // 点击其他区域隐藏提示
+    handleClickOutside(event) {
+      // 检查点击目标是否在提示或图片上
+      const tooltipElements = document.querySelectorAll('.tooltip, image[src*="icon-remind.png"]');
+      let isClickOnTooltip = false;
+
+      tooltipElements.forEach((element) => {
+        if (element.contains(event.target)) {
+          isClickOnTooltip = true;
+        }
+      });
+
+      // 如果点击的不是提示或图片,隐藏所有提示
+      if (!isClickOnTooltip) {
+        this.showTooltip = null;
+        // 清除定时器
+        if (this.tooltipTimer) {
+          clearTimeout(this.tooltipTimer);
+        }
+      }
+    },
+    back() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.settle {
+  background: #f7f8fc;
+  min-height: 100vh;
+  font-family: Source Han Sans SC;
+  padding-bottom: 100rpx;
+  font-weight: 500;
+
+  .fix {
+    position: sticky;
+    top: 0;
+    /*#ifdef APP-PLUS*/
+    .top {
+      width: 100%;
+      height: var(--status-bar-height);
+      background: #fff;
+    }
+
+    /*#endif*/
+
+    .head {
+      width: 100%;
+      height: 112rpx;
+      padding: 20rpx;
+      display: flex;
+      align-items: center;
+      background: #fff;
+      position: relative;
+      border-bottom: 1rpx solid #eeeeee;
+
+      .cuIcon-back {
+        font-size: 40rpx;
+        margin-right: 40rpx;
+      }
+
+      .case {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        font-size: 38rpx;
+        color: #333333;
+      }
+    }
+  }
+
+  .settle-card {
+    background-color: #fff;
+    padding: 30rpx 31rpx 31rpx;
+
+    .settle-header {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+
+      .amount {
+        font-size: 63rpx;
+        color: #1f1f1f;
+        margin-bottom: 41rpx;
+      }
+    }
+
+    .settle-info {
+      background-color: #fff;
+      margin-bottom: 20rpx;
+
+      .info {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding-bottom: 21rpx;
+
+        &:last-child {
+          border-bottom: none;
+        }
+
+        .label {
+          display: flex;
+          align-items: center;
+          font-weight: 400;
+          font-size: 31rpx;
+          color: #666666;
+          position: relative;
+
+          .tooltip {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            width: 158rpx;
+            height: 42rpx;
+            background: rgba(0, 0, 0, 0.6);
+            border-radius: 4rpx 4rpx 4rpx 4rpx;
+            font-family: PingFang SC;
+            font-weight: 400;
+            font-size: 23rpx;
+            color: #ffffff;
+            margin-left: 10rpx;
+
+            &::after {
+              content: '';
+              position: absolute;
+              right: 158rpx;
+              bottom: 14rpx;
+              width: 0;
+              height: 0;
+              border-bottom: 10rpx solid transparent;
+              border-right: 10rpx solid rgba(0, 0, 0, 0.6);
+              border-top: 10rpx solid transparent;
+              border-left: 0;
+            }
+          }
+        }
+
+        .value {
+          font-size: 31rpx;
+          color: #333333;
+        }
+      }
+      .remark {
+        font-weight: 400;
+        font-size: 25rpx;
+        color: #666666;
+        margin-top: 10rpx;
+      }
+    }
+    .settle-list {
+      margin-top: 42rpx;
+    }
+  }
+}
+</style>

+ 416 - 0
pages/finance/index.vue

@@ -0,0 +1,416 @@
+<template>
+  <view class="container">
+    <view class="top"></view>
+    <view class="title">财务数据</view>
+
+    <view class="balance-card">
+      <!-- 账户余额 -->
+      <view class="balance-info">
+        <view @click="goPage">
+          <view class="flex">
+            <text class="balance-label">账户余额</text>
+            <u-icon name="arrow-right" class="ml-1" color="#fff" size="24"></u-icon>
+          </view>
+          <text class="balance-amount">{{ formatAmount(financeData.availableAmount) }}</text>
+        </view>
+        <view>
+          <button class="withdraw-btn" @click="goWithdrawal">提现</button>
+        </view>
+      </view>
+
+      <!-- 金额统计 -->
+      <view class="stats-row u-m-b-20">
+        <view class="stat-item">
+          <text class="stat-label">已结算金额 (元)</text>
+          <text class="stat-value">{{ formatAmount(financeData.totalSettledAmount) }}</text>
+        </view>
+        <view class="stat-item">
+          <text class="stat-label">待结算金额 (元)</text>
+          <text class="stat-value">{{ formatAmount(financeData.pendingSettledAmount) }}</text>
+        </view>
+      </view>
+      <view class="stats-row">
+        <view class="stat-item">
+          <text class="stat-label">已提现金额 (元)</text>
+          <text class="stat-value">{{ formatAmount(financeData.totalWithdrawnAmount) }}</text>
+        </view>
+        <view class="stat-item">
+          <text class="stat-label">提现中金额 (元)</text>
+          <text class="stat-value">{{ formatAmount(financeData.frozenAmount) }}</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- 业务类型 -->
+    <view class="business-tabs">
+      <view
+        v-for="(tab, index) in businessTabs"
+        :key="tab.name"
+        :class="index == currentTab ? 'tab-item active' : 'tab-item'"
+        @click="onTabChange(index)"
+        >{{ tab.name }}</view
+      >
+    </view>
+
+    <!-- 订单统计 -->
+    <view class="amount-card">
+      <!-- 日期选择 -->
+      <view class="date-picker">
+        <view @click="selectDate">
+          <text>{{ startDate ? startDate : '开始时间' }}</text>
+          <text class="date-separator">至</text>
+          <text>{{ endDate ? endDate : '结束时间' }}</text>
+          <u-icon v-if="!startDate || !endDate" class="ml-1" name="arrow-down-fill" size="18" color="#666666"></u-icon>
+        </view>
+        <uni-icons
+          v-if="startDate"
+          class="ml-1"
+          type="clear"
+          size="18"
+          color="#909399"
+          @click="resetDateRange"
+        ></uni-icons>
+      </view>
+      <!-- 普通/团餐 -->
+      <view v-if="currentTab == 0 || currentTab == 2">
+        <view class="row u-m-b-12">
+          <view class="item">
+            <text class="label">{{ currentTab == 0 ? '订单金额 (元)' : '团餐订单金额 (元)' }}</text>
+            <text class="value">{{ formatAmount(orderData.orderAmount) || '0.00' }}</text>
+          </view>
+          <view class="item">
+            <text class="label">{{ currentTab == 0 ? '退款金额 (元)' : '团餐退款金额 (元)' }}</text>
+            <text class="value">{{ formatAmount(orderData.refundAmount) || '0.00' }}</text>
+          </view>
+        </view>
+        <view class="row u-m-b-12">
+          <view class="item">
+            <text class="label">{{ currentTab == 0 ? '支付订单量' : '团餐订单量' }}</text>
+            <text class="value">{{ formatAmount(orderData.orderCount, 'quantity') || '0' }}</text>
+          </view>
+          <view class="item">
+            <text class="label">退款订单量</text>
+            <text class="value">{{ formatAmount(orderData.refundCount, 'quantity') || '0' }}</text>
+          </view>
+        </view>
+        <view class="row" v-if="currentTab == 2">
+          <view class="item">
+            <text class="label">普通订单金额 (元)</text>
+            <text class="value">{{ formatAmount(orderData.normalOrderAmount) || '0.00' }}</text>
+          </view>
+          <view class="item">
+            <text class="label">企业订单金额 (元)</text>
+            <text class="value">{{ formatAmount(orderData.enterpriseOrderAmount) || '0.00' }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 渠道订单 -->
+      <view v-if="currentTab == 1">
+        <view class="row u-m-b-12">
+          <view class="item">
+            <text class="label">权益券金额 (元)</text>
+            <text class="value">{{ formatAmount(orderData.couponAmount) || '0.00' }}</text>
+          </view>
+          <view class="item">
+            <text class="label">实付金额 (元)</text>
+            <text class="value">{{ formatAmount(orderData.actualPayAmount) || '0.00' }}</text>
+          </view>
+        </view>
+        <view class="row">
+          <view class="item">
+            <text class="label">应收金额 (元)</text>
+            <text class="value">{{ formatAmount(orderData.receivableAmount) || '0.00' }}</text>
+          </view>
+          <view class="item">
+            <text class="label">订单量</text>
+            <text class="value">{{ formatAmount(orderData.orderCount, 'quantity') || '0' }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <rangTime ref="rangTime" :mode="1" title="选择日期" @onSubmit="onEndTimeChange" />
+  </view>
+</template>
+
+<script>
+import api from '@/api/account.js';
+import { formatAmount } from '@/common/util/util';
+import rangTime from '@/components/dengrq-datetime-picker/dateSelector/index.vue';
+
+export default {
+  components: {
+    rangTime,
+  },
+  data() {
+    return {
+      formatAmount,
+      currentTab: 0,
+      financeData: {},
+      orderData: {},
+      startDate: '',
+      endDate: '',
+      businessTabs: [
+        { name: '普通业务', type: 'NORMAL' },
+        { name: '渠道业务', type: 'CHANNEL' },
+        { name: '团餐业务', type: 'GROUP_MEAL' },
+      ],
+    };
+  },
+  onShow() {
+    this.getData();
+    this.getFinanceInfo();
+  },
+  methods: {
+    getData() {
+      api.getAccountInfo().then((res) => {
+        if (res.data.code === 200 && res.data.result) {
+          this.financeData = res.data.result;
+        }
+      });
+    },
+    getFinanceInfo() {
+      const params = {
+        bizType: this.businessTabs[this.currentTab].type,
+      };
+      if (this.startDate) {
+        params.startDate = this.startDate;
+        params.endDate = this.endDate;
+      }
+      api.getFinanceStats(params).then((res) => {
+        if (res.data.code === 200 && res.data.result) {
+          this.orderData = res.data.result;
+          this.startDate = res.data.result.startDate;
+          this.endDate = res.data.result.endDate;
+          this.$refs.rangTime.startDate = this.startDate;
+          this.$refs.rangTime.endDate = this.endDate;
+        }
+      });
+    },
+    onTabChange(e) {
+      this.currentTab = e;
+      this.resetDateRange();
+    },
+    // 选择日期
+    selectDate() {
+      this.$refs.rangTime.open();
+    },
+    onEndTimeChange(val) {
+      this.startDate = val.startDate;
+      this.endDate = val.endDate;
+      console.log(this.startDate, this.endDate);
+      this.$forceUpdate();
+      this.getFinanceInfo();
+    },
+    resetDateRange() {
+      this.startDate = '';
+      this.endDate = '';
+      this.$refs.rangTime.startDate = '';
+      this.$refs.rangTime.endDate = '';
+      this.getFinanceInfo();
+    },
+    // 跳转账号余额
+    goPage() {
+      uni.navigateTo({
+        url: `/pages/finance/balance?balance=${this.financeData.availableAmount}`,
+      });
+    },
+    // 跳转提现
+    goWithdrawal() {
+      uni.navigateTo({
+        url: `/pages/finance/withdrawal?balance=${this.financeData.availableAmount}`,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.container {
+  width: 100%;
+  background: #ffffff;
+  font-family: Source Han Sans CN;
+
+  .top {
+    width: 100%;
+    height: var(--status-bar-height);
+    background:
+      linear-gradient(90deg, #e3f4f8 0%, #ebf7f7 47.5%, #d6eff7 100%),
+      linear-gradient(180deg, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
+  }
+
+  .title {
+    height: 117rpx;
+    font-family: Source Han Sans SC;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 38rpx;
+    color: #333333;
+    font-weight: 500;
+    border-bottom: 1rpx solid #eeeeee;
+    background:
+      linear-gradient(90deg, #e3f4f8 0%, #ebf7f7 47.5%, #d6eff7 100%),
+      linear-gradient(180deg, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
+  }
+
+  .balance-card {
+    margin: 21rpx 25rpx 10rpx;
+    padding: 21rpx 31rpx 31rpx;
+    background: linear-gradient(286deg, #34bbff 0%, #4496fb 100%);
+    box-shadow: 0rpx 4rpx 10rpx 0rpx #dae3f4;
+    border-radius: 21rpx 21rpx 21rpx 21rpx;
+    border: 1rpx solid rgba(255, 255, 255, 0.6);
+
+    .balance-info {
+      flex: 1;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      border-bottom: 1rpx solid rgba(255, 255, 255, 0.2);
+      margin-bottom: 21rpx;
+
+      .balance-label {
+        display: block;
+        font-weight: 400;
+        font-size: 25rpx;
+        color: #ffffff;
+      }
+
+      .balance-amount {
+        font-family:
+          DIN Alternate,
+          DIN Alternate;
+        font-weight: bold;
+        font-size: 63rpx;
+        color: #ffffff;
+      }
+
+      .withdraw-btn {
+        width: 129rpx;
+        height: 63rpx;
+        background: #ffffff;
+        border-radius: 8rpx 8rpx 8rpx 8rpx;
+        font-family: Source Han Sans SC;
+        font-weight: 500;
+        font-size: 29rpx;
+        color: #38b2fe;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+
+  .stats-row {
+    display: flex;
+    text-align: left;
+
+    :last-child {
+      margin-bottom: 0;
+    }
+
+    .stat-item {
+      flex: 1;
+      text-align: center;
+
+      .stat-label {
+        display: block;
+        font-weight: 400;
+        font-size: 21rpx;
+        color: #ffffff;
+      }
+
+      .stat-value {
+        font-family: DIN Alternate;
+        font-weight: bold;
+        font-size: 38rpx;
+        color: #ffffff;
+      }
+    }
+  }
+
+  .amount-card {
+    margin: 21rpx 25rpx 0;
+    padding: 17rpx 0 21rpx;
+    background: #f7f8fc;
+    border-radius: 21rpx 21rpx 21rpx 21rpx;
+
+    .row {
+      display: flex;
+      text-align: left;
+
+      :last-child {
+        margin-bottom: 0;
+      }
+
+      .item {
+        flex: 1;
+        text-align: center;
+
+        .label {
+          display: block;
+          font-weight: 400;
+          font-size: 21rpx;
+          color: #666666;
+        }
+
+        .value {
+          font-family: Source Han Sans SC;
+          font-weight: 500;
+          font-size: 33rpx;
+          color: #333333;
+        }
+      }
+    }
+  }
+
+  .business-tabs {
+    display: flex;
+    justify-content: space-around;
+
+    .tab-item {
+      // flex: 1;
+      position: relative;
+      padding: 18rpx 0;
+      cursor: pointer;
+      font-family: Source Han Sans SC;
+      color: #333333;
+      font-weight: 400;
+      font-size: 29rpx;
+    }
+
+    .active {
+      font-weight: 500;
+      color: #449aff;
+    }
+    .tab-item.active::after {
+      content: '';
+      position: absolute;
+      bottom: -28px;
+      left: 35%;
+      width: 38rpx;
+      height: 100%;
+      background: url('@/static/product/tab-act.png') no-repeat;
+      background-size: contain;
+    }
+  }
+
+  .date-picker {
+    display: flex;
+    justify-content: center;
+    border-radius: 12rpx;
+    margin: 0 28rpx 17rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    font-weight: 400;
+    font-size: 27rpx;
+    color: #666666;
+
+    .date-separator {
+      margin: 0 5px;
+    }
+  }
+}
+</style>

+ 258 - 0
pages/finance/orderDetails.vue

@@ -0,0 +1,258 @@
+<template>
+  <view class="order">
+    <view class="fix">
+      <view class="top"></view>
+      <view class="head">
+        <span class="cuIcon-back" @click="back"></span>
+        <view class="case"> 结算详情 </view>
+      </view>
+    </view>
+
+    <view class="order-card">
+      <view class="order-header">
+        <view class="amount">{{ orderInfo.payableToMerchant }}</view>
+        <view class="title">应收金额</view>
+      </view>
+      <view class="order-info">
+        <view v-for="(item, index) in orderFields" :key="index" class="info">
+          <view class="label">
+            {{ item.title }}
+            <image
+              v-if="item.isShowTip"
+              src="/static/finance/status/icon-remind.png"
+              mode="aspectFit"
+              style="width: 33rpx; height: 33rpx; margin-left: 8rpx"
+              @click.stop="toggleTooltip(item.key)"
+            ></image>
+            <view class="tooltip" v-show="showTooltip === item.key"> 商户占比{{ orderInfo[item.rateField] }}% </view>
+          </view>
+          <view class="value">{{ orderInfo[item.valueField] }}</view>
+        </view>
+      </view>
+
+      <!-- 备注说明 -->
+      <view class="remark">
+        注:应收金额=订单金额*商品分佣占比-邀新分佣成本-优惠券成本-会员折扣成本-金豆抵扣成本-推广分佣成本</view
+      >
+    </view>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+import {orderFields} from './dictionary';
+
+export default {
+  name: 'OrderDetails',
+  data() {
+    return {
+      orderId: '',
+      orderInfo: {},
+      showTooltip: null,
+      tooltipTimer: null,
+      orderFields,
+    };
+  },
+  mounted() {
+    // 点击其他区域隐藏提示
+    document.addEventListener('click', this.handleClickOutside);
+  },
+  beforeUnmount() {
+    // 移除事件监听
+    document.removeEventListener('click', this.handleClickOutside);
+    // 清除定时器
+    if (this.tooltipTimer) {
+      clearTimeout(this.tooltipTimer);
+    }
+  },
+  onLoad(options) {
+    if (options.id) {
+      this.orderId = options.id;
+    }
+  },
+  onShow() {
+    this.getOrderDetails(this.orderId);
+  },
+  methods: {
+    getOrderDetails(id) {
+      api.orderClearDetail(id).then((res) => {
+        if (res.data.code === 200) {
+          this.orderInfo = res.data.result;
+        }
+      });
+    },
+    back() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+    // 处理点击事件,显示提示并设置10秒自动隐藏
+    toggleTooltip(key) {
+      // 清除之前的定时器
+      if (this.tooltipTimer) {
+        clearTimeout(this.tooltipTimer);
+      }
+      // 显示当前提示,隐藏其他提示
+      this.showTooltip = this.showTooltip === key ? null : key;
+
+      // 如果是显示状态,设置10秒后自动隐藏
+      if (this.showTooltip) {
+        this.tooltipTimer = setTimeout(() => {
+          this.showTooltip = null;
+        }, 10000); // 10秒自动隐藏
+      }
+    },
+    // 点击其他区域隐藏提示
+    handleClickOutside(event) {
+      // 检查点击目标是否在提示或图片上
+      const tooltipElements = document.querySelectorAll('.tooltip, image[src*="icon-remind.png"]');
+      let isClickOnTooltip = false;
+
+      tooltipElements.forEach((element) => {
+        if (element.contains(event.target)) {
+          isClickOnTooltip = true;
+        }
+      });
+
+      // 如果点击的不是提示或图片,隐藏所有提示
+      if (!isClickOnTooltip) {
+        this.showTooltip = null;
+        // 清除定时器
+        if (this.tooltipTimer) {
+          clearTimeout(this.tooltipTimer);
+        }
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.order {
+  background: #f7f8fc;
+  min-height: 100vh;
+  font-family: Source Han Sans SC;
+  font-weight: 500;
+
+  .fix {
+    position: sticky;
+    top: 0;
+
+    /*#ifdef APP-PLUS*/
+    .top {
+      width: 100%;
+      height: var(--status-bar-height);
+      background: #fff;
+    }
+
+    /*#endif*/
+
+    .head {
+      width: 100%;
+      height: 112rpx;
+      padding: 20rpx;
+      display: flex;
+      align-items: center;
+      background: #fff;
+      position: relative;
+      border-bottom: 1rpx solid #eeeeee;
+
+      .cuIcon-back {
+        font-size: 40rpx;
+        margin-right: 40rpx;
+      }
+
+      .case {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        font-weight: 500;
+        font-size: 38rpx;
+        color: #333333;
+      }
+    }
+  }
+
+  .order-card {
+    padding: 42rpx 31rpx 85rpx;
+    overflow: hidden;
+    background: #ffffff;
+    height: 95vh;
+  }
+}
+
+.order-header {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+
+  .amount {
+    font-size: 63rpx;
+    color: #1f1f1f;
+  }
+
+  .title {
+    font-size: 28rpx;
+    color: #666666;
+    margin: 11rpx 0 42rpx;
+  }
+}
+
+.order-info {
+  .info {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 21rpx;
+
+    .label {
+      display: flex;
+      align-items: center;
+      font-weight: 400;
+      font-size: 31rpx;
+      color: #666666;
+      position: relative;
+
+      .tooltip {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 158rpx;
+        height: 42rpx;
+        background: rgba(0, 0, 0, 0.6);
+        border-radius: 4rpx 4rpx 4rpx 4rpx;
+        font-family: PingFang SC;
+        font-weight: 400;
+        font-size: 23rpx;
+        color: #ffffff;
+        margin-left: 10rpx;
+
+        &::after {
+          content: '';
+          position: absolute;
+          right: 158rpx;
+          bottom: 14rpx;
+          width: 0;
+          height: 0;
+          border-bottom: 10rpx solid transparent;
+          border-right: 10rpx solid rgba(0, 0, 0, 0.6);
+          border-top: 10rpx solid transparent;
+          border-left: 0;
+        }
+      }
+    }
+
+    .value {
+      font-size: 31rpx;
+      color: #333333;
+    }
+  }
+}
+
+.remark {
+  font-weight: 400;
+  font-size: 25rpx;
+  color: #666666;
+  margin-top: 10rpx;
+}
+</style>

+ 219 - 0
pages/finance/settlementDetails.vue

@@ -0,0 +1,219 @@
+<template>
+  <view class="settle">
+    <view class="fix">
+      <view class="top"></view>
+      <view class="head">
+        <span class="cuIcon-back" @click="back"></span>
+        <view class="case"> 结算详情 </view>
+      </view>
+    </view>
+
+    <view class="settle-card">
+      <view class="settle-header">
+        <view class="amount">¥{{ settlementInfo.amountPayable }}</view>
+      </view>
+      <view class="settle-info">
+        <view class="info">
+          <view class="label">结算单号</view>
+          <view class="value">{{ settlementInfo.statementNumber }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">结算时间</view>
+          <view class="value">{{ settlementInfo.settlementTime }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">结算金额</view>
+          <view class="value">¥{{ settlementInfo.amountPayable }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">结算明细范围</view>
+          <view class="value"
+            >{{ settlementInfo.settlementScopeStartTime }} - {{ settlementInfo.settlementScopeEndTime }}</view
+          >
+        </view>
+
+        <view class="info">
+          <view class="label">操作人</view>
+          <view class="value">{{ settlementInfo.operator }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">结算状态</view>
+          <view class="value">{{ settlementInfo.settleStatusName }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">结算单据</view>
+          <view class="value">{{ settlementInfo.settlementDocument }}</view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 订单列表 -->
+    <view class="list-card">
+      <OrderList :list="orderList"></OrderList>
+    </view>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+import OrderList from './components/order-list.vue';
+
+export default {
+  name: 'SettlementDetails',
+  components: {
+    OrderList,
+  },
+  data() {
+    return {
+      bizId: '',
+      // 结算信息
+      settlementInfo: {},
+      // 订单列表
+      orderList: [],
+    };
+  },
+  onLoad(options) {
+    if (options.id) {
+      this.bizId = options.id;
+    }
+  },
+  onShow() {
+    this.getDetails(this.bizId);
+  },
+  methods: {
+    getDetails(id) {
+      api
+        .settlementDetail(id)
+        .then((res) => {
+          if (res.data.code === 200) {
+            this.settlementInfo = res.data.result;
+            this.orderList = res.data.result.orderList || [];
+          } else {
+            uni.showToast({
+              title: res.data.msg || '获取结算详情失败',
+              icon: 'none',
+            });
+          }
+        })
+        .catch(() => {
+          uni.showToast({
+            title: '获取结算详情失败',
+            icon: 'none',
+          });
+        });
+    },
+    back() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.settle {
+  background: #f7f8fc;
+  min-height: 100vh;
+  font-family: Source Han Sans SC;
+  padding-bottom: 100rpx;
+
+  .fix {
+    position: sticky;
+    top: 0;
+    /*#ifdef APP-PLUS*/
+    .top {
+      width: 100%;
+      height: var(--status-bar-height);
+      background: #fff;
+    }
+
+    /*#endif*/
+
+    .head {
+      width: 100%;
+      height: 112rpx;
+      padding: 20rpx;
+      display: flex;
+      align-items: center;
+      background: #fff;
+      position: relative;
+      border-bottom: 1rpx solid #eeeeee;
+
+      .cuIcon-back {
+        font-size: 40rpx;
+        margin-right: 40rpx;
+      }
+
+      .case {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        font-weight: 500;
+        font-size: 38rpx;
+        color: #333333;
+      }
+    }
+  }
+
+  .settle-card {
+    background-color: #fff;
+    padding: 30rpx 31rpx 10rpx;
+  }
+}
+
+.settle-header {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  font-weight: 500;
+
+  .amount {
+    font-weight: 500;
+    font-size: 63rpx;
+    color: #1f1f1f;
+    margin-bottom: 41rpx;
+  }
+}
+.settle-info {
+  background-color: #fff;
+  margin-bottom: 20rpx;
+}
+
+.info {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 21rpx;
+
+  &:last-child {
+    border-bottom: none;
+  }
+
+  .label {
+    font-weight: 400;
+    font-size: 31rpx;
+    color: #666666;
+  }
+
+  .value {
+    font-weight: 500;
+    font-size: 31rpx;
+    color: #333333;
+  }
+}
+
+.list-card {
+  height: 100%;
+  flex: 1;
+  overflow: hidden;
+  margin: 21rpx 31rpx;
+  background-color: #fff;
+}
+</style>

+ 114 - 0
pages/finance/submitted.vue

@@ -0,0 +1,114 @@
+<template>
+  <view class="container">
+    <view class="top"></view>
+    <view class="head">
+      <span class="cuIcon-back" @click="goBack"></span>
+      <view class="case"> 已提交 </view>
+    </view>
+
+    <view class="content">
+      <image class="icon" src="/static/finance/status/success.png" />
+
+      <text class="title">提交成功</text>
+      <text class="desc">已提交审核,请耐心等待平台审核</text>
+
+      <view class="btn" @click="goBack">返回账户</view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  methods: {
+    goBack() {
+      uni.navigateTo({
+        url: '/pages/finance/balance',
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.container {
+  width: 100vw;
+  height: 100vh;
+  overflow: auto;
+  background: #ffffff;
+  font-family: Source Han Sans SC;
+
+  /*#ifdef APP-PLUS*/
+  .top {
+    width: 100%;
+    height: var(--status-bar-height);
+    background: #fff;
+  }
+
+  /*#endif*/
+
+  .head {
+    width: 100%;
+    height: 112rpx;
+    padding: 20rpx;
+    display: flex;
+    align-items: center;
+    background: #fff;
+    position: relative;
+    border-bottom: 1rpx solid #eeeeee;
+
+    .cuIcon-back {
+      font-size: 40rpx;
+      margin-right: 40rpx;
+    }
+
+    .case {
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      font-weight: 500;
+      font-size: 38rpx;
+      color: #333333;
+    }
+  }
+
+  .content {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    flex-direction: column;
+
+    .icon {
+      width: 104rpx;
+      height: 104rpx;
+      margin: 83rpx 0 21rpx;
+    }
+
+    .title {
+      font-weight: 500;
+      font-size: 50rpx;
+      color: #333333;
+      margin-bottom: 10rpx;
+    }
+
+    .desc {
+      font-weight: 400;
+      font-size: 29rpx;
+      color: #666666;
+      margin-bottom: 125rpx;
+    }
+
+    .btn {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 642rpx;
+      height: 79rpx;
+      background: linear-gradient(90deg, #4daeee 0%, #449aff 100%);
+      border-radius: 55rpx 55rpx 55rpx 55rpx;
+      font-weight: 500;
+      font-size: 29rpx;
+      color: #ffffff;
+    }
+  }
+}
+</style>

+ 429 - 0
pages/finance/withdrawal.vue

@@ -0,0 +1,429 @@
+<template>
+  <view class="container">
+    <view class="fix">
+      <view class="top"></view>
+      <view class="head">
+        <span class="cuIcon-back" @click="back"></span>
+        <view class="case"> 申请提现 </view>
+      </view>
+    </view>
+
+    <view class="form-card">
+      <view class="section-input">
+        <view class="label">提现金额 <i class="text-bg"></i></view>
+        <view class="input-row">
+          <text class="currency-symbol">¥</text>
+          <u-input
+            type="digit"
+            height="80"
+            placeholder="请输入提现金额"
+            :customStyle="{
+              fontSize: '42rpx',
+              padding: '0 10rpx',
+              marginTop: '10rpx',
+            }"
+            v-model="withdrawalAmount"
+            @input="handleInput"
+          ></u-input>
+        </view>
+        <view v-if="isExceeded" class="error">输入金额超过可提现余额</view>
+
+        <view class="balance-info">
+          <text>可提现余额{{ availableAmount }}元,</text>
+          <text>手续费每笔{{ handlingFee }}元</text>
+          <text class="all-withdraw-btn" @click="allWithdraw">全部提现</text>
+        </view>
+      </view>
+    </view>
+
+    <view class="form-card">
+      <view class="label">账户信息 <i class="text-bg"></i></view>
+      <view class="bank-info">
+        <view class="bank-label">银行账户</view>
+        <view class="u-flex">
+          <u-image :src="bankCardInfo.bankLogo" width="42rpx" height="42rpx"></u-image>
+          <view class="bank-number">{{ bankCardInfo.bankName }}({{ bankCardInfo.bankCardNumber }})</view>
+        </view>
+      </view>
+    </view>
+
+    <view class="form-card">
+      <view class="u-flex justify-between">
+        <view class="title">开票信息<i class="text-bg"></i></view>
+        <view class="note">注:提现申请请上传开票凭证</view>
+      </view>
+      <view class="invoice-info">
+        <text class="title">发票抬头</text>
+        <text class="value">{{ invoiceInfo.companyName }}</text>
+      </view>
+      <view class="invoice-info">
+        <text class="title">纳税人识别号</text>
+        <text>{{ invoiceInfo.taxNo }}</text>
+      </view>
+      <view class="invoice-info">
+        <text class="title">地址详情</text>
+        <text class="value">{{ invoiceInfo.address }} {{ invoiceInfo.phone }}</text>
+      </view>
+      <view class="invoice-info last">
+        <text class="title">开户银行及账号</text>
+        <text class="value">{{ invoiceInfo.openingBank }} {{ invoiceInfo.bankAccount }}</text>
+      </view>
+    </view>
+
+    <view class="form-card">
+      <view class="label">上传发票 <i class="text-bg"></i></view>
+      <u-upload
+        ref="uUpload"
+        :action="action"
+        :file-list="billList"
+        @on-success="handleSuccess"
+        @on-remove="handleRemove"
+        @on-choose-complete="onChooseComplete"
+        max-count="5"
+        multiple
+        previewFullImage
+        :auto-upload="true"
+        customBtn
+        width="146rpx"
+        height="146rpx"
+      >
+        <template slot="addBtn">
+          <image src="/static/coupon/upload.png" mode="widthFix" style="width: 146rpx; height: 146rpx"></image>
+        </template>
+      </u-upload>
+    </view>
+    <view class="footer-bar">
+      <u-button
+        type="primary"
+        :disabled="!withdrawalAmount || parseFloat(withdrawalAmount) <= 0 || isExceeded"
+        @click="applyWithdrawal"
+        >提现</u-button
+      >
+    </view>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+import configService from '@/common/service/config.service';
+import { formatAmount } from '@/common/util/util';
+
+export default {
+  data() {
+    return {
+      formatAmount,
+      action: configService.apiUrl + '/sys/common/upload',
+      imageHttp: configService.apiUrl + '/',
+      billList: [], //发票回显
+      uploadedFiles: [], //已上传文件列表
+      bankCard: {},
+      availableAmount: '', // 当前可提现余额
+      handlingFee: 0, // 手续费
+      withdrawalAmount: '', // 提现金额输入框的值
+      isExceeded: false, // 是否超过可提现余额
+      bankCardInfo: {}, // 银行卡信息
+      invoiceInfo: {}, // 开票信息
+    };
+  },
+  watch: {
+    withdrawalAmount(newVal, oldVal) {
+      // 检查金额是否超过可提现余额
+      if (parseFloat(newVal) > parseFloat(this.availableAmount)) {
+        this.isExceeded = true;
+      } else {
+        this.isExceeded = false;
+      }
+    },
+  },
+  onShow() {
+    this.init();
+  },
+  formatAmount,
+  methods: {
+    // 初始化提现数据
+    async init() {
+      const res = await api.initWithdrawalData();
+      if (res.data.code === 200 && res.data.result) {
+        const data = res.data.result;
+        this.availableAmount = data.availableAmount;
+        this.handlingFee = data.handlingFee;
+        this.bankCardInfo = data.bankCardInfo;
+        this.invoiceInfo = data.invoiceInfo;
+      }
+    },
+    handleInput(val) {
+      if (!val) {
+        this.withdrawalAmount = '';
+        return;
+      }
+      /// 保留2位小数
+      val = val.replace(/(\.\d{2})\d+/g, '$1');
+      // 处理前导0
+      val = val.replace(/^0+(?=\d)/, '');
+
+      this.$nextTick(() => {
+        this.withdrawalAmount = val;
+      });
+    },
+    // 上传发票
+    handleSuccess(res) {
+      if (res.code === 0) {
+        this.uploadedFiles.push(this.imageHttp + res.message);
+        console.log(this.uploadedFiles);
+      } else {
+        uni.showToast({
+          title: '上传失败: ' + res.message,
+          icon: 'none',
+        });
+      }
+    },
+    // 移除图片
+    handleRemove(index) {
+      this.uploadedFiles.splice(index, 1);
+    },
+    // 选择图片
+    onChooseComplete(lists) {
+      this.billList = lists;
+    },
+    // 全部提现
+    allWithdraw() {
+      this.withdrawalAmount = this.availableAmount;
+    },
+    // 申请提现
+    applyWithdrawal() {
+      // if (!this.uploadedFiles.length) {
+      //   uni.showToast({
+      //     title: '请上传发票',
+      //     icon: 'none',
+      //   });
+      //   return;
+      // }
+      uni.showLoading({ title: '提交中' });
+      api
+        .applyWithdrawal({
+          applyAmount: this.withdrawalAmount,
+          bankCardId: this.bankCardInfo.bankCardId,
+          handlingFee: this.handlingFee,
+          invoiceImgs: this.uploadedFiles,
+        })
+        .then((res) => {
+          if (res.data.code === 200) {
+            uni.hideLoading();
+            uni.showToast({ title: '提现申请成功', icon: 'success' });
+            setTimeout(() => {
+              uni.navigateTo({
+                url: '/pages/finance/submitted',
+              });
+            }, 1500);
+          } else {
+            uni.hideLoading();
+            uni.showToast({ title: res.data.message, icon: 'none' });
+          }
+        });
+    },
+    back() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.container {
+  min-height: 100vh;
+  background-color: #f7f8fc;
+  font-family: Source Han Sans SC;
+  font-weight: 400;
+  padding-bottom: 120rpx;
+
+  .fix {
+    position: sticky;
+    top: 0;
+    z-index: 999;
+
+    /*#ifdef APP-PLUS*/
+    .top {
+      width: 100%;
+      height: var(--status-bar-height);
+      background: #fff;
+    }
+
+    /*#endif*/
+
+    .head {
+      width: 100%;
+      height: 112rpx;
+      padding: 20rpx;
+      display: flex;
+      align-items: center;
+      background: #fff;
+      position: relative;
+      border-bottom: 1rpx solid #eeeeee;
+
+      .cuIcon-back {
+        font-size: 40rpx;
+        margin-right: 40rpx;
+      }
+
+      .case {
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        font-weight: 500;
+        font-size: 38rpx;
+        color: #333333;
+      }
+    }
+  }
+
+  .form-card {
+    background-color: #fff;
+    padding: 30rpx;
+    margin-bottom: 30rpx;
+    padding: 17rpx 31rpx 21rpx;
+    box-shadow: 0rpx 2rpx 8rpx 0rpx rgba(214, 225, 237, 0.1);
+
+    .label {
+      font-size: 30rpx;
+      color: #333333;
+      margin-bottom: 21rpx;
+
+      .text-bg {
+        width: 120rpx;
+      }
+    }
+  }
+}
+
+// 提现至:银行卡选择区域
+.section-item {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 30rpx 0;
+  border-bottom: 1rpx solid #eee;
+
+  .label {
+    font-weight: 500;
+    font-size: 31rpx;
+    color: #333333;
+  }
+
+  .content {
+    display: flex;
+    align-items: center;
+  }
+}
+
+// 提现金额输入区域
+.section-input {
+  .input-row {
+    display: flex;
+    align-items: center;
+    padding: 20rpx 0;
+    border-bottom: 1rpx solid #eee;
+
+    .currency-symbol {
+      font-weight: bold;
+      font-size: 54rpx;
+      color: #333333;
+      padding-right: 23rpx;
+    }
+  }
+
+  .error {
+    text-align: right;
+    font-size: 25rpx;
+    color: #e55e4f;
+  }
+
+  .balance-info {
+    font-size: 26rpx;
+    color: rgba(51, 51, 51, 0.6);
+    margin-top: 16rpx;
+    font-family: Source Han Sans CN;
+
+    .all-withdraw-btn {
+      font-size: 27rpx;
+      color: #2d4d89;
+      margin-left: 10rpx;
+
+      &:active {
+        opacity: 0.8;
+      }
+    }
+  }
+}
+
+// 银行信息
+.bank-info {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-top: 44rpx;
+
+  .bank-label {
+    font-size: 29rpx;
+    color: #666666;
+  }
+
+  .bank-number {
+    padding: 0 0 5rpx 2rpx;
+    font-size: 31rpx;
+    color: #333333;
+  }
+}
+
+// 开票信息区域
+.note {
+  font-size: 27rpx;
+  color: #999999;
+  margin-bottom: 26rpx;
+}
+
+.invoice-info {
+  padding: 21rpx 0;
+  display: flex;
+  justify-content: space-between;
+  border-bottom: 1rpx solid #eeeeee;
+
+  .title {
+    font-size: 29rpx;
+    color: #666666;
+  }
+
+  .value {
+    font-size: 31rpx;
+    color: #333333;
+    max-width: 450rpx;
+    text-align: right;
+  }
+}
+
+.last {
+  border-bottom: none;
+}
+
+// 底部按钮
+.footer-bar {
+  z-index: 999;
+
+  ::v-deep .u-btn {
+    width: 100%;
+    height: 76rpx;
+    border-radius: 54rpx;
+    background: linear-gradient(90deg, #77b6ff 0%, #449aff 100%);
+    &.u-btn--primary--disabled {
+      background: #a0cfff;
+    }
+  }
+}
+
+::v-deep {
+  .u-delete-icon {
+    background-color: rgb(0, 0, 0, 0.6) !important;
+  }
+}
+</style>

+ 210 - 0
pages/finance/withdrawalDetails.vue

@@ -0,0 +1,210 @@
+<template>
+  <view class="cash">
+    <view class="top"></view>
+    <view class="head">
+      <span class="cuIcon-back" @click="back"></span>
+      <view class="case"> 提现详情 </view>
+    </view>
+
+    <view class="cash-card">
+      <view class="cash-header">
+        <view class="img">
+          <image :src="`/static/finance/status/${reviewIcon}.png`" mode="aspectFit"></image>
+        </view>
+        <view class="amount">-¥{{ cashInfo.applyAmount }}</view>
+        <view class="title">{{ cashInfo.statusName }}</view>
+      </view>
+      <view class="cash-info">
+        <view class="info">
+          <view class="label">申请时间</view>
+          <view class="value">{{ cashInfo.applyTime }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">申请人</view>
+          <view class="value">{{ cashInfo.applicantName }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">审批时间</view>
+          <view class="value">{{ cashInfo.auditTime }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">审批人</view>
+          <view class="value">{{ cashInfo.auditByName }}</view>
+        </view>
+
+        <view class="info">
+          <view class="label">订单号</view>
+          <view class="value">{{ cashInfo.withdrawNo }}</view>
+        </view>
+
+        <view v-if="cashInfo.invoiceImgs && cashInfo.invoiceImgs.length" class="info">
+          <view class="label">发票</view>
+          <view class="value view-btn" @click="openInvoicePopup">查看</view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import api from '@/api/account';
+
+export default {
+  name: 'cashDetails',
+  data() {
+    return {
+      bizId: '',
+      cashInfo: {},
+      showInvoicePopup: false,
+      reviewIcon: '',
+    };
+  },
+  onLoad(options) {
+    if (options.id) {
+      this.bizId = options.id;
+    }
+  },
+  onShow() {
+    this.getCashDetails(this.bizId);
+  },
+  methods: {
+    getCashDetails(bizId) {
+      api.getWithdrawalDetails(bizId).then((res) => {
+        if (res.data.code === 200) {
+          this.cashInfo = res.data.result;
+          switch (this.cashInfo.statusName) {
+            case '提现成功':
+              this.reviewIcon = 'success';
+              break;
+            case '提现失败':
+              this.reviewIcon = 'fail';
+              break;
+            case '审核中':
+              this.reviewIcon = 'processing';
+              break;
+          }
+        }
+      });
+    },
+    back() {
+      uni.navigateBack();
+    },
+    openInvoicePopup() {
+      uni.previewImage({
+        urls: this.cashInfo.invoiceImgs,
+        current: this.cashInfo.invoiceImgs[0],
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.cash {
+  background: #f8f8f8;
+  min-height: 100vh;
+  font-weight: 500;
+
+  /*#ifdef APP-PLUS*/
+  .top {
+    width: 100%;
+    height: var(--status-bar-height);
+    background: #fff;
+  }
+
+  /*#endif*/
+
+  .head {
+    width: 100%;
+    height: 112rpx;
+    padding: 20rpx;
+    display: flex;
+    align-items: center;
+    background: #fff;
+    position: relative;
+    border-bottom: 1rpx solid #eeeeee;
+
+    .cuIcon-back {
+      font-size: 40rpx;
+      margin-right: 40rpx;
+    }
+
+    .case {
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      font-weight: 500;
+      font-size: 38rpx;
+      color: #333333;
+    }
+  }
+
+  .cash-card {
+    border-radius: 10rpx;
+    overflow: hidden;
+    padding: 50rpx 32rpx 0;
+    background: #fff;
+  }
+}
+
+.cash-header {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  background-color: #ffffff;
+
+  image {
+    width: 88rpx;
+    height: 88rpx;
+  }
+
+  .amount {
+    font-size: 60rpx;
+    color: #1f1f1f;
+    margin: 30rpx 0 20rpx;
+  }
+
+  .title {
+    font-weight: 400;
+    font-size: 28rpx;
+    color: #666666;
+    margin-bottom: 40rpx;
+  }
+}
+
+.cash-info {
+  background-color: #fff;
+  padding: 0 30rpx;
+}
+
+.info {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 30rpx;
+  font-size: 30rpx;
+
+  .label {
+    display: flex;
+    align-items: center;
+    font-weight: 400;
+    color: #666666;
+    line-height: 30rpx;
+  }
+
+  .value {
+    font-family: Source Han Sans SC;
+    font-weight: 500;
+    font-size: 30rpx;
+    color: #333333;
+  }
+
+  .view-btn {
+    color: #449aff;
+  }
+}
+</style>

+ 1 - 1
pages/index/index.vue

@@ -22,7 +22,7 @@
 					<span>{{income}}</span>收益
 				</view>
 				<view class="item" @click="goUser">
-					<span>{{newCustomer}}</span>新客
+					<span>{{newCustomer || 0}}</span>新客
 				</view>
 			</view>
 		</view>

BIN
static/finance/account/auditing.png


BIN
static/finance/account/cash.png


BIN
static/finance/account/completed.png


BIN
static/finance/account/icon-list.png


BIN
static/finance/account/pending.png


BIN
static/finance/account/settlement.png


BIN
static/finance/status/fail.png


BIN
static/finance/status/icon-remind.png


BIN
static/finance/status/processing.png


BIN
static/finance/status/success.png


BIN
static/tabbar/finance_select_tab.png


BIN
static/tabbar/finance_tab.png