465 行
21 KiB
HTML
465 行
21 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8"/>
|
||
<title>编辑骑手信息</title>
|
||
<link rel="stylesheet" type="text/css" href="__PUBLIC__/layui-v2.4.3/layui/css/layui.css"/>
|
||
<link rel="stylesheet" type="text/css" href="__PUBLIC__/vue/element-ui.css?v=2.13.2">
|
||
<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__/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>
|
||
<style>
|
||
body { margin: 0; padding: 20px; background: #f5f7fa; }
|
||
.form-section { margin-bottom: 20px; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); }
|
||
.form-section-title { font-size: 16px; font-weight: bold; color: #303133; margin-bottom: 15px; padding-left: 10px; border-left: 4px solid #409EFF; }
|
||
.el-form-item { margin-bottom: 18px; }
|
||
.el-input-number { width: 100%; }
|
||
.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: 178px; height: 178px; line-height: 178px; text-align: center; }
|
||
.avatar { width: 178px; height: 178px; display: block; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="RiderEditApp" v-cloak>
|
||
<el-form :model="riderForm" :rules="riderRules" ref="riderForm" label-width="120px">
|
||
<!-- 基本信息 -->
|
||
<div class="form-section">
|
||
<div class="form-section-title">基本信息</div>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="骑手姓名" prop="rider_name">
|
||
<el-input v-model="riderForm.rider_name" placeholder="请输入骑手姓名"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="手机号" prop="rider_phone">
|
||
<el-input v-model="riderForm.rider_phone" placeholder="请输入手机号"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="身份证号" prop="id_card">
|
||
<el-input v-model="riderForm.id_card" placeholder="请输入身份证号"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="工作状态" prop="work_status">
|
||
<el-select v-model="riderForm.work_status" placeholder="请选择工作状态" style="width: 100%">
|
||
<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-col>
|
||
</el-row>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="绑定店铺" prop="store_id">
|
||
<el-select v-model="riderForm.store_id" placeholder="请选择绑定店铺" style="width: 100%" filterable clearable>
|
||
<el-option label="不限制店铺(可接所有订单)" :value="0"></el-option>
|
||
<el-option
|
||
v-for="store in storeList"
|
||
:key="store.id"
|
||
:label="store.store_name"
|
||
:value="+store.id">
|
||
</el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="账户余额" prop="balance">
|
||
<el-input-number v-model="riderForm.balance" :precision="2" :step="0.01" :min="0" style="width: 100%">
|
||
<template slot="append">元</template>
|
||
</el-input-number>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="冻结金额" prop="frozen_balance">
|
||
<el-input-number v-model="riderForm.frozen_balance" :precision="2" :step="0.01" :min="0" style="width: 100%">
|
||
<template slot="append">元</template>
|
||
</el-input-number>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="评分" prop="rating">
|
||
<el-rate v-model="riderForm.rating" :max="5" show-score text-color="#ff9900" score-template="{value}分"></el-rate>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="准时率" prop="on_time_rate">
|
||
<el-input-number v-model="riderForm.on_time_rate" :precision="2" :step="0.01" :min="0" :max="100" style="width: 100%">
|
||
<template slot="append">%</template>
|
||
</el-input-number>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
|
||
<!-- 紧急联系人 -->
|
||
<div class="form-section">
|
||
<div class="form-section-title">紧急联系人</div>
|
||
<el-row :gutter="20">
|
||
<el-col :span="8">
|
||
<el-form-item label="联系人姓名" prop="emergency_name">
|
||
<el-input v-model="riderForm.emergency_name" placeholder="请输入联系人姓名"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="联系人电话" prop="emergency_phone">
|
||
<el-input v-model="riderForm.emergency_phone" placeholder="请输入联系人电话"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="关系" prop="emergency_relation">
|
||
<el-input v-model="riderForm.emergency_relation" placeholder="请输入关系"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
|
||
<!-- 认证信息 -->
|
||
<div class="form-section">
|
||
<div class="form-section-title">认证信息</div>
|
||
<el-row :gutter="20">
|
||
<el-col :span="8">
|
||
<el-form-item label="认证状态" prop="auth_status">
|
||
<el-select v-model="riderForm.auth_status" placeholder="请选择认证状态" style="width: 100%">
|
||
<el-option label="未认证" :value="'0'"></el-option>
|
||
<el-option label="待审核" :value="'1'"></el-option>
|
||
<el-option label="已认证" :value="'2'"></el-option>
|
||
<el-option label="认证失败" :value="'3'"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="健康证状态" prop="health_status">
|
||
<el-select v-model="riderForm.health_status" placeholder="请选择健康证状态" style="width: 100%">
|
||
<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-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="健康证过期时间" prop="health_cert_expire">
|
||
<el-date-picker v-model="riderForm.health_cert_expire" type="date" placeholder="选择日期" style="width: 100%"></el-date-picker>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="认证备注" prop="auth_remark">
|
||
<el-input v-model="riderForm.auth_remark" type="textarea" placeholder="请输入认证备注"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="健康证备注" prop="health_remark">
|
||
<el-input v-model="riderForm.health_remark" type="textarea" placeholder="请输入健康证备注"></el-input>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
|
||
<!-- 位置信息 -->
|
||
<div class="form-section">
|
||
<div class="form-section-title">位置信息</div>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="最后位置纬度" prop="last_location_lat">
|
||
<el-input-number v-model="riderForm.last_location_lat" :precision="6" :step="0.000001" :min="-90" :max="90" style="width: 100%"></el-input-number>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="最后位置经度" prop="last_location_lng">
|
||
<el-input-number v-model="riderForm.last_location_lng" :precision="6" :step="0.000001" :min="-180" :max="180" style="width: 100%"></el-input-number>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
|
||
<!-- 状态设置 -->
|
||
<div class="form-section">
|
||
<div class="form-section-title">状态设置</div>
|
||
<el-form-item label="账户状态" prop="status">
|
||
<el-radio-group v-model="riderForm.status">
|
||
<el-radio :label="'1'">启用</el-radio>
|
||
<el-radio :label="'0'">禁用</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
</div>
|
||
|
||
<!-- 操作按钮 -->
|
||
<div style="text-align: center; margin-top: 30px;">
|
||
<el-button @click="resetForm">重 置</el-button>
|
||
<el-button type="primary" @click="saveRider" :loading="saving">确 定</el-button>
|
||
</div>
|
||
</el-form>
|
||
</div>
|
||
|
||
<script>
|
||
new Vue({
|
||
el: '#RiderEditApp',
|
||
data() {
|
||
return {
|
||
saving: false,
|
||
storeList: [], // 店铺列表
|
||
riderForm: {
|
||
id: null,
|
||
merchant_id: 1,
|
||
store_id: 0,
|
||
rider_name: '',
|
||
rider_phone: '',
|
||
rider_avatar: '',
|
||
id_card: '',
|
||
id_card_front: '',
|
||
id_card_back: '',
|
||
health_cert: '',
|
||
health_cert_expire: '',
|
||
emergency_name: '',
|
||
emergency_phone: '',
|
||
emergency_relation: '',
|
||
work_status: '0',
|
||
auth_status: '2',
|
||
auth_remark: '',
|
||
health_status: '1',
|
||
health_remark: '',
|
||
balance: 0.00,
|
||
frozen_balance: 0.00,
|
||
rating: 5.00,
|
||
on_time_rate: 100.00,
|
||
last_location_lat: null,
|
||
last_location_lng: null,
|
||
status: '1'
|
||
},
|
||
riderRules: {
|
||
rider_name: [
|
||
{ required: true, message: '请输入骑手姓名', trigger: 'blur' },
|
||
{ min: 2, max: 50, message: '姓名长度在2到50个字符', trigger: 'blur' }
|
||
],
|
||
rider_phone: [
|
||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||
],
|
||
id_card: [
|
||
{ required: true, message: '请输入身份证号', trigger: 'blur' },
|
||
{ pattern: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/, message: '请输入正确的身份证号', trigger: 'blur' }
|
||
],
|
||
emergency_name: [
|
||
{ max: 50, message: '联系人姓名不能超过50个字符', trigger: 'blur' }
|
||
],
|
||
emergency_phone: [
|
||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的联系人电话', trigger: 'blur' }
|
||
],
|
||
emergency_relation: [
|
||
{ max: 20, message: '关系描述不能超过20个字符', trigger: 'blur' }
|
||
],
|
||
work_status: [
|
||
{ required: true, message: '请选择工作状态', trigger: 'change' }
|
||
],
|
||
auth_status: [
|
||
{ required: true, message: '请选择认证状态', trigger: 'change' }
|
||
],
|
||
health_status: [
|
||
{ required: true, message: '请选择健康证状态', trigger: 'change' }
|
||
],
|
||
auth_remark: [
|
||
{ max: 255, message: '认证备注不能超过255个字符', trigger: 'blur' }
|
||
],
|
||
health_remark: [
|
||
{ max: 255, message: '健康证备注不能超过255个字符', trigger: 'blur' }
|
||
],
|
||
balance: [
|
||
{ type: 'number', min: 0, message: '账户余额不能为负数', trigger: 'blur' }
|
||
],
|
||
frozen_balance: [
|
||
{ type: 'number', min: 0, message: '冻结金额不能为负数', trigger: 'blur' }
|
||
],
|
||
rating: [
|
||
{ required: true, message: '请设置评分', trigger: 'blur' },
|
||
{ type: 'number', min: 0, max: 5, message: '评分范围为0-5分', trigger: 'blur' }
|
||
],
|
||
on_time_rate: [
|
||
{ type: 'number', min: 0, max: 100, message: '准时率范围为0-100', trigger: 'blur' }
|
||
],
|
||
last_location_lat: [
|
||
{ type: 'number', min: -90, max: 90, message: '纬度范围为-90到90', trigger: 'blur' }
|
||
],
|
||
last_location_lng: [
|
||
{ type: 'number', min: -180, max: 180, message: '经度范围为-180到180', trigger: 'blur' }
|
||
],
|
||
status: [
|
||
{ required: true, message: '请选择账户状态', trigger: 'change' }
|
||
]
|
||
}
|
||
}
|
||
},
|
||
mounted() {
|
||
// 加载店铺列表
|
||
this.loadStoreList();
|
||
|
||
// 获取URL参数中的骑手ID
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const riderId = urlParams.get('id');
|
||
if (riderId) {
|
||
this.loadRiderData(riderId);
|
||
}
|
||
},
|
||
methods: {
|
||
async loadStoreList() {
|
||
try {
|
||
const response = await $.ajax({
|
||
url: '/Retail/Store/getStoreList',
|
||
type: 'POST',
|
||
data: { page: 1, limit: 1000 }, // 获取所有店铺
|
||
dataType: 'json'
|
||
});
|
||
|
||
if (response.status === 1) {
|
||
this.storeList = response.data || [];
|
||
} else {
|
||
console.error('获取店铺列表失败:', response.message);
|
||
}
|
||
} catch (error) {
|
||
console.error('获取店铺列表异常:', error);
|
||
}
|
||
},
|
||
|
||
async loadRiderData(id) {
|
||
try {
|
||
const response = await $.ajax({
|
||
url: '/Retail/Rider/getRiderInfo',
|
||
type: 'POST',
|
||
data: { id: id },
|
||
dataType: 'json'
|
||
});
|
||
|
||
if (response.code === 1) {
|
||
this.riderForm = Object.assign({}, this.riderForm, response.data, { store_id: +response.data.store_id || 0, rating: +response.data.rating || 0 });
|
||
} else {
|
||
this.$message.error(response.message || '获取骑手信息失败');
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('网络错误,请重试');
|
||
console.error('获取骑手信息异常:', error);
|
||
}
|
||
},
|
||
|
||
async saveRider() {
|
||
this.$refs.riderForm.validate(async (valid) => {
|
||
if (!valid) return;
|
||
|
||
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.refreshParentData();
|
||
// 延迟关闭弹窗,确保消息显示
|
||
setTimeout(() => {
|
||
if (parent && parent.layer) {
|
||
parent.layer.closeAll();
|
||
}
|
||
}, 1000);
|
||
} else {
|
||
this.$message.error(response.message || '保存失败');
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('网络错误,请重试');
|
||
console.error('保存骑手异常:', error);
|
||
} finally {
|
||
this.saving = false;
|
||
}
|
||
});
|
||
},
|
||
|
||
refreshParentData() {
|
||
try {
|
||
// 方法1:通过window.vm访问父窗口Vue实例
|
||
if (parent && parent.window && parent.window.vm) {
|
||
console.log('通过parent.window.vm刷新数据');
|
||
if (parent.window.vm.loadRiders) {
|
||
parent.window.vm.loadRiders();
|
||
}
|
||
if (parent.window.vm.loadStatistics) {
|
||
parent.window.vm.loadStatistics();
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 方法2:通过parent.vm访问(兼容性处理)
|
||
if (parent && parent.vm) {
|
||
console.log('通过parent.vm刷新数据');
|
||
if (parent.vm.loadRiders) {
|
||
parent.vm.loadRiders();
|
||
}
|
||
if (parent.vm.loadStatistics) {
|
||
parent.vm.loadStatistics();
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 方法3:通过postMessage通信(最后的兜底方案)
|
||
if (parent && parent !== window) {
|
||
console.log('通过postMessage刷新数据');
|
||
parent.postMessage({ action: 'refreshRiderData' }, '*');
|
||
return;
|
||
}
|
||
|
||
console.log('无法找到父窗口,刷新失败');
|
||
} catch (error) {
|
||
console.error('刷新父窗口数据失败:', error);
|
||
}
|
||
},
|
||
|
||
resetForm() {
|
||
this.$refs.riderForm.resetFields();
|
||
// 重置为默认值
|
||
this.riderForm = {
|
||
id: null,
|
||
merchant_id: 0,
|
||
store_id: 0,
|
||
rider_name: '',
|
||
rider_phone: '',
|
||
rider_avatar: '',
|
||
id_card: '',
|
||
id_card_front: '',
|
||
id_card_back: '',
|
||
health_cert: '',
|
||
health_cert_expire: '',
|
||
emergency_name: '',
|
||
emergency_phone: '',
|
||
emergency_relation: '',
|
||
work_status: 0,
|
||
auth_status: 0,
|
||
auth_remark: '',
|
||
health_status: 0,
|
||
health_remark: '',
|
||
balance: 0.00,
|
||
frozen_balance: 0.00,
|
||
rating: 5.00,
|
||
on_time_rate: 100.00,
|
||
last_location_lat: null,
|
||
last_location_lng: null,
|
||
status: 1
|
||
};
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |