文件

1223 行
35 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="RiderManagement" v-cloak>
<div class="goodsBox">
<div class="goods_title">
<div class="goods_title_inner">
<i class="fas fa-motorcycle" style="margin-right: 8px; color: #409EFF;"></i>
骑手管理
</div>
</div>
</div>
<!-- 统计卡片区域 -->
<div class="rider-stats-container" style="padding: 20px; background: #f5f7fa;">
<el-row :gutter="20">
<el-col :span="6">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<i class="fas fa-users"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.totalRiders }}</div>
<div class="stat-label">总骑手数</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
<i class="fas fa-user-check"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.onlineRiders }}</div>
<div class="stat-label">在线骑手</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
<i class="fas fa-clipboard-list"></i>
</div>
<div class="stat-content">
<div class="stat-number">{{ statistics.todayOrders }}</div>
<div class="stat-label">今日订单</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
<i class="fas fa-dollar-sign"></i>
</div>
<div class="stat-content">
<div class="stat-number">¥{{ statistics.todayRevenue }}</div>
<div class="stat-label">今日收入</div>
</div>
</div>
</el-col>
</el-row>
</div>
<!-- 主要内容区域 -->
<div style="padding: 20px; background: white; margin: 20px; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);">
<!-- 工具栏 -->
<div class="toolbar" style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;">
<div class="toolbar-left">
<el-input
v-model="searchKeyword"
placeholder="搜索骑手姓名或手机号"
prefix-icon="el-icon-search"
style="width: 300px; margin-right: 15px;"
@input="handleSearch">
</el-input>
<el-select v-model="statusFilter" placeholder="状态筛选" style="width: 120px; margin-right: 15px;" @change="handleFilter">
<el-option label="全部状态" value=""></el-option>
<el-option label="在线" value="1"></el-option>
<el-option label="离线" value="0"></el-option>
<el-option label="忙碌" value="2"></el-option>
</el-select>
<el-select v-model="certificationFilter" placeholder="认证状态" style="width: 120px; margin-right: 15px;" @change="handleFilter">
<el-option label="全部认证" value=""></el-option>
<el-option label="认证失败" value="3"></el-option>
<el-option label="已认证" value="2"></el-option>
<el-option label="未认证" value="0"></el-option>
<el-option label="待审核" value="1"></el-option>
</el-select>
<el-select v-model="storeFilter" placeholder="店铺筛选" style="width: 150px; margin-right: 15px;" clearable filterable @change="handleFilter">
<el-option label="全部店铺" value=""></el-option>
<el-option label="不限制店铺" value="0"></el-option>
<el-option
v-for="store in storeList"
:key="store.id"
:label="store.name"
:value="store.id.toString()">
</el-option>
</el-select>
</div>
<div class="toolbar-right">
<el-button type="primary" icon="el-icon-plus" @click="showAddRiderDialog">添加骑手</el-button>
<el-button type="success" icon="el-icon-refresh" @click="refreshData">刷新</el-button>
</div>
</div>
<!-- 骑手列表表格 -->
<el-table
:data="riders"
v-loading="loading"
element-loading-text="加载中..."
style="width: 100%"
:header-cell-style="{background:'#f5f7fa',color:'#606266'}"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="头像" width="80" align="center">
<template slot-scope="scope">
<el-avatar :size="40" :src="scope.row.rider_avatar" icon="el-icon-user-solid"></el-avatar>
</template>
</el-table-column>
<el-table-column prop="rider_name" label="姓名" width="120"></el-table-column>
<el-table-column prop="rider_phone" label="手机号" width="130"></el-table-column>
<el-table-column label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="getStatusTagType(scope.row.work_status)" size="small">
{{ getStatusText(scope.row.work_status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="认证状态" width="120" align="center">
<template slot-scope="scope">
<el-tag :type="getCertificationTagType(scope.row.auth_status)" size="small">
{{ getCertificationText(scope.row.auth_status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="绑定店铺" width="150" align="center">
<template slot-scope="scope">
<span v-if="scope.row.store_id && scope.row.store_id > 0" style="color: #409EFF;">
{{ scope.row.store_name || '店铺ID:' + scope.row.store_id }}
</span>
<span v-else style="color: #909399;">不限制</span>
</template>
</el-table-column>
<el-table-column prop="today_orders" label="今日订单" width="100" align="center"></el-table-column>
<el-table-column label="今日收入" width="120" align="center">
<template slot-scope="scope">
<span style="color: #67C23A; font-weight: bold;">¥{{ scope.row.today_income }}</span>
</template>
</el-table-column>
<el-table-column prop="rating" label="评分" width="150" align="center">
<template slot-scope="scope">
<el-rate v-model="+scope.row.rating" disabled text-color="#ff9900"></el-rate>
</template>
</el-table-column>
<el-table-column label="注册时间" width="120">
<template slot-scope="scope">
{{ formatDate(scope.row.add_time) }}
</template>
</el-table-column>
<el-table-column label="操作" width="320" align="center" fixed="right">
<template slot-scope="scope">
<el-link icon="el-icon-view" @click="viewRiderDetail(scope.row)">详情</el-link>
<el-link icon="el-icon-edit" @click="editRider(scope.row)">编辑</el-link>
<el-link icon="el-icon-check" @click="openAuthReviewDialog(scope.row)">认证</el-link>
<el-link icon="el-icon-key" @click="resetPassword(scope.row)">重置密码</el-link>
<el-link icon="el-icon-delete" @click="deleteRider(scope.row)">删除</el-link>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div style="margin-top: 20px; text-align: center;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="+totalCount">
</el-pagination>
</div>
</div>
<!-- 添加/编辑骑手对话框 -->
</div>
<style>
/* 表单分组样式 */
.form-section {
margin-bottom: 30px;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #409EFF;
}
.section-title {
margin: 0 0 20px 0;
font-size: 16px;
font-weight: 600;
color: #303133;
display: flex;
align-items: center;
}
.section-title::before {
content: '';
width: 4px;
height: 16px;
background: #409EFF;
margin-right: 8px;
border-radius: 2px;
}
.el-form-item {
margin-bottom: 18px;
}
.el-input-number {
width: 100%;
}
/* 统计卡片样式 */
.stat-card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
}
.stat-icon {
width: 60px;
height: 60px;
border-radius: 12px;
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: 28px;
font-weight: bold;
color: #2c3e50;
line-height: 1;
}
.stat-label {
font-size: 14px;
color: #7f8c8d;
margin-top: 5px;
}
/* 头像上传样式 */
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
display: block;
}
/* 骑手详情样式 */
.detail-avatar {
text-align: center;
padding: 20px;
}
.detail-avatar h3 {
margin: 15px 0 10px 0;
color: #2c3e50;
}
.detail-info {
padding: 20px;
}
/* 骑手详情对话框样式 */
.rider-detail-dialog .el-dialog {
border-radius: 16px;
overflow: hidden;
}
.rider-detail-dialog .el-dialog__header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px 24px;
margin: 0;
}
.rider-detail-dialog .el-dialog__title {
color: white;
font-size: 18px;
font-weight: 600;
}
.rider-detail-dialog .el-dialog__headerbtn .el-dialog__close {
color: white;
font-size: 20px;
}
.rider-detail-dialog .el-dialog__body {
padding: 0;
background: #f8fafc;
}
.rider-detail-container {
padding: 24px;
max-height: 70vh;
overflow-y: auto;
}
/* 头部信息卡片 */
.rider-header-card {
background: white;
border-radius: 16px;
padding: 24px;
margin-bottom: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
display: flex;
align-items: center;
gap: 24px;
position: relative;
overflow: hidden;
}
.rider-header-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
}
.rider-avatar-section {
flex-shrink: 0;
}
.avatar-wrapper {
position: relative;
display: inline-block;
}
.rider-avatar {
border: 4px solid #fff;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
transition: transform 0.3s ease;
}
.rider-avatar:hover {
transform: scale(1.05);
}
.avatar-status {
position: absolute;
bottom: -5px;
right: -5px;
background: white;
border-radius: 20px;
padding: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.rider-basic-info {
flex: 1;
}
.rider-name {
margin: 0 0 16px 0;
font-size: 24px;
font-weight: 700;
color: #2c3e50;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.rider-meta {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 16px;
}
.meta-item {
display: flex;
align-items: center;
gap: 8px;
color: #64748b;
font-size: 14px;
}
.meta-item i {
color: #667eea;
width: 16px;
}
.certification-status .el-tag {
border-radius: 20px;
font-weight: 500;
}
.certification-status .el-tag i {
margin-right: 4px;
}
/* 统计数据卡片 */
.rider-stats-section {
margin-bottom: 20px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 3px;
}
.stat-item {
background: white;
border-radius: 12px;
padding: 20px;
display: flex;
align-items: center;
gap: 16px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
border: 1px solid #e2e8f0;
}
.stat-item:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
.stat-item .stat-icon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 20px;
}
.stat-item .stat-icon.today-orders {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.stat-item .stat-icon.today-income {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.stat-item .stat-icon.total-orders {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.stat-item .stat-icon.total-income {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
.stat-item .stat-content {
flex: 1;
}
.stat-item .stat-number {
font-size: 20px;
font-weight: 700;
color: #2c3e50;
line-height: 1.2;
}
.stat-item .stat-label {
font-size: 13px;
color: #64748b;
margin-top: 4px;
}
/* 健康证信息卡片 */
.health-cert-section {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
border: 1px solid #e2e8f0;
}
.section-title {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
font-size: 16px;
font-weight: 600;
color: #2c3e50;
}
.section-title i {
color: #667eea;
font-size: 18px;
}
.health-cert-content {
display: flex;
align-items: center;
gap: 20px;
}
.cert-image {
flex-shrink: 0;
}
.no-cert {
width: 200px;
height: 120px;
border: 2px dashed #cbd5e1;
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #94a3b8;
background: #f8fafc;
}
.no-cert i {
font-size: 32px;
margin-bottom: 8px;
}
.cert-info {
flex: 1;
}
.cert-expire {
display: flex;
align-items: center;
gap: 8px;
}
.cert-expire label {
font-weight: 500;
color: #475569;
}
.expire-date {
color: #059669;
font-weight: 600;
background: #d1fae5;
padding: 4px 12px;
border-radius: 16px;
font-size: 14px;
}
.no-expire {
color: #dc2626;
font-weight: 500;
background: #fee2e2;
padding: 4px 12px;
border-radius: 16px;
font-size: 14px;
}
/* 评分信息 */
.rating-section {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
border: 1px solid #e2e8f0;
}
.rating-content {
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
background: #fef3c7;
border-radius: 8px;
border: 1px solid #fbbf24;
}
/* 响应式设计 */
@media (max-width: 768px) {
.rider-stats-container .el-col {
margin-bottom: 15px;
}
.toolbar {
flex-direction: column;
gap: 15px;
}
.toolbar-left, .toolbar-right {
width: 100%;
display: flex;
flex-wrap: wrap;
gap: 10px;
}
/* 骑手详情对话框移动端适配 */
.rider-detail-dialog .el-dialog {
width: 95% !important;
margin: 0 auto;
}
.rider-detail-container {
padding: 16px;
max-height: 80vh;
}
.rider-header-card {
flex-direction: column;
text-align: center;
gap: 16px;
padding: 20px;
}
.rider-name {
font-size: 20px;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.stat-item {
padding: 16px;
flex-direction: column;
text-align: center;
gap: 8px;
}
.stat-item .stat-icon {
width: 40px;
height: 40px;
font-size: 18px;
}
.stat-item .stat-number {
font-size: 18px;
}
.health-cert-content {
flex-direction: column;
align-items: center;
gap: 16px;
}
.cert-image {
width: 100%;
display: flex;
justify-content: center;
}
.no-cert {
width: 100%;
max-width: 200px;
}
.cert-info {
text-align: center;
}
}
@media (max-width: 480px) {
.rider-detail-dialog .el-dialog {
width: 98% !important;
}
.rider-detail-container {
padding: 12px;
}
.rider-header-card {
padding: 16px;
}
.stats-grid {
grid-template-columns: 1fr;
}
.stat-item .stat-number {
font-size: 16px;
}
.stat-item .stat-label {
font-size: 12px;
}
.section-title {
font-size: 14px;
}
.health-cert-section,
.rating-section {
padding: 16px;
}
}
</style>
<script>
new Vue({
el: '#RiderManagement',
data() {
return {
loading: false,
saving: false,
searchKeyword: '',
statusFilter: '',
certificationFilter: '',
storeFilter: '', // 店铺筛选
storeList: [], // 店铺列表
currentPage: 1,
pageSize: 20,
totalCount: 0,
selectedRiders: [],
selectedRider: null,
// 统计数据
statistics: {
totalRiders: 0,
onlineRiders: 0,
todayOrders: 0,
todayRevenue: '0'
},
// 骑手列表数据
riders: []
};
},
computed: {
filteredRiders() {
let result = this.riders;
// 关键词搜索
if (this.searchKeyword) {
result = result.filter(rider =>
rider.rider_name.includes(this.searchKeyword) ||
rider.rider_phone.includes(this.searchKeyword)
);
}
// 状态筛选
if (this.statusFilter) {
result = result.filter(rider => rider.work_status == this.statusFilter);
}
// 认证状态筛选
if (this.certificationFilter) {
result = result.filter(rider => rider.auth_status == this.certificationFilter);
}
this.totalCount = result.length;
return result;
},
totalPages() {
return Math.ceil(this.totalCount / this.pageSize);
}
},
methods: {
// API接口方法
async loadStatistics() {
try {
const response = await $.ajax({
url: '/Retail/Rider/getStatistics',
type: 'GET',
dataType: 'json'
});
if (response.code === 1) {
this.statistics = response.data;
} else {
console.error('获取统计数据失败:', response.message);
}
} catch (error) {
console.error('获取统计数据异常:', error);
}
},
async loadRiders() {
this.loading = true;
try {
const response = await $.ajax({
url: '/Retail/Rider/getRiderList',
type: 'GET',
data: {
page: this.currentPage,
limit: this.pageSize,
keyword: this.searchKeyword,
status: this.statusFilter,
certification: this.certificationFilter,
store_id: this.storeFilter // 添加店铺筛选参数
},
dataType: 'json'
});
if (response.code === 1) {
this.riders = response.data.list || [];
this.totalCount = response.data.total || 0;
} else {
this.$message.error(response.message || '获取骑手列表失败');
}
} catch (error) {
this.$message.error('网络错误,请重试');
console.error('获取骑手列表异常:', error);
} finally {
this.loading = false;
}
},
async loadStoreList() {
try {
const response = await $.ajax({
url: '/Retail/Store/getStoreList',
type: 'POST',
data: { page: 1, limit: 1000 }, // 获取所有店铺
dataType: 'json'
});
if (response.code === 1) {
this.storeList = response.data.list || [];
} else {
console.error('获取店铺列表失败:', response.message);
}
} catch (error) {
console.error('获取店铺列表异常:', error);
}
},
async saveRiderData() {
this.saving = true;
try {
const url = this.riderForm.id ? '/Retail/Rider/updateRider' : '/Retail/Rider/addRider';
const response = await $.ajax({
url: url,
type: 'POST',
data: this.riderForm,
dataType: 'json'
});
if (response.code === 1) {
this.$message.success(this.riderForm.id ? '更新成功' : '添加成功');
this.showRiderDialog = false;
this.loadRiders();
this.loadStatistics();
} else {
this.$message.error(response.message || '保存失败');
}
} catch (error) {
this.$message.error('网络错误,请重试');
console.error('保存骑手异常:', error);
} finally {
this.saving = false;
}
},
async deleteRiderData(riderId) {
try {
const response = await $.ajax({
url: '/Retail/Rider/deleteRider',
type: 'POST',
data: { id: riderId },
dataType: 'json'
});
if (response.code === 1) {
this.$message.success('删除成功');
this.loadRiders();
this.loadStatistics();
} else {
this.$message.error(response.message || '删除失败');
}
} catch (error) {
this.$message.error('网络错误,请重试');
console.error('删除骑手异常:', error);
}
},
async getRiderDetail(riderId) {
try {
const response = await $.ajax({
url: '/Retail/Rider/getRiderDetail',
type: 'GET',
data: { id: riderId },
dataType: 'json'
});
if (response.code === 1) {
return response.data;
} else {
this.$message.error(response.message || '获取详情失败');
return null;
}
} catch (error) {
this.$message.error('网络错误,请重试');
console.error('获取骑手详情异常:', error);
return null;
}
},
async updateAuthStatus(riderId, authStatus, remark) {
this.saving = true;
try {
const response = await $.ajax({
url: '/Retail/Rider/updateAuthStatus',
type: 'POST',
data: {
id: riderId,
auth_status: authStatus,
auth_remark: remark
},
dataType: 'json'
});
if (response.code === 1) {
this.$message.success('认证状态更新成功');
this.showAuthReviewDialog = false;
this.loadRiders();
} else {
this.$message.error(response.message || '更新失败');
}
} catch (error) {
this.$message.error('网络错误,请重试');
console.error('更新认证状态异常:', error);
} finally {
this.saving = false;
}
},
async exportRiderData() {
try {
this.$message.info('正在导出数据...');
const response = await $.ajax({
url: '/Retail/Rider/exportRiders',
type: 'GET',
data: {
keyword: this.searchKeyword,
status: this.statusFilter,
certification: this.certificationFilter
},
dataType: 'json'
});
if (response.code === 1 && response.data.url) {
// 创建下载链接
const link = document.createElement('a');
link.href = response.data.url;
link.download = response.data.filename || '骑手数据.xlsx';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('导出成功');
} else {
this.$message.error(response.message || '导出失败');
}
} catch (error) {
this.$message.error('网络错误,请重试');
console.error('导出数据异常:', error);
}
},
// 状态相关方法
getStatusTagType(status) {
const types = {
'1': 'success', // 在线
'0': 'info', // 离线
'2': 'warning' // 忙碌
};
return types[status] || 'info';
},
getStatusText(status) {
const texts = {
'1': '在线',
'0': '离线',
'2': '忙碌'
};
return texts[status] || '未知';
},
getCertificationTagType(certification) {
const types = {
'2': 'success',
'0': 'danger',
'3': 'danger',
'1': 'warning'
};
return types[certification] || 'info';
},
getCertificationText(certification) {
const texts = {
'2': '已认证',
'0': '未认证',
'1': '待审核',
'3': '认证失败'
};
return texts[certification] || '未知';
},
// 格式化日期
formatDate(date) {
if (!date) return '';
return new Date(date).toLocaleDateString();
},
// 搜索和筛选
handleSearch() {
this.currentPage = 1;
this.loadRiders();
},
handleFilter() {
this.currentPage = 1;
this.loadRiders();
},
// 分页
handleSizeChange(val) {
this.pageSize = val;
this.currentPage = 1;
this.loadRiders();
},
handleCurrentChange(val) {
this.currentPage = val;
this.loadRiders();
},
// 选择
handleSelectionChange(val) {
this.selectedRiders = val;
},
// 骑手操作
showAddRiderDialog() {
layer.open({
type: 2,
title: '添加骑手',
content: '/Retail/Rider/edit.html',
area: ['calc(100% - 240px)', 'calc(100% - 66px)'],
offset: 'rb'
});
},
editRider(rider) {
layer.open({
type: 2,
title: '编辑骑手',
content: '/Retail/Rider/edit.html?id=' + rider.id,
area: ['calc(100% - 240px)', 'calc(100% - 66px)'],
offset: 'rb'
});
},
async viewRiderDetail(rider) {
layer.open({
type: 2,
title: '骑手详情',
content: '/Retail/Rider/detail.html?id=' + rider.id,
area: ['calc(100% - 240px)', 'calc(100% - 66px)'],
offset: 'rb'
});
},
deleteRider(rider) {
this.$confirm('确定要删除骑手 ' + rider.rider_name + ' 吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.deleteRiderData(rider.id);
}).catch(() => {
this.$message.info('已取消删除');
});
},
// 头像上传
handleAvatarSuccess(res, file) {
if (res.code === 1) {
this.riderForm.avatar = res.data.url;
this.$message.success('头像上传成功');
} else {
this.$message.error(res.message || '上传失败');
}
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG/PNG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
// 重置密码
resetPassword(rider) {
layer.open({
type: 2,
title: '重置密码',
content: '/Retail/Rider/password_reset.html?id=' + rider.id,
area: ['calc(100% - 240px)', 'calc(100% - 66px)'],
offset: 'rb'
});
},
// 实名认证
openAuthReviewDialog(rider) {
layer.open({
type: 2,
title: '实名认证审核',
content: '/Retail/Rider/auth_review.html?id=' + rider.id,
area: ['calc(100% - 240px)', 'calc(100% - 66px)'],
offset: 'rb'
});
},
refreshData() {
this.loadStatistics();
this.loadRiders();
}
},
mounted() {
this.loadStoreList(); // 加载店铺列表
this.refreshData();
// 将Vue实例挂载到window对象,供子窗口调用
window.vm = this;
// 监听来自子窗口的消息
window.addEventListener('message', (event) => {
if (event.data && event.data.action === 'refreshRiderData') {
console.log('收到子窗口刷新请求');
this.refreshData();
}
});
}
});
</script>
</body>
</html>