RiderList.vue 8.71 KB
<template>
  <div>
    <a-card title="骑手管理" :bordered="false">
      <template #extra>
        <a-space>
          <a-select v-model:value="filterStatus" placeholder="审核状态" allowClear style="width:120px" @change="loadList">
            <a-select-option :value="2">待审核</a-select-option>
            <a-select-option :value="1">已通过</a-select-option>
            <a-select-option :value="0">已拒绝</a-select-option>
          </a-select>
          <a-input-search v-model:value="keyword" placeholder="搜索姓名/手机" @search="loadList" style="width:200px" />
          <a-button type="primary" @click="openAdd">新增骑手</a-button>
        </a-space>
      </template>
      <a-table :dataSource="list" :columns="columns" :loading="loading" rowKey="id" :pagination="false">
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'userStatus'">
            <a-tag :color="record.userStatus === 1 ? 'green' : record.userStatus === 0 ? 'red' : 'orange'">
              {{ statusMap[record.userStatus] }}
            </a-tag>
          </template>
          <template v-if="column.key === 'levelName'">
            {{ record.levelName || '默认等级' }}
          </template>
          <template v-if="column.key === 'accountStatus'">
            <a-tag :color="getAccountStatus(record) === 1 ? 'green' : 'red'">
              {{ getAccountStatus(record) === 1 ? '正常' : '禁用' }}
            </a-tag>
          </template>
          <template v-if="column.key === 'workStatus'">
            <a-tag :color="getWorkStatus(record) === 0 ? 'green' : 'orange'">
              {{ getWorkStatus(record) === 0 ? '在线' : '休息' }}
            </a-tag>
          </template>
          <template v-if="column.key === 'type'">
            <a-tag>{{ record.type === 1 ? '兼职' : '全职' }}</a-tag>
          </template>
          <template v-if="column.key === 'action'">
            <a-space>
              <a @click="openSetLevel(record)">设置等级</a>
              <template v-if="record.userStatus === 2">
                <a-popconfirm title="确认通过审核?" @confirm="setStatus(record.id, 1)">
                  <a style="color:green">通过</a>
                </a-popconfirm>
                <a-popconfirm title="确认拒绝?" @confirm="setStatus(record.id, 0)">
                  <a style="color:red">拒绝</a>
                </a-popconfirm>
              </template>
              <template v-else>
                <a-popconfirm
                  :title="getAccountStatus(record) === 1 ? '确认禁用该骑手?' : '确认启用该骑手?'"
                  @confirm="setEnableStatus(record.id, getAccountStatus(record) === 1 ? 0 : 1)">
                  <a :style="getAccountStatus(record) === 1 ? 'color:red' : ''">
                    {{ getAccountStatus(record) === 1 ? '禁用' : '启用' }}
                  </a>
                </a-popconfirm>
                <a-popconfirm
                  :title="record.type === 1 ? '切换为全职?' : '切换为兼职?'"
                  @confirm="setType(record.id, record.type === 1 ? 2 : 1)">
                  <a>切换{{ record.type === 1 ? '全职' : '兼职' }}</a>
                </a-popconfirm>
              </template>
            </a-space>
          </template>
        </template>
      </a-table>
    </a-card>

    <a-modal v-model:open="modalVisible" title="新增骑手" @ok="handleAdd" :confirmLoading="saving">
      <a-form :model="form" layout="vertical">
        <a-form-item v-if="isAdmin" label="租户">
          <a-select v-model:value="form.cityId" placeholder="选择租户">
            <a-select-option v-for="c in cityList" :key="c.id" :value="c.id">{{ c.name }}</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="昵称">
          <a-input v-model:value="form.userNickname" placeholder="请输入骑手昵称" />
        </a-form-item>
        <a-form-item label="手机号">
          <a-input v-model:value="form.mobile" placeholder="请输入手机号" />
        </a-form-item>
        <a-form-item label="密码">
          <a-input-password v-model:value="form.password" placeholder="请输入登录密码" />
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="levelVisible" title="设置骑手等级" @ok="handleSetLevel" :confirmLoading="levelSaving">
      <a-form layout="vertical">
        <a-form-item label="骑手">
          <a-input :value="levelTargetName" disabled />
        </a-form-item>
        <a-form-item label="等级">
          <a-select v-model:value="selectedLevelId" placeholder="请选择等级">
            <a-select-option :value="0">使用默认等级</a-select-option>
            <a-select-option v-for="item in levelOptions" :key="item.id" :value="item.id">
              {{ item.name }}{{ item.isDefault === 1 ? '(默认)' : '' }}
            </a-select-option>
          </a-select>
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { computed, reactive, ref, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import { cityApi, riderApi, riderLevelApi } from '@/api'
import { useAuthStore } from '@/stores/auth'

const auth = useAuthStore()
const loading = ref(false)
const saving = ref(false)
const list = ref<any[]>([])
const cityList = ref<any[]>([])
const levelOptions = ref<any[]>([])
const filterStatus = ref<number | undefined>()
const keyword = ref('')
const modalVisible = ref(false)
const levelVisible = ref(false)
const form = reactive({
  cityId: undefined as number | undefined,
  userNickname: '',
  mobile: '',
  password: '',
})
const levelSaving = ref(false)
const levelTargetId = ref<number>(0)
const levelTargetName = ref('')
const selectedLevelId = ref<number>(0)
const isAdmin = computed(() => auth.userInfo?.role === 'admin')

const statusMap: Record<number, string> = { 0: '已拒绝', 1: '已通过', 2: '待审核' }

const columns = [
  { title: 'ID', dataIndex: 'id', width: 80 },
  { title: '昵称', dataIndex: 'userNickname' },
  { title: '手机', dataIndex: 'mobile' },
  { title: '租户ID', dataIndex: 'cityId' },
  { title: '等级', key: 'levelName' },
  { title: '类型', key: 'type' },
  { title: '审核状态', key: 'userStatus' },
  { title: '账号状态', key: 'accountStatus' },
  { title: '骑手状态', key: 'workStatus' },
  { title: '余额', dataIndex: 'balance' },
  { title: '操作', key: 'action' },
]

function getAccountStatus(record: any) {
  return record.status === 0 ? 0 : 1
}

function getWorkStatus(record: any) {
  return record.isRest === 1 ? 1 : 0
}

async function loadList() {
  loading.value = true
  try {
    const res: any = await riderApi.list({
      keyword: keyword.value,
      userStatus: filterStatus.value,
    }).catch(() => ({ data: [] }))
    list.value = Array.isArray(res?.data) ? res.data : []
  } finally { loading.value = false }
}

async function loadCities() {
  const res: any = await cityApi.openList()
  cityList.value = Array.isArray(res?.data) ? res.data : []
}

function openAdd() {
  Object.assign(form, {
    cityId: undefined,
    userNickname: '',
    mobile: '',
    password: '',
  })
  modalVisible.value = true
}

async function handleAdd() {
  if (!form.userNickname || !form.mobile || !form.password) {
    message.error('请填写完整骑手信息')
    return
  }
  if (isAdmin.value && !form.cityId) {
    message.error('请选择租户')
    return
  }

  saving.value = true
  try {
    await riderApi.add({ ...form })
    message.success('新增成功')
    modalVisible.value = false
    loadList()
  } finally {
    saving.value = false
  }
}

async function openSetLevel(record: any) {
  const res: any = await riderLevelApi.list(record.cityId)
  levelOptions.value = Array.isArray(res?.data) ? res.data : []
  levelTargetId.value = record.id
  levelTargetName.value = record.userNickname || record.mobile
  selectedLevelId.value = record.levelId || 0
  levelVisible.value = true
}

async function handleSetLevel() {
  levelSaving.value = true
  try {
    await riderApi.setLevel(levelTargetId.value, selectedLevelId.value || undefined)
    message.success('设置成功')
    levelVisible.value = false
    loadList()
  } finally {
    levelSaving.value = false
  }
}

async function setStatus(riderId: number, status: number) {
  await riderApi.setStatus(riderId, status)
  message.success('操作成功')
  loadList()
}

async function setEnableStatus(riderId: number, status: number) {
  await riderApi.setEnableStatus(riderId, status)
  message.success('操作成功')
  loadList()
}

async function setType(riderId: number, type: number) {
  await riderApi.setType(riderId, type)
  message.success('操作成功')
  loadList()
}

onMounted(() => {
  loadList()
  if (isAdmin.value) {
    loadCities()
  }
})
</script>