1
董国庆
2026-06-05 3a4a3a09cbef6e8a4551c569b247f04958fa4579
1
3个文件已修改
256 ■■■■■ 已修改文件
src/service/api/testPlanManagement.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/testDemo/testPlanManagement/api.txt 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/testDemo/testPlanManagement/detail.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/service/api/testPlanManagement.ts
@@ -91,27 +91,27 @@
}
export function fetchTestPlanDetailOrderPageList(data: {
  dispatchEndTime?: string
  dispatchStartTime?: string
  dispatchStatus?: number
  endAddress?: string
  orderNumber?: string
  orderStatus?: number
  pageNum: number
  pageSize: number
  plateNumber?: string
  startAddress?: string
  testPlanId: number | string
  vehicleId?: number | string
}) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/test-plan-demo/detail/pageOrders', data)
}
export function exportTestPlanDetailOrders(data: {
  dispatchEndTime?: string
  dispatchStartTime?: string
  dispatchStatus?: number
  endAddress?: string
  orderNumber?: string
  orderStatus?: number
  pageNum?: number
  pageSize?: number
  plateNumber?: string
  startAddress?: string
  testPlanId: number | string
  vehicleId?: number | string
}) {
  const method = request.Post<Blob>('/operation/api/v1/test-plan-demo/detail/exportOrders', data, {
    responseType: 'blob',
@@ -151,6 +151,15 @@
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/test-plan-demo/detail/pageVehicles', data)
}
export function fetchTestPlanVehicleList(data: {
  plateNumber?: string
  testPlanId: number | string
  vehicleCode?: string
  vehicleStatus?: number
}) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/test-plan-demo/detail/listVehicles', data)
}
export function pauseTestPlanVehicles(data: {
  testPlanId: number | string
  vehicleIds: Array<number | string>
src/views/testDemo/testPlanManagement/api.txt
@@ -347,4 +347,59 @@
  "removeVehicleIds": [
    0
  ]
}
}
接口更改
1,/api/v1/test-plan-demo/detail/pageOrders 订单分页  post  json
请求:{
  "endAddress": "string", 终点
  "orderNumber": "string", 订单编号
  "orderStatus": 0, 订单执行状态 0=已取消,1=待接单,2=待出发,3=接驾中,4=待客上车,5=乘客已上车,6=服务中,7=待客下车,8=待付款,9=待评价,10=已完成
  "pageNum": 0,
  "pageSize": 0,
  "plateNumber": "string", 车牌号(兼容车辆查询)
  "startAddress": "string", 起点
  "testPlanId": 0, 测试计划ID
}
响应:
{
  "code": 0,
  "data": {
    "current": 0,
    "hasNextPage": true,
    "hasPrevPage": true,
    "pages": 0,
    "records": [
      {
        "actionCodes": [
          "string"
        ],
        "dispatchStatus": 0,
        "dispatchTime": "string",
        "endAddress": "string", 终点
        "fleetId": 0,
        "fleetName": "string",
        "orderId": 0,
        "orderNumber": "string", 订单编号
        "orderSource": 0, 订单来源(系统自动创建固定为1)
        "orderStatus": 0,
        "orderStatusName": "string", 订单状态文案(
        "plateNumber": "string", 车牌号
        "startAddress": "string", 起点
        "vehicleId": 0
      }
    ],
    "size": 0,
    "startIndex": 0,
    "total": 0
  },
  "msg": "string"
}
​/api​/v1​/test-plan-demo​/detail​/listVehicles 车辆状态不分页 post
src/views/testDemo/testPlanManagement/detail.vue
@@ -1,8 +1,7 @@
<script setup lang="tsx">
import dayjs from 'dayjs'
import { computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NButton, NDataTable, NDatePicker, NForm, NFormItem, NInput, NSelect, NSpace, NTag, useDialog, useMessage } from 'naive-ui'
import { NButton, NDataTable, NForm, NFormItem, NInput, NSelect, NSpace, NTag, useDialog, useMessage } from 'naive-ui'
import type { DataTableColumns } from 'naive-ui'
import Pagination from '@/components/common/Pagination.vue'
import SearchPanel from '@/components/custom/SearchPanel.vue'
@@ -15,7 +14,7 @@
  fetchTestPlanDetail,
  fetchTestPlanDetailOrderPageList,
  fetchTestPlanMonitorDetail,
  fetchTestPlanVehiclePageList,
  fetchTestPlanVehicleList,
  interruptTestPlanDispatch,
  resumeTestPlanDispatch,
} from '@/service/api/testPlanManagement'
@@ -47,20 +46,16 @@
const searchModel = ref({
  orderNo: '',
  vehicleId: null as number | string | null,
  dispatchTimeRange: null as [number, number] | null,
  startAddress: null as string | null,
  endAddress: null as string | null,
  plateNumber: null as string | null,
  orderStatus: null as number | null,
})
const isVehicleSelectOpen = ref(false)
const orderCheckedRowKeys = ref<Array<number | string>>([])
const orderCount = ref(0)
const orderPageParams = ref({
  pageNum: 1,
  pageSize: 10,
})
const vehicleCount = ref(0)
const vehiclePageParams = ref({
  pageNum: 1,
  pageSize: 10,
})
@@ -95,6 +90,7 @@
const isAssignVehicleModalVisible = ref(false)
const isManageTestVehicleModalVisible = ref(false)
const currentAssignOrderId = ref<number | string | null>(null)
const pointOptions = ref<Array<{ label: string, value: string }>>([])
const PLAN_STATUS_STYLE_MAP: Record<number, { textColor: string, color: string }> = {
  1: { textColor: '#0068FF', color: '#E6F4FF' },
@@ -134,9 +130,37 @@
const vehicleOptions = computed(() =>
  vehicleData.value.map(item => ({
    label: item.plateNo,
    value: item.id,
    value: item.plateNo,
  })),
)
const orderStatusOptions = [
  { label: '已取消', value: 0 },
  { label: '待接单', value: 1 },
  { label: '待出发', value: 2 },
  { label: '接驾中', value: 3 },
  { label: '待客上车', value: 4 },
  { label: '乘客已上车', value: 5 },
  { label: '服务中', value: 6 },
  { label: '待客下车', value: 7 },
  { label: '待付款', value: 8 },
  { label: '待评价', value: 9 },
  { label: '已完成', value: 10 },
]
const ORDER_STATUS_LABEL_MAP: Record<number, string> = {
  0: '已取消',
  1: '待接单',
  2: '待出发',
  3: '接驾中',
  4: '待客上车',
  5: '乘客已上车',
  6: '服务中',
  7: '待客下车',
  8: '待付款',
  9: '待评价',
  10: '已完成',
}
const filterItems = computed(() => [
  {
@@ -145,11 +169,35 @@
    render: () => <n-input v-model:value={searchModel.value.orderNo} placeholder="请输入" clearable />,
  },
  {
    label: '车辆',
    path: 'vehicleId',
    label: '起点',
    path: 'startAddress',
    render: () => (
      <n-select
        v-model:value={searchModel.value.vehicleId}
        v-model:value={searchModel.value.startAddress}
        options={pointOptions.value}
        placeholder="请选择"
        clearable
      />
    ),
  },
  {
    label: '终点',
    path: 'endAddress',
    render: () => (
      <n-select
        v-model:value={searchModel.value.endAddress}
        options={pointOptions.value}
        placeholder="请选择"
        clearable
      />
    ),
  },
  {
    label: '车辆',
    path: 'plateNumber',
    render: () => (
      <n-select
        v-model:value={searchModel.value.plateNumber}
        options={vehicleOptions.value}
        placeholder="请选择"
        clearable
@@ -178,31 +226,29 @@
    ),
  },
  {
    label: '下发时间',
    path: 'dispatchTimeRange',
    label: '订单状态',
    path: 'orderStatus',
    render: () => (
      <n-date-picker
        v-model:value={searchModel.value.dispatchTimeRange}
        type="datetimerange"
        format="yyyy/MM/dd HH:mm:ss"
      <n-select
        v-model:value={searchModel.value.orderStatus}
        options={orderStatusOptions}
        placeholder="请选择"
        clearable
        class="w-full"
      />
    ),
  },
])
function getOrderStatusStyle(statusName: string) {
  if (!statusName)
function getOrderStatusStyle(statusCode?: number, statusName?: string) {
  const resolvedStatusName = statusName || (statusCode != null ? ORDER_STATUS_LABEL_MAP[statusCode] : '')
  if (!resolvedStatusName)
    return { textColor: '#8C9299', color: '#F5F5F5' }
  if (statusName.includes('待下发'))
    return { textColor: '#A034FF', color: '#F4E6FF' }
  if (statusName.includes('暂停'))
    return { textColor: '#F59E0B', color: '#FFF7E6' }
  if (statusName.includes('完成') || statusName.includes('关闭'))
  if (resolvedStatusName.includes('取消') || resolvedStatusName.includes('完成'))
    return { textColor: '#8C9299', color: '#F5F5F5' }
  if (statusName.includes('服务') || statusName.includes('待出发') || statusName.includes('待接单') || statusName.includes('待乘客'))
  if (resolvedStatusName.includes('服务') || resolvedStatusName.includes('待接单') || resolvedStatusName.includes('待出发') || resolvedStatusName.includes('接驾') || resolvedStatusName.includes('待客') || resolvedStatusName.includes('上车'))
    return { textColor: '#0068FF', color: '#E6F4FF' }
  if (resolvedStatusName.includes('付款') || resolvedStatusName.includes('评价'))
    return { textColor: '#F59E0B', color: '#FFF7E6' }
  return { textColor: '#10B981', color: '#F6FFED' }
}
@@ -222,14 +268,27 @@
}
function buildOrderQueryParams() {
  const timeRange = searchModel.value.dispatchTimeRange
  return {
    orderNumber: searchModel.value.orderNo.trim() || undefined,
    vehicleId: searchModel.value.vehicleId || undefined,
    dispatchStartTime: timeRange?.[0] ? dayjs(timeRange[0]).format('YYYY-MM-DD HH:mm:ss') : undefined,
    dispatchEndTime: timeRange?.[1] ? dayjs(timeRange[1]).format('YYYY-MM-DD HH:mm:ss') : undefined,
    startAddress: searchModel.value.startAddress || undefined,
    endAddress: searchModel.value.endAddress || undefined,
    plateNumber: searchModel.value.plateNumber || undefined,
    orderStatus: searchModel.value.orderStatus ?? undefined,
    testPlanId: currentPlanId.value,
  }
}
function buildPointOptions(points: unknown) {
  if (!Array.isArray(points))
    return []
  const optionMap = new Map<string, string>()
  points.forEach((item: any) => {
    const pointName = item?.pointName || ''
    if (!pointName || optionMap.has(pointName))
      return
    optionMap.set(pointName, pointName)
  })
  return [...optionMap.entries()].map(([value, label]) => ({ value, label }))
}
async function fetchBaseDetail() {
@@ -242,11 +301,14 @@
    if (res.code !== 200 && res.code !== 0) {
      throw new Error(res.msg || '获取测试计划详情失败')
    }
    planName.value = res.data?.planName || '-'
    const detail = res.data || {}
    planName.value = detail.planName || '-'
    pointOptions.value = buildPointOptions(detail.points)
  }
  catch (error: any) {
    message.error(error?.message || '获取测试计划详情失败')
    planName.value = '-'
    pointOptions.value = []
  }
  finally {
    detailLoading.value = false
@@ -299,8 +361,9 @@
    const pageData = res.data || {}
    const records = Array.isArray(pageData.records) ? pageData.records : []
    orderData.value = records.map((item: any) => {
      const statusName = item.orderStatusName || '-'
      const statusStyle = getOrderStatusStyle(statusName)
      const statusCode = item.orderStatus != null ? Number(item.orderStatus) : undefined
      const statusName = item.orderStatusName || (statusCode != null ? ORDER_STATUS_LABEL_MAP[statusCode] : '-') || '-'
      const statusStyle = getOrderStatusStyle(statusCode, statusName)
      return {
        orderId: item.orderId ?? item.id,
        orderNo: item.orderNumber || '-',
@@ -351,16 +414,18 @@
  vehicleLoading.value = true
  try {
    const res = await fetchTestPlanVehiclePageList({
      pageNum: vehiclePageParams.value.pageNum,
      pageSize: vehiclePageParams.value.pageSize,
    const res = await fetchTestPlanVehicleList({
      testPlanId: currentPlanId.value,
    })
    if (res.code !== 200 && res.code !== 0) {
      throw new Error(res.msg || '获取测试车辆失败')
    }
    const pageData = res.data || {}
    const records = Array.isArray(pageData.records) ? pageData.records : []
    const rawData = res.data
    const records = Array.isArray(rawData)
      ? rawData
      : Array.isArray(rawData?.records)
        ? rawData.records
        : []
    vehicleData.value = records.map((item: any) => {
      const status = Number(item.vehicleStatus ?? item.paused ?? 0)
      return {
@@ -373,11 +438,9 @@
        statusColor: VEHICLE_STATUS_STYLE_MAP[status] || '#8C9299',
      }
    })
    vehicleCount.value = Number(pageData.total || 0)
  }
  catch (error: any) {
    vehicleData.value = []
    vehicleCount.value = 0
    message.error(error?.message || '获取测试车辆失败')
  }
  finally {
@@ -398,7 +461,7 @@
const orderColumns = computed<DataTableColumns<OrderRow>>(() => [
  { type: 'selection', width: 50, align: 'center' },
  { title: '订单编号', key: 'orderNo', width: 160 },
  { title: '订单编号', key: 'orderNo', width: 160 ,ellipsis: { tooltip: true } },
  { title: '下发时间', key: 'issueTime', width: 180 },
  { title: '起点', key: 'startPoint', width: 180, ellipsis: { tooltip: true } },
  { title: '终点', key: 'endPoint', width: 180, ellipsis: { tooltip: true } },
@@ -460,8 +523,10 @@
function handleReset() {
  searchModel.value = {
    orderNo: '',
    vehicleId: null,
    dispatchTimeRange: null,
    startAddress: null,
    endAddress: null,
    plateNumber: null,
    orderStatus: null,
  }
  orderPageParams.value.pageNum = 1
  fetchOrderList()
@@ -471,12 +536,6 @@
  orderPageParams.value.pageNum = size !== orderPageParams.value.pageSize ? 1 : page
  orderPageParams.value.pageSize = size
  fetchOrderList()
}
function handleVehiclePageChange(page: number, size: number) {
  vehiclePageParams.value.pageNum = size !== vehiclePageParams.value.pageSize ? 1 : page
  vehiclePageParams.value.pageSize = size
  fetchVehicleList()
}
async function handleExportOrders() {
@@ -660,7 +719,7 @@
      orderData.value = []
      vehicleData.value = []
      orderCount.value = 0
      vehicleCount.value = 0
      pointOptions.value = []
      return
    }
    await loadPageData()
@@ -826,13 +885,6 @@
                </div>
              </template>
            </n-data-table>
            <Pagination
              :count="vehicleCount"
              :page="vehiclePageParams.pageNum"
              :page-size="vehiclePageParams.pageSize"
              class="robotaxi-pagination mt-12px shrink-0"
              @change="handleVehiclePageChange"
            />
          </div>
        </div>
      </div>