Sfoglia il codice sorgente

add delivery rider management page

admin 1 mese fa
parent
commit
5540eee5ef

+ 4 - 0
src/components/page/admin/Left.vue

@@ -181,6 +181,10 @@
                                 index: '/delivery/deliveryerManage',
                                 title: '配送员管理',
                             },
+                            {
+                                index: '/delivery/deliveryerManage1',
+                                title: '新配送员管理',
+                            },
                             {
                                 index: '/delivery/deliveryAreaManage',
                                 title: '配送区域管理',

+ 499 - 0
src/components/page/admin/delivery/DeliveryerManage1.vue

@@ -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>

+ 8 - 0
src/router/index.js

@@ -204,6 +204,14 @@ export default new Router({
                         ], resolve),
                     meta: { titile: "配送员管理" }
                 },
+                {
+                  path: "/delivery/deliveryerManage1",
+                  component: resolve =>
+                        require([
+                            "@/components/page/admin/delivery/DeliveryerManage1.vue"
+                        ], resolve),
+                    meta: { titile: "新配送员管理" }
+                },
                 {
                   path: "/delivery/deliveryAreaManage",
                   component: resolve =>