|
|
@@ -0,0 +1,499 @@
|
|
|
+<template>
|
|
|
+ <div class="page-wrap">
|
|
|
+ <div class="crumbs">
|
|
|
+ <el-breadcrumb separator="/">
|
|
|
+ <i class="el-icon-eleme"></i> 新配送员管理
|
|
|
+ </el-breadcrumb>
|
|
|
+ </div>
|
|
|
+ <div class="background">
|
|
|
+ <div class="topbox">
|
|
|
+ <div class="topbox-left">
|
|
|
+ <span class="page-title">新配送员管理</span>
|
|
|
+ </div>
|
|
|
+ <div class="topbox-right">
|
|
|
+ <el-button type="primary" icon="el-icon-plus" size="mini" @click="openCreate">新增配送员</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="searchbox">
|
|
|
+ <span>姓名</span>
|
|
|
+ <el-input v-model="filters.name" size="small" style="width:150px" clearable placeholder="配送员姓名"></el-input>
|
|
|
+ <span>手机号</span>
|
|
|
+ <el-input v-model="filters.phone" size="small" style="width:150px" clearable placeholder="手机号"></el-input>
|
|
|
+ <span>类型</span>
|
|
|
+ <el-select v-model="filters.type" size="small" style="width:140px" clearable placeholder="配送员类型">
|
|
|
+ <el-option label="平台配送员" :value="1"></el-option>
|
|
|
+ <el-option label="商家配送员" :value="2"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span>状态</span>
|
|
|
+ <el-select v-model="filters.accountStatus" size="small" style="width:110px" clearable placeholder="账号状态">
|
|
|
+ <el-option label="正常" :value="1"></el-option>
|
|
|
+ <el-option label="冻结" :value="0"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span style="flex:1"></span>
|
|
|
+ <el-button type="primary" icon="el-icon-search" size="small" @click="search">查询</el-button>
|
|
|
+ <el-button size="small" @click="resetSearch">重置</el-button>
|
|
|
+ </div>
|
|
|
+ <div class="tablebox">
|
|
|
+ <dptable
|
|
|
+ :columns="columns"
|
|
|
+ :dataSource="tableData"
|
|
|
+ :options="options"
|
|
|
+ :fetch="getDataList"
|
|
|
+ :pagination="pagination"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="640px" :close-on-click-modal="false">
|
|
|
+ <el-form :model="form" label-width="120px">
|
|
|
+ <el-form-item label="配送员姓名" required>
|
|
|
+ <el-input v-model="form.name" maxlength="50" placeholder="请输入配送员姓名"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="手机号" required>
|
|
|
+ <el-input v-model="form.phone" maxlength="20" placeholder="请输入手机号" autocomplete="off"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="密码" :required="!form.id">
|
|
|
+ <el-input v-model="form.password" maxlength="128" :placeholder="form.id ? '不填写则不修改密码' : '请输入登录密码'" show-password autocomplete="new-password"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="配送员类型" required>
|
|
|
+ <el-radio-group v-model="form.type" @change="handleTypeChange">
|
|
|
+ <el-radio :label="1">平台配送员</el-radio>
|
|
|
+ <el-radio :label="2">商家配送员</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="form.type === 2" label="所属商家ID" required>
|
|
|
+ <el-select v-model="form.merchantId" filterable placeholder="请选择所属商家" style="width:100%">
|
|
|
+ <el-option
|
|
|
+ v-for="item in merchantList"
|
|
|
+ :key="getStoreId(item)"
|
|
|
+ :label="getStoreName(item)"
|
|
|
+ :value="getStoreId(item)"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="工作状态">
|
|
|
+ <el-radio-group v-model="form.workStatus">
|
|
|
+ <el-radio :label="1">可接单</el-radio>
|
|
|
+ <el-radio :label="0">暂停接单</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="账号状态">
|
|
|
+ <el-radio-group v-model="form.accountStatus">
|
|
|
+ <el-radio :label="1">正常</el-radio>
|
|
|
+ <el-radio :label="0">冻结</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <template v-if="form.type === 1">
|
|
|
+ <el-form-item label="平台权限">
|
|
|
+ <el-checkbox v-model="form.pickup" :true-label="1" :false-label="0">取餐</el-checkbox>
|
|
|
+ <el-checkbox v-model="form.delivery" :true-label="1" :false-label="0">配送</el-checkbox>
|
|
|
+ <el-checkbox v-model="form.climbStairs" :true-label="1" :false-label="0">爬楼</el-checkbox>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ <el-form-item v-if="form.type === 2" label="不能接单时间">
|
|
|
+ <el-time-picker v-model="form.noOrderStartTimeStr" value-format="HH:mm" format="HH:mm" placeholder="开始时间" style="width:140px" editable clearable></el-time-picker>
|
|
|
+ <span class="time-separator">至</span>
|
|
|
+ <el-time-picker v-model="form.noOrderEndTimeStr" value-format="HH:mm" format="HH:mm" placeholder="结束时间" style="width:140px" editable clearable></el-time-picker>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <span slot="footer">
|
|
|
+ <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" :loading="saving" @click="save">保存</el-button>
|
|
|
+ </span>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import dptable from '@/components/common/Dptable.vue'
|
|
|
+
|
|
|
+const baseUrl = '/deliveryRiderManage1'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'DeliveryerManage1',
|
|
|
+ components: { dptable },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ filters: this.createFilters(),
|
|
|
+ tableData: [],
|
|
|
+ pagination: {
|
|
|
+ resultCount: 0,
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 20
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ mutiSelect: false,
|
|
|
+ index: false,
|
|
|
+ initTable: true,
|
|
|
+ height: '520'
|
|
|
+ },
|
|
|
+ dialogVisible: false,
|
|
|
+ dialogTitle: '',
|
|
|
+ saving: false,
|
|
|
+ form: this.createForm(),
|
|
|
+ merchantList: [],
|
|
|
+ columns: [
|
|
|
+ { prop: 'name', label: '姓名', width: 140 },
|
|
|
+ { prop: 'phone', label: '手机号', width: 150 },
|
|
|
+ {
|
|
|
+ prop: 'type',
|
|
|
+ label: '类型',
|
|
|
+ width: 130,
|
|
|
+ formatter: row => row.type == 1 ? '平台配送员' : '商家配送员'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'workStatus',
|
|
|
+ label: '工作状态',
|
|
|
+ width: 110,
|
|
|
+ render: row => row.workStatus == 1
|
|
|
+ ? <el-tag size="small" type="success" style="cursor:pointer" onClick={() => this.updateWorkStatus(row)}>可接单</el-tag>
|
|
|
+ : <el-tag size="small" type="warning" style="cursor:pointer" onClick={() => this.updateWorkStatus(row)}>暂停接单</el-tag>
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'accountStatus',
|
|
|
+ label: '账号状态',
|
|
|
+ width: 100,
|
|
|
+ render: row => row.accountStatus == 1
|
|
|
+ ? <el-tag size="small" style="cursor:pointer" onClick={() => this.updateAccountStatus(row)}>正常</el-tag>
|
|
|
+ : <el-tag size="small" type="danger" style="cursor:pointer" onClick={() => this.updateAccountStatus(row)}>冻结</el-tag>
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'pickup',
|
|
|
+ label: '取餐',
|
|
|
+ width: 75,
|
|
|
+ switch: true,
|
|
|
+ switchHide: (value, row) => row.type == 2,
|
|
|
+ onChange: (value, row) => this.updatePermission(row, 'pickup', value)
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'delivery',
|
|
|
+ label: '配送',
|
|
|
+ width: 75,
|
|
|
+ switch: true,
|
|
|
+ switchHide: (value, row) => row.type == 2,
|
|
|
+ onChange: (value, row) => this.updatePermission(row, 'delivery', value)
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'climbStairs',
|
|
|
+ label: '爬楼',
|
|
|
+ width: 75,
|
|
|
+ switch: true,
|
|
|
+ switchHide: (value, row) => row.type == 2,
|
|
|
+ onChange: (value, row) => this.updatePermission(row, 'climbStairs', value)
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'noOrderStartTimeStr',
|
|
|
+ label: '不能接单时间',
|
|
|
+ width: 160,
|
|
|
+ formatter: row => row.type == 2 && row.noOrderStartTimeStr && row.noOrderEndTimeStr
|
|
|
+ ? row.noOrderStartTimeStr + ' - ' + row.noOrderEndTimeStr
|
|
|
+ : ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'createTime',
|
|
|
+ label: '创建时间',
|
|
|
+ width: 160,
|
|
|
+ formatter: row => row.createTime ? this.$moment(row.createTime).format('YYYY-MM-DD HH:mm:ss') : ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'updateTime',
|
|
|
+ label: '修改时间',
|
|
|
+ width: 160,
|
|
|
+ formatter: row => row.updateTime ? this.$moment(row.updateTime).format('YYYY-MM-DD HH:mm:ss') : ''
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '操作',
|
|
|
+ width: 220,
|
|
|
+ button: true,
|
|
|
+ group: [
|
|
|
+ {
|
|
|
+ name: '编辑',
|
|
|
+ type: 'primary',
|
|
|
+ plain: true,
|
|
|
+ buttonCode: 'edit',
|
|
|
+ onClick: row => this.openEdit(row)
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '删除',
|
|
|
+ type: 'danger',
|
|
|
+ plain: true,
|
|
|
+ buttonCode: 'delete',
|
|
|
+ onClick: row => this.deleteRider(row)
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ createFilters() {
|
|
|
+ return {
|
|
|
+ name: '',
|
|
|
+ phone: '',
|
|
|
+ type: '',
|
|
|
+ accountStatus: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ createForm() {
|
|
|
+ return {
|
|
|
+ id: '',
|
|
|
+ phone: '',
|
|
|
+ password: '',
|
|
|
+ name: '',
|
|
|
+ type: 1,
|
|
|
+ merchantId: '',
|
|
|
+ workStatus: 1,
|
|
|
+ accountStatus: 1,
|
|
|
+ pickup: 1,
|
|
|
+ delivery: 1,
|
|
|
+ climbStairs: 0,
|
|
|
+ noOrderStartTimeStr: '',
|
|
|
+ noOrderEndTimeStr: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ search() {
|
|
|
+ this.pagination.currentPage = 1
|
|
|
+ this.getDataList()
|
|
|
+ },
|
|
|
+ resetSearch() {
|
|
|
+ this.filters = this.createFilters()
|
|
|
+ this.search()
|
|
|
+ },
|
|
|
+ getDataList() {
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.options.loading = true
|
|
|
+ this.$axios.post(baseUrl + '/list', querystring.stringify({
|
|
|
+ name: this.filters.name,
|
|
|
+ phone: this.filters.phone,
|
|
|
+ type: this.filters.type,
|
|
|
+ accountStatus: this.filters.accountStatus,
|
|
|
+ pageSize: this.pagination.pageSize,
|
|
|
+ currentPage: this.pagination.currentPage
|
|
|
+ })).then(res => {
|
|
|
+ this.tableData = res.data.list || []
|
|
|
+ if (res.data.page) {
|
|
|
+ this.pagination.resultCount = res.data.page.resultCount
|
|
|
+ this.pagination.currentPage = res.data.page.currentPage
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.options.loading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ openCreate() {
|
|
|
+ this.dialogTitle = '新增配送员'
|
|
|
+ this.form = this.createForm()
|
|
|
+ this.getMerchantList()
|
|
|
+ this.dialogVisible = true
|
|
|
+ },
|
|
|
+ getMerchantList() {
|
|
|
+ if (this.merchantList.length > 0) return
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.$axios.post('/storeManage/getStoreList', querystring.stringify({})).then(res => {
|
|
|
+ this.merchantList = res.data.list || []
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getStoreId(item) {
|
|
|
+ return item.storeId || item.STORE_ID
|
|
|
+ },
|
|
|
+ getStoreName(item) {
|
|
|
+ return item.storeName || item.STORE_NAME || item.name || item.NAME
|
|
|
+ },
|
|
|
+ openEdit(row) {
|
|
|
+ this.dialogTitle = '编辑配送员'
|
|
|
+ this.form = Object.assign(this.createForm(), JSON.parse(JSON.stringify(row)))
|
|
|
+ this.getMerchantList()
|
|
|
+ this.form.password = ''
|
|
|
+ this.dialogVisible = true
|
|
|
+ },
|
|
|
+ handleTypeChange() {
|
|
|
+ if (this.form.type === 1) {
|
|
|
+ this.form.merchantId = ''
|
|
|
+ this.form.noOrderStartTimeStr = ''
|
|
|
+ this.form.noOrderEndTimeStr = ''
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.form.pickup = 0
|
|
|
+ this.form.delivery = 0
|
|
|
+ this.form.climbStairs = 0
|
|
|
+ },
|
|
|
+ updatePermission(row, field, value) {
|
|
|
+ if (field === 'pickup' && value == 1 && row.climbStairs == 1) {
|
|
|
+ this.$message.error('取餐权限和爬楼权限不能同时存在')
|
|
|
+ this.getDataList()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (field === 'climbStairs' && value == 1 && row.pickup == 1) {
|
|
|
+ this.$message.error('取餐权限和爬楼权限不能同时存在')
|
|
|
+ this.getDataList()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.$axios.post(baseUrl + '/updatePermission', querystring.stringify({
|
|
|
+ id: row.id,
|
|
|
+ field: field,
|
|
|
+ value: value
|
|
|
+ })).then(res => this.handleResult(res, true))
|
|
|
+ },
|
|
|
+ updateWorkStatus(row) {
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.$axios.post(baseUrl + '/updateWorkStatus', querystring.stringify({
|
|
|
+ id: row.id,
|
|
|
+ workStatus: row.workStatus == 1 ? 0 : 1
|
|
|
+ })).then(res => this.handleResult(res, true))
|
|
|
+ },
|
|
|
+ deleteRider(row) {
|
|
|
+ this.$confirm('确定要删除该配送员吗?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.$axios.post(baseUrl + '/delete', querystring.stringify({ id: row.id })).then(res => {
|
|
|
+ this.handleResult(res, true)
|
|
|
+ })
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
+ updateAccountStatus(row) {
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.$axios.post(baseUrl + '/updateAccountStatus', querystring.stringify({
|
|
|
+ id: row.id,
|
|
|
+ accountStatus: row.accountStatus == 1 ? 0 : 1
|
|
|
+ })).then(res => this.handleResult(res, true))
|
|
|
+ },
|
|
|
+ save() {
|
|
|
+ if (!this.validateForm()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const querystring = require('querystring')
|
|
|
+ this.saving = true
|
|
|
+ this.$axios.post(baseUrl + '/save', querystring.stringify(this.form)).then(res => {
|
|
|
+ if (this.handleResult(res, false)) {
|
|
|
+ this.dialogVisible = false
|
|
|
+ this.getDataList()
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.saving = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ validateForm() {
|
|
|
+ if (!this.form.name || !this.form.phone) {
|
|
|
+ this.$message.error('请填写姓名和手机号')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!this.form.id && !this.form.password) {
|
|
|
+ this.$message.error('新增配送员必须填写密码')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (!/^1\d{10}$/.test(this.form.phone)) {
|
|
|
+ this.$message.error('请输入正确的手机号')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.form.type === 2 && !this.form.merchantId) {
|
|
|
+ this.$message.error('商家配送员必须填写所属商家ID')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (this.form.type === 1 && this.form.pickup == 1 && this.form.climbStairs == 1) {
|
|
|
+ this.$message.error('取餐权限和爬楼权限不能同时存在')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ handleResult(res, refresh) {
|
|
|
+ if (res.data.rtnBean && res.data.rtnBean.rtnCode != 0) {
|
|
|
+ this.$message.error(res.data.rtnBean.rtnMsg)
|
|
|
+ if (refresh) this.getDataList()
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ this.$message.success('操作成功')
|
|
|
+ if (refresh) this.getDataList()
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.page-wrap{
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.crumbs{
|
|
|
+ color: #666;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+.background{
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ padding: 0 10px 10px;
|
|
|
+}
|
|
|
+.topbox{
|
|
|
+ background: white;
|
|
|
+ box-shadow: 0 12px 20px -8px rgba(22, 50, 62, 0.3);
|
|
|
+ border-radius: 10px;
|
|
|
+ min-height: 52px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 10px 16px;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+.topbox-left{ flex-shrink: 0; }
|
|
|
+.page-title{
|
|
|
+ font-size: 14px;
|
|
|
+ color: #409EFF;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+.topbox-right{
|
|
|
+ flex-shrink: 0;
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+.searchbox{
|
|
|
+ background: white;
|
|
|
+ box-shadow: 0 12px 20px -8px rgba(22, 50, 62, 0.3);
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 12px 16px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+.searchbox > span{ white-space: nowrap; }
|
|
|
+.tablebox{
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ background: white;
|
|
|
+ box-shadow: 0 12px 20px -8px rgba(22, 50, 62, 0.3);
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 16px;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.time-separator{ margin: 0 8px; color: #909399; }
|
|
|
+</style>
|
|
|
+<style>
|
|
|
+.tablebox .el-table{ width: 100% !important; table-layout: auto !important; }
|
|
|
+.tablebox .el-table__header-wrapper table,
|
|
|
+.tablebox .el-table__body-wrapper table{ width: 100% !important; }
|
|
|
+.tablebox th{
|
|
|
+ background: #409EFF !important;
|
|
|
+ color: #fff !important;
|
|
|
+ font-weight: 500 !important;
|
|
|
+ font-size: 13px !important;
|
|
|
+ padding: 10px 8px !important;
|
|
|
+ border: none !important;
|
|
|
+}
|
|
|
+.tablebox td{
|
|
|
+ padding: 8px !important;
|
|
|
+ font-size: 13px;
|
|
|
+ border-left: 1px solid #ebeef5 !important;
|
|
|
+}
|
|
|
+.tablebox td:first-child{ border-left: none !important; }
|
|
|
+.tablebox tr:hover td{ background: #f6faff; }
|
|
|
+</style>
|