zjk
2026-02-11 1557c49db3a44908c3083466bbe1e28fdd1ede7f
feat: 导航及路径规划接口对接,交易策略接口
1个文件已添加
5个文件已修改
511 ■■■■■ 已修改文件
src/service/api/common.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/service/api/transaction.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/transaction/evaluationRecord/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/transaction/navigationAndRoutePlanning/components/TableModal.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/transaction/navigationAndRoutePlanning/index.vue 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/transaction/transactionStrategy/index.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/service/api/common.ts
New file
@@ -0,0 +1,12 @@
import { request } from '@/service/http'
/** 获取区域列表 */
export async function getRegionList() {
  return request.Get<Service.ResponseResult<any>>('/operation/base/v1/mini-program/open/t-region/getRegion')
}
/** 获取市 */
export async function getProvinceList(params: any) {
  return request.Post<Service.ResponseResult<any>>('/operation/base/v1/mini-program/open/t-region/getProvince', params)
}
src/service/api/transaction.ts
@@ -39,3 +39,44 @@
export function getOrderEvaluateList(params: any) {
  return request.Post<Service.ResponseResult<any>>('/order/api/v1/orderEvaluate/pageList', params)
}
/** 导航与路径规划 */
// 获取导航与路径规划列表
export function getRoutePlanList(params: any) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/routePlan/pageList', params)
}
// 添加导航与路径规划
export function addRoutePlan(params: any) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/routePlan/add', params)
}
// 添加导航与路径规划
export function editRoutePlan(params: any) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/routePlan/edit', params)
}
// 删除导航与路径规划
export function deleteRoutePlan(id: any) {
  return request.Delete<Service.ResponseResult<any>>('/operation/api/v1/routePlan/deleteById/' + id)
}
/** 获取开通城市列表 */
export function getCityList() {
  return request.Get<Service.ResponseResult<any>>('/operation/base/v1/mini-program/api/v1/openCity/list')
}
// 交易策略
/** 获取交易策略 */
export function getTradingStrategyDetail() {
  return request.Get<Service.ResponseResult<any>>('/operation/api/v1/tradingStrategy/queryById')
}
/** 编辑交易策略 */
export function editTradingStrategy(params: any) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/tradingStrategy/edit', params)
}
src/views/transaction/evaluationRecord/index.vue
@@ -121,8 +121,8 @@
    orderRating: model.value.orderRating,
    phoneNumber: model.value.phoneNumber,
    plateNumber: model.value.plateNumber,
    startTime: model.value.time ? dayjs(model.value.time[0]).format('YYYY-MM-DD HH:mm:ss') : '',
    endTime: model.value.time ? dayjs(model.value.time[1]).format('YYYY-MM-DD HH:mm:ss') : '',
    startTime: model.value.time ? dayjs(model.value.time[0]).format('YYYY-MM-DD HH:mm:ss') : null,
    endTime: model.value.time ? dayjs(model.value.time[1]).format('YYYY-MM-DD HH:mm:ss') : null,
  }
  getOrderEvaluateList(params).then((res) => {
    listData.value = res.data || []
@@ -171,7 +171,7 @@
      <n-card class="flex-1">
        <NSpace vertical>
          <n-data-table :columns="columns" :data="listData" :loading="loading" />
          <n-data-table :columns="columns" :data="listData" :loading="loading" :bordered="false" :header-height="18" :row-height="18" />
          <Pagination :count="count" @change="changePage" />
        </NSpace>
      </n-card>
src/views/transaction/navigationAndRoutePlanning/components/TableModal.vue
@@ -1,6 +1,9 @@
<script setup lang="ts">
import { useBoolean } from '@/hooks'
import { fetchRoleList } from '@/service'
import { getCityList, addRoutePlan, editRoutePlan } from '@/service/api/transaction'
import type { FormItemRule } from 'naive-ui'
const message = useMessage()
interface Props {
  modalName?: string
@@ -13,6 +16,7 @@
const emit = defineEmits<{
  open: []
  close: []
  refresh: []
}>()
const { bool: modalVisible, setTrue: showModal, setFalse: hiddenModal } = useBoolean(false)
@@ -20,10 +24,10 @@
const { bool: submitLoading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false)
const formDefault = {
  name: '',
  city: null,
  remark: '',
  routePlanningRules: '',
  planName: '',
  openCityId: null,
  remarks: '',
  routePlanRule: '',
}
const formModel = ref({ ...formDefault })
@@ -42,7 +46,6 @@
  emit('open')
  modalType.value = type
  showModal()
  getRoleList()
  const handlers = {
    async add() {
      formModel.value = { ...formDefault }
@@ -76,18 +79,26 @@
  const handlers = {
    async add() {
      return new Promise((resolve) => {
        setTimeout(() => {
          window.$message.success('模拟新增成功')
          resolve(true)
        }, 2000)
        addRoutePlan(formModel.value).then((res) => {
          if (res.code === 200) {
            message.success('新增成功')
            resolve(true)
          } else {
            resolve(false)
          }
        })
      })
    },
    async edit() {
      return new Promise((resolve) => {
        setTimeout(() => {
          window.$message.success('模拟编辑成功')
          resolve(true)
        }, 2000)
        editRoutePlan(formModel.value).then((res) => {
          if (res.code === 200) {
            message.success('编辑成功')
            resolve(true)
          } else {
            resolve(false)
          }
        })
      })
    },
    async view() {
@@ -96,43 +107,121 @@
  }
  await formRef.value?.validate()
  startLoading()
  await handlers[modalType.value]() && closeModal()
  const result = await handlers[modalType.value]()
  endLoading()
  if (result) {
    emit('refresh')
    closeModal()
  }
}
const rules = {
  name: {
  planName: {
    required: true,
    message: '请输入名称',
    trigger: 'blur',
  },
  city: {
  openCityId: {
    required: true,
    message: '请选择适用城市',
    trigger: 'change',
  },
  routePlanningRules: {
  routePlanRule: {
    type: 'number',
    required: true,
    message: '请选择线路规划规则',
    trigger: 'change',
  },
  } as FormItemRule,
}
const options = ref()
async function getRoleList() {
  const { data } = await fetchRoleList()
  options.value = data
const routePlanOptions = [
  {
    label: '速度优先(只返回一条路线),此路线不一定距离最短',
    value: 0,
  },
  {
    label: '费用优先(只返回一条路线),不走收费路段,且耗时最少的路线',
    value: 1,
  },
  {
    label: '常规最快(只返回一条路线),综合距离/耗时规划结果',
    value: 2,
  },
  {
    label: '默认,高德推荐,同高德地图APP默认',
    value: 32,
  },
  {
    label: '躲避拥堵',
    value: 33,
  },
  {
    label: '高速优先',
    value: 34,
  },
  {
    label: '不走高速',
    value: 35,
  },
  {
    label: '少收费',
    value: 36,
  },
  {
    label: '大路优先',
    value: 37,
  },
  {
    label: '速度最快',
    value: 38,
  },
  {
    label: '躲避拥堵+高速优先',
    value: 39,
  },
  {
    label: '躲避拥堵+不走高速',
    value: 40,
  },
  {
    label: '躲避拥堵+少收费',
    value: 41,
  },
  {
    label: '少收费+不走高速',
    value: 42,
  },
  {
    label: '躲避拥堵+少收费+不走高速',
    value: 43,
  },
  {
    label: '躲避拥堵+大路优先',
    value: 44,
  },
  {
    label: '躲避拥堵+速度最快',
    value: 45,
  }
]
const cityList = ref<any[]>([])
const getCityListData = () => {
  getCityList().then((res) => {
    if (res.code === 200) {
      cityList.value = res.data || []
      cityList.value.forEach((item) => {
        item.label = item.name
        item.value = item.id
      })
    }
  })
}
const routePlanOptions = computed(() => [
  {
    label: '速度优先(只返回一条路线),此路线不一定距离最短',
    value: '1',
  },
  {
    label: '费用优先(只返回一条路线),不走收费路线,且耗时最少的路线',
    value: '2',
  },
])
onMounted(() => {
  getCityListData()
})
</script>
<template>
@@ -141,19 +230,20 @@
      content: true,
      action: true,
    }">
    <n-form ref="formRef" :rules="rules" label-placement="left" :model="formModel" :disabled="modalType === 'view'" require-mark-placement="left" >
    <n-form ref="formRef" :rules="rules" label-placement="left" :model="formModel" :disabled="modalType === 'view'"
      require-mark-placement="left">
      <n-grid :cols="2" :x-gap="18">
        <n-form-item-grid-item :span="1" label="名称" path="name">
          <n-input v-model:value="formModel.name" />
        <n-form-item-grid-item :span="1" label="名称" path="planName">
          <n-input v-model:value="formModel.planName" />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" label="适用城市" path="city">
          <PcaCascader v-model:value="formModel.city" />
        <n-form-item-grid-item :span="1" label="适用城市" path="openCityId">
          <n-select v-model:value="formModel.openCityId" :options="cityList" />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="2" label="备注" path="remark">
          <n-input v-model:value="formModel.remark" type="textarea" />
        <n-form-item-grid-item :span="2" label="备注" path="remarks">
          <n-input v-model:value="formModel.remarks" type="textarea" />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="2" label="线路规划规则" path="routePlanningRules" label-placement="top">
          <n-radio-group v-model:value="formModel.routePlanningRules" name="routePlanningRules" class="pl-8">
        <n-form-item-grid-item :span="2" label="线路规划规则" path="routePlanRule" label-placement="top">
          <n-radio-group v-model:value="formModel.routePlanRule" class="pl-8">
            <n-space vertical>
              <n-radio v-for="option in routePlanOptions" :key="option.value" :value="option.value">
                {{ option.label }}
src/views/transaction/navigationAndRoutePlanning/index.vue
@@ -1,18 +1,19 @@
<script setup lang="tsx">
import type { DataTableColumns, FormInst } from 'naive-ui'
import { useBoolean } from '@/hooks'
import { fetchUserPage } from '@/service'
import { getRoutePlanList, addRoutePlan, editRoutePlan, deleteRoutePlan } from '@/service/api/transaction'
import { NButton, NPopconfirm, NSpace } from 'naive-ui'
import SearchPanel from '@/components/custom/SearchPanel.vue'
import TableModal from './components/TableModal.vue'
const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false)
const { t } = useI18n()
const dialog = useDialog()
const message = useMessage()
const initialModel = {
  condition_1: '',
  condition_2: '',
  condition_3: null,
  cityName: '',
  routePlanRule: null,
}
const model = ref({ ...initialModel })
function handleResetSearch() {
@@ -21,10 +22,10 @@
const formRef = ref<FormInst | null>()
const modalRef = ref()
function delteteUser(id: number) {
  window.$message.success(`删除用户id:${id}`)
}
const pageParams = ref({
  pageNum: 1,
  pageSize: 10,
})
const columns = computed<DataTableColumns<any>>(() =>[
  {
@@ -36,25 +37,25 @@
  {
    title: '名称',
    align: 'center',
    key: 'name',
    key: 'planName',
    ellipsis: true
  },
  {
    title: '开通城市',
    align: 'center',
    key: 'city',
    key: 'cityName',
    ellipsis: true
  },
  {
    title: '优先规则',
    align: 'center',
    key: 'priorityRules',
    key: 'routePlanRule',
    ellipsis: true
  },
  {
    title: '备注',
    align: 'center',
    key: 'remark',
    key: 'remarks',
    ellipsis: true
  },
  {
@@ -79,12 +80,29 @@
          >
            编辑
          </NButton>
          <NPopconfirm onPositiveClick={() => delteteUser(row.id!)}>
            {{
              default: () => '确认删除',
              trigger: () => <NButton text type="error">删除</NButton>,
           <NButton
            text
            type="error"
            onClick={() => {
              dialog.create({
                title: '是否确认删除订单?',
                content: '',
                positiveText: '确定',
                negativeText: '取消',
                draggable: true,
                onPositiveClick: () => {
                  deleteRoutePlan(row.id).then(res => {
                  if (res.code === 200) {
                    message.success('删除成功')
                    getList()
                  }
                })
                }
              })
            }}
          </NPopconfirm>
          >
            删除
          </NButton>
        </NSpace>
      )
    },
@@ -93,25 +111,85 @@
const options = [
  {
    label: '速度优先',
    value: '1',
    label: '速度优先(只返回一条路线),此路线不一定距离最短',
    value: 0,
  },
  {
    label: '距离优先',
    value: '2',
  }
    label: '费用优先(只返回一条路线),不走收费路段,且耗时最少的路线',
    value: 1,
  },
  {
    label: '常规最快(只返回一条路线),综合距离/耗时规划结果',
    value: 2,
  },
  {
    label: '默认,高德推荐,同高德地图APP默认',
    value: 32,
  },
  {
    label: '躲避拥堵',
    value: 33,
  },
  {
    label: '高速优先',
    value: 34,
  },
  {
    label: '不走高速',
    value: 35,
  },
   {
    label: '少收费',
    value: 36,
   },
   {
    label: '大路优先',
    value: 37,
   },
   {
    label: '速度最快',
    value: 38,
   },
   {
    label: '躲避拥堵+高速优先',
    value: 39,
   },
   {
    label: '躲避拥堵+不走高速',
    value: 40,
   },
   {
    label: '躲避拥堵+少收费',
    value: 41,
   },
   {
    label: '少收费+不走高速',
    value: 42,
   },
   {
    label: '躲避拥堵+少收费+不走高速',
    value: 43,
   },
   {
    label: '躲避拥堵+大路优先',
    value: 44,
   },
   {
    label: '躲避拥堵+速度最快',
    value: 45,
   }
]
const filterItems = computed(() => [
  {
    label: '城市',
    path: 'condition_1',
    render: () => <n-input v-model:value={model.value.condition_1} />,
    path: 'cityName',
    render: () => <n-input v-model:value={model.value.cityName} clearable />,
  },
  {
    label: '优先规则',
    path: 'condition_3',
    render: () => <n-select v-model:value={model.value.condition_3} options={options}  />,
    path: 'routePlanRule',
    render: () => <n-select v-model:value={model.value.routePlanRule} options={options} clearable />,
  }
])
@@ -120,33 +198,20 @@
async function getList() {
  startLoading()
  setTimeout(() => {
    listData.value = [
      {
        id: 1,
        name: '城市1',
        city: '四川省成都市',
        priorityRules: '速度优先',
        remark: '备注1',
        createTime: '2023-01-01 10:00:00',
        updateTime: '2023-01-01 10:00:00',
      },
      {
        id: 2,
        name: '城市2',
        city: '四川省成都市',
        priorityRules: '距离优先',
        remark: '备注2',
        createTime: '2023-01-01 10:00:00',
        updateTime: '2023-01-01 10:00:00',
      },
    ]
  const params = {
    ...pageParams.value,
    cityName: model.value.cityName,
    routePlanRule: model.value.routePlanRule,
  }
  getRoutePlanList(params).then((res) => {
    listData.value = res.data.records || []
    listData.value.forEach((item: any, index: number)  => {
      item.serialNumber = index + 1
    })
    count.value = 1
    count.value = res.data.total || res.data.records?.length
  }).finally(() => {
    endLoading()
  }, 1000)
  })
}
onMounted(() => {
@@ -154,14 +219,16 @@
})
function changePage(page: number, size: number) {
  window.$message.success(`分页器:${page},${size}`)
  pageParams.value.pageNum = page
  pageParams.value.pageSize = size
  getList()
}
</script>
<template>
  <n-flex>
  <n-flex class="roboTaxi">
    <NSpace vertical class="flex-1">
      <n-card>
      <div class="roboTaxi-form-card">
        <n-form ref="formRef" :model="model" label-placement="left" inline :show-feedback="false">
          <SearchPanel>
            <n-gi v-for="item in filterItems" :key="item.path">
@@ -170,38 +237,32 @@
              </n-form-item>
            </n-gi>
            <template #action>
              <NButton strong secondary @click="handleResetSearch">
                <template #icon>
                  <icon-park-outline-redo />
                </template>
              <NButton strong @click="handleResetSearch">
                {{ $t('common.reset') }}
              </NButton>
              <NButton type="primary" @click="getList">
                <template #icon>
                  <icon-park-outline-search />
                </template>
                {{ $t('common.search') }}
              </NButton>
            </template>
          </SearchPanel>
        </n-form>
      </n-card>
      </div>
      <n-card class="flex-1">
        <template #header>
          <NButton type="primary" @click="modalRef.openModal('add')">
            <template #icon>
              <icon-park-outline-add-one />
            </template>
            新增城市
          </NButton>
          <n-flex justify="flex-end">
            <NButton type="primary" secondary @click="modalRef.openModal('add')">
              新增城市
            </NButton>
          </n-flex>
        </template>
        <NSpace vertical>
          <n-data-table :columns="columns" :data="listData" :loading="loading" />
          <n-data-table :columns="columns" :data="listData" :loading="loading" :bordered="false" :header-height="18"
            :row-height="18" />
          <Pagination :count="count" @change="changePage" />
        </NSpace>
        <TableModal ref="modalRef" modal-name="线路规划配置" />
        <TableModal ref="modalRef" modal-name="线路规划配置" @refresh="getList"/>
      </n-card>
    </NSpace>
  </n-flex>
src/views/transaction/transactionStrategy/index.vue
@@ -2,13 +2,38 @@
import { useBoolean } from '@/hooks'
import type { DataTableColumns } from 'naive-ui'
import { NButton, NSpace } from 'naive-ui'
import { editTradingStrategy, getTradingStrategyDetail } from '@/service/api/transaction'
const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false)
const initialModel:any = {
  condition_1: null,
  condition_2: false,
  condition_3: [],
  cancleCount: null, // 取消订单次数
  exemptionAmount: null, // 豁免金额
  exemptionTime: null, // 豁免时效
  exemptionStartTime: null, // 豁免开始时间
  exemptionEndTime: null,// 豁免结束时间
  exemptionRole: [], // 豁免角色
  isLongValid: null, // 是否长期有效
  onePushDistance: null, // 一轮推单距离
  onePushTime: null, // 一轮推单时间
  twoPushDistance: null, // 二轮推单距离
  twoPushTime: null, // 二轮推单时间
  threePushDistance: null, // 三轮推单距离
  threePushTime: null, // 三轮推单时间
  passwordFreeAmount: null, // 免密授权金额
  prepaidLimit: null, // 预付额度 订单大于金额需预付
  ruleType: null, // 规则类型
  simultaneouslyOrderCount: null, // 同时抢单人数
  tendencyDistance: null, // 倾向距离
  tendencyElectricity: null, // 倾向电量
  tendencyOrderValue: null, // 倾向订单价值
  tendencyTime: null, // 倾向时间
  weightDistance: null, // 权重距离
  weightDistanceDifference: null, // 权重距离差
  weightElectricity: null, // 权重电量
  weightTime: null, // 权重时间
  weightTimeDifference: null, // 权重时间差
  cityList: [], // 豁免城市列表
}
const model = ref({ ...initialModel })
@@ -16,27 +41,27 @@
const options = computed(() => [
  {
    label: '全部',
    value: '1',
    value: 0,
  },
  {
    label: '新客',
    value: '2',
    disabled: model.value.condition_3.includes('1'),
    value: 1,
    disabled: model.value.exemptionRole.includes(0),
  },
  {
    label: '老客',
    value: '3',
     disabled: model.value.condition_3.includes('1'),
    value: 2,
     disabled: model.value.exemptionRole.includes(0),
  },
  {
    label: '流失召回',
    value: '4',
     disabled: model.value.condition_3.includes('1'),
    value: 3,
     disabled: model.value.exemptionRole.includes(0),
  },
  {
    label: '媒体',
    value: '5',
     disabled: model.value.condition_3.includes('1'),
    value: 4,
     disabled: model.value.exemptionRole.includes(0),
  }
])
@@ -118,7 +143,11 @@
])
onMounted(() => {
  // startLoading()
  getTradingStrategyDetail().then((res) => {
    if (res.code === 0) {
      model.value = res.data
    }
  })
})
</script>
@@ -134,7 +163,7 @@
            <NSpace vertical :size="16">
              <div class="text-base font-bold">发单策略</div>
              <div class="pl-4">
                <n-form-item label="用户取消订单" path="condition_1" required>
                <n-form-item label="用户取消订单" path="cancleCount" required>
                  <n-tooltip placement="top-start" trigger="hover">
                    <template #trigger>
                      <icon-park-outline-help />
@@ -144,8 +173,8 @@
                </n-form-item>
              </div>
              <div class="pl-20">
                <n-form-item label="用户每日取消订单数" path="condition_1" required>
                  <n-input-number v-model:value="model.condition_1" min="0" :precision="0" :show-button="false" />
                <n-form-item label="用户每日取消订单数" path="cancleCount" required>
                  <n-input-number v-model:value="model.cancleCount" min="0" :precision="0" :show-button="false" />
                </n-form-item>
              </div>
            </NSpace>
@@ -153,24 +182,24 @@
            <NSpace vertical :size="16">
              <div class="text-base font-bold">发单拦截策略</div>
              <div class="pl-4">
                <n-form-item label="小额豁免配置" path="condition_1" />
                <n-form-item label="小额豁免配置" path="smallAmountExemption" />
              </div>
              <NSpace vertical class="pl-20" :size="16">
                <n-form-item label="金额上限" path="condition_1" required>
                  <n-input-number v-model:value="model.condition_1" min="0" :precision="0" :show-button="false"
                <n-form-item label="金额上限" path="smallAmountExemption" required>
                  <n-input-number v-model:value="model.smallAmountExemption" min="0" :precision="0" :show-button="false"
                    class="mr-2" />元内可豁免
                </n-form-item>
                <n-form-item label="豁免城市" path="condition_1" required>
                  <PcaCascader v-model:value="model.condition_1" class="w-[240px]" />
                <n-form-item label="豁免城市" path="cityList" required>
                  <PcaCascader v-model:value="model.cityList" class="w-[240px]" />
                </n-form-item>
                <n-form-item label="豁免时效" path="condition_1" required>
                  <n-date-picker v-model:value="model.condition_1" type="daterange" clearable class="mr-2 w-[240px]" />
                  <n-checkbox v-model:checked="model.condition_2">
                <n-form-item label="豁免时效" path="exemptionTime" required>
                  <n-date-picker v-model:value="model.exemptionTime" type="daterange" clearable class="mr-2 w-[240px]" />
                  <n-checkbox v-model:checked="model.isLongValid">
                    长期有效
                  </n-checkbox>
                </n-form-item>
                <n-form-item label="豁免角色" path="condition_1" required>
                  <n-select v-model:value="model.condition_3" :options="options" multiple class="w-[240px]" />
                <n-form-item label="豁免角色" path="exemptionRole" required>
                  <n-select v-model:value="model.exemptionRole" :options="options" multiple class="w-[240px]" />
                </n-form-item>
              </NSpace>
              <div class="pl-4">