文件

478 行
18 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>骑手提现管理</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/css/menu.css?v=1.0.5"/>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/css/minimal-admin.css?v=1.0.0"/>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/Retail/css/myscroll.css?v=1.0.2"/>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/layui-v2.4.3/layui/css/layui.css"/>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/Retail/css/home.css"/>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/Retail/css/goodsList.css?v=1.0.2"/>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/vue/element-ui.css?v=2.13.2">
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/vue/js/vue2.5.16.js"></script>
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/vue/element-ui.js?v=2.13.2"></script>
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/js/common.js?v=1.0.2"></script>
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/jquery/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/layui-v2.4.3/layui/layui.js"></script>
</head>
<body>
<div id="RiderWithdrawManagement" v-cloak>
<div class="goodsBox">
<div class="goods_title">
<div class="goods_title_inner">
<i class="fas fa-money-bill-wave" style="margin-right: 8px; color: #409EFF;"></i>
骑手提现管理
</div>
</div>
</div>
<!-- 统计卡片区域 -->
<div class="withdraw-stats-container" style="padding: 20px; background: #f5f7fa;">
<el-row :gutter="20">
<el-col :span="4">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<i class="fas fa-list"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.total_count }}</div>
<div class="stat-label">总申请数</div>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
<i class="fas fa-clock"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.pending_count }}</div>
<div class="stat-label">待审核</div>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
<i class="fas fa-check-circle"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.approved_count }}</div>
<div class="stat-label">已通过</div>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);">
<i class="fas fa-times-circle"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.rejected_count }}</div>
<div class="stat-label">已拒绝</div>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);">
<i class="fas fa-dollar-sign"></i>
</div>
<div class="stat-content">
<div class="stat-number">¥{{ statistics.total_amount }}</div>
<div class="stat-label">总金额</div>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);">
<i class="fas fa-hand-holding-usd"></i>
</div>
<div class="stat-content">
<div class="stat-number">¥{{ statistics.approved_amount }}</div>
<div class="stat-label">已通过金额</div>
</div>
</div>
</el-col>
</el-row>
</div>
<!-- 搜索筛选区域 -->
<div class="search-container" style="padding: 20px; background: white; margin: 20px; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);">
<el-form :inline="true" :model="searchForm" class="search-form">
<el-form-item>
<el-input v-model="searchForm.keyword" placeholder="骑手姓名/手机号" clearable style="width: 200px;"></el-input>
</el-form-item>
<el-form-item>
<el-select v-model="searchForm.status" placeholder="请选择状态" clearable style="width: 150px;">
<el-option label="待审核" value="0"></el-option>
<el-option label="已通过" value="1"></el-option>
<el-option label="已拒绝" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-date-picker
v-model="searchForm.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 240px;">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchWithdraw" icon="el-icon-search">搜索</el-button>
<el-button @click="resetSearch" icon="el-icon-refresh">重置</el-button>
</el-form-item>
</el-form>
</div>
<!-- 提现列表 -->
<div class="table-container" style="margin: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);">
<el-table :data="withdrawList" v-loading="loading" style="width: 100%;" stripe>
<el-table-column prop="id" label="提现ID" width="80" align="center"></el-table-column>
<el-table-column label="骑手信息" width="200">
<template slot-scope="scope">
<div style="display: flex; align-items: center;">
<el-avatar :src="scope.row.rider_avatar" size="small" style="margin-right: 10px;">
<i class="el-icon-user-solid"></i>
</el-avatar>
<div>
<div style="font-weight: bold;">{{ scope.row.rider_name }}</div>
<div style="color: #999; font-size: 12px;">{{ scope.row.rider_phone }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="amount_format" label="提现金额" width="120" align="center">
<template slot-scope="scope">
<span style="color: #f56c6c; font-weight: bold;">¥{{ scope.row.amount_format }}</span>
</template>
</el-table-column>
<el-table-column prop="fee" label="手续费" width="120" align="center">
<template slot-scope="scope">
<span style="color: #f56c6c; font-weight: bold;">¥{{ scope.row.fee }}</span>
</template>
</el-table-column>
<el-table-column prop="actual_amount" label="实际到账金额" width="120" align="center">
<template slot-scope="scope">
<span style="color: #f56c6c; font-weight: bold;">¥{{ scope.row.actual_amount }}</span>
</template>
</el-table-column>
<el-table-column label="打款账号" width="200">
<template slot-scope="scope">
<div>
<div style="display: flex; align-items: center; margin-bottom: 4px;">
<i :class="getWithdrawTypeIcon(scope.row.withdraw_type)" style="margin-right: 5px; color: #409EFF;"></i>
<span style="font-weight: bold;">{{ getWithdrawTypeName(scope.row.withdraw_type) }}</span>
</div>
<div style="color: #666; font-size: 12px;">{{ scope.row.account_name }}</div>
<div style="color: #999; font-size: 12px;">{{ scope.row.account_number }}</div>
<div v-if="scope.row.withdraw_type == 1 && scope.row.bank_name" style="color: #999; font-size: 11px;">{{ scope.row.bank_name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="status_text" label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)">{{ scope.row.status_text }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="create_time_format" label="申请时间" width="160" align="center"></el-table-column>
<el-table-column prop="update_time_format" label="处理时间" width="160" align="center"></el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-link size="mini" @click="viewDetail(scope.row)" icon="el-icon-view">详情</el-link>
<el-link v-if="scope.row.status == 0" size="mini" type="success" @click="auditWithdraw(scope.row, 1)" icon="el-icon-check">通过</el-link>
<el-link v-if="scope.row.status == 0" size="mini" type="danger" @click="auditWithdraw(scope.row, 2)" icon="el-icon-close">拒绝</el-link>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div style="padding: 20px; text-align: center;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="+pagination.total">
</el-pagination>
</div>
</div>
</div>
<style>
.stat-card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
transition: transform 0.3s ease;
}
.stat-card:hover {
transform: translateY(-5px);
}
.stat-icon {
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
}
.stat-icon i {
font-size: 24px;
color: white;
}
.stat-content {
flex: 1;
}
.stat-number {
font-size: 24px;
font-weight: bold;
color: #303133;
margin-bottom: 5px;
}
.stat-label {
font-size: 14px;
color: #909399;
}
.search-form .el-form-item {
margin-bottom: 0;
}
[v-cloak] {
display: none;
}
.el-date-editor .el-range__icon, .el-date-editor .el-range__close-icon {
line-height: 14px !important;
}
.el-date-editor .el-range-separator {
line-height: 16px !important;
width: 13% !important;
}
.el-input--prefix .el-input__inner {
padding-left: 30px !important;
}
</style>
<script>
new Vue({
el: '#RiderWithdrawManagement',
data() {
return {
loading: false,
withdrawList: [],
statistics: {
total_count: 0,
pending_count: 0,
approved_count: 0,
rejected_count: 0,
total_amount: '0.00',
approved_amount: '0.00'
},
searchForm: {
keyword: '',
status: '',
dateRange: []
},
pagination: {
page: 1,
pageSize: 20,
total: 0
},
}
},
mounted() {
this.loadWithdrawList();
this.loadStatistics();
},
methods: {
// 加载提现列表
loadWithdrawList() {
this.loading = true;
let params = {
page: this.pagination.page,
pageSize: this.pagination.pageSize,
keyword: this.searchForm.keyword,
status: this.searchForm.status
};
if (this.searchForm.dateRange && this.searchForm.dateRange.length === 2) {
params.start_time = this.searchForm.dateRange[0];
params.end_time = this.searchForm.dateRange[1];
}
$.get('/index.php/Retail/RiderWithdraw/getWithdrawList', params, (res) => {
this.loading = false;
if (res.code === 0) {
this.withdrawList = res.data.list;
this.pagination.total = res.data.total;
} else {
this.$message.error(res.msg);
}
});
},
// 加载统计数据
loadStatistics() {
let params = {};
if (this.searchForm.dateRange && this.searchForm.dateRange.length === 2) {
params.start_time = this.searchForm.dateRange[0];
params.end_time = this.searchForm.dateRange[1];
}
$.get('/index.php/Retail/RiderWithdraw/getWithdrawStats', params, (res) => {
if (res.code === 0) {
this.statistics = res.data;
}
});
},
// 搜索
searchWithdraw() {
this.pagination.page = 1;
this.loadWithdrawList();
this.loadStatistics();
},
// 重置搜索
resetSearch() {
this.searchForm = {
keyword: '',
status: '',
dateRange: []
};
this.pagination.page = 1;
this.loadWithdrawList();
this.loadStatistics();
},
// 查看详情
viewDetail(row) {
layer.open({
type: 2,
title: '提现详情',
content: '/index.php/Retail/RiderWithdraw/detail?id=' + row.id,
area: ['800px', '600px'],
offset: 'auto'
});
},
// 审核提现
auditWithdraw(row, status) {
const that = this;
if (status === 1) {
// 通过:直接询问确认
layer.confirm('确定要通过这个提现申请吗?', {
icon: 3,
title: '确认通过'
}, function(index) {
// 确认通过,直接调用接口
that.confirmAudit(row.id, status, '');
layer.close(index);
});
} else {
// 拒绝:弹出填写拒绝原因的弹窗
const url = '/index.php/Retail/RiderWithdraw/audit?id=' + row.id + '&status=' + status;
layer.open({
type: 2,
title: '拒绝提现申请',
content: url,
area: ['500px', '270px'],
offset: 'auto',
end: function() {
// 关闭弹窗时刷新列表
that.loadWithdrawList();
that.loadStatistics();
}
});
}
},
// 确认审核(新增方法)
confirmAudit(withdrawId, status, remark) {
$.post('/index.php/Retail/RiderWithdraw/auditWithdraw', {
id: withdrawId,
status: status,
remark: remark
}, (res) => {
if (res.code === 0) {
this.$message.success('操作成功');
this.loadWithdrawList();
this.loadStatistics();
} else {
this.$message.error(res.msg);
}
});
},
// 获取状态类型
getStatusType(status) {
const typeMap = {
0: 'warning',
1: 'success',
2: 'danger'
};
return typeMap[+status] || 'info';
},
// 获取提现方式名称
getWithdrawTypeName(type) {
const typeMap = {
1: '银行卡',
2: '支付宝',
3: '微信'
};
return typeMap[type] || '未知';
},
// 获取提现方式图标
getWithdrawTypeIcon(type) {
const iconMap = {
1: 'el-icon-bank-card',
2: 'el-icon-wallet',
3: 'el-icon-chat-dot-round'
};
return iconMap[type] || 'el-icon-question';
},
// 分页大小改变
handleSizeChange(val) {
this.pagination.pageSize = val;
this.pagination.page = 1;
this.loadWithdrawList();
},
// 当前页改变
handleCurrentChange(val) {
this.pagination.page = val;
this.loadWithdrawList();
}
}
});
</script>
</body>
</html>