feat(web-admin): 承运商去审核 UI 并移除安排运输准入拦截
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
4eed1183b5
commit
fd62043f71
5 files changed
+9
-173
No files matched your search
@@ -49,6 +49,7 @@ export const carrierApi = {
|
||||
get: (id: string) => request.get<Carrier>(`/transport/carrier/${id}`),
|
||||
create: (data: Partial<Carrier>) => request.post<Carrier>('/transport/carrier', data),
|
||||
update: (id: string, data: Partial<Carrier>) => request.put<Carrier>(`/transport/carrier/${id}`, data),
|
||||
/** @deprecated 承运商审核已移除,后端接口已禁用 */
|
||||
approve: (id: string) => request.post<Carrier>(`/transport/carrier/${id}/approve`),
|
||||
reject: (id: string, data?: { remark?: string }) =>
|
||||
request.post<Carrier>(`/transport/carrier/${id}/reject`, data ?? {}),
|
||||
|
||||
@@ -86,8 +86,6 @@ import {
|
||||
} from '@/composables/usePlVehicleViewDetail'
|
||||
import { formatDateTime } from '@/utils/format'
|
||||
import {
|
||||
getPlCarrierAuditStatusLabel,
|
||||
getPlCarrierAuditStatusTagType,
|
||||
getPlCarrierStatusLabel,
|
||||
getPlCarrierStatusTagType
|
||||
} from '@/utils/pl-display'
|
||||
@@ -118,8 +116,7 @@ const heroMeta = computed(() => {
|
||||
const parts = [
|
||||
c.contactName || undefined,
|
||||
c.contactPhone || undefined,
|
||||
getPlCarrierStatusLabel(c.status),
|
||||
getPlCarrierAuditStatusLabel(c.auditStatus)
|
||||
getPlCarrierStatusLabel(c.status)
|
||||
].filter(Boolean)
|
||||
return parts.join(' · ')
|
||||
})
|
||||
@@ -145,26 +142,6 @@ const carrierInfoRow2Fields = computed<ViewField[]>(() => {
|
||||
const c = carrier.value
|
||||
if (!c) return []
|
||||
|
||||
return [
|
||||
{
|
||||
label: '审核状态',
|
||||
value: getPlCarrierAuditStatusLabel(c.auditStatus),
|
||||
tagType: getPlCarrierAuditStatusTagType(c.auditStatus),
|
||||
long: false
|
||||
},
|
||||
{
|
||||
label: '审核时间',
|
||||
value: c.auditTime ? formatDateTime(c.auditTime) : '—',
|
||||
long: false
|
||||
},
|
||||
{ label: '审核备注', value: c.auditRemark || '—', long: false, fullSpan: false }
|
||||
]
|
||||
})
|
||||
|
||||
const carrierInfoRow3Fields = computed<ViewField[]>(() => {
|
||||
const c = carrier.value
|
||||
if (!c) return []
|
||||
|
||||
return [
|
||||
{ label: '创建时间', value: formatDateTime(c.createTime), long: false },
|
||||
{
|
||||
@@ -192,8 +169,7 @@ const viewSections = computed<ViewSection[]>(() => {
|
||||
title: '承运商信息',
|
||||
fieldGroups: [
|
||||
{ fieldLayout: 'table', tableMode: 'quad', fields: [] },
|
||||
{ fieldLayout: 'table', tableMode: 'quad', fields: [] },
|
||||
{ fieldLayout: 'table', tableMode: 'triple', fields: [] }
|
||||
{ fieldLayout: 'table', tableMode: 'quad', fields: [] }
|
||||
],
|
||||
fields: []
|
||||
},
|
||||
@@ -214,11 +190,6 @@ const viewSections = computed<ViewSection[]>(() => {
|
||||
{
|
||||
fieldLayout: 'table',
|
||||
tableMode: 'quad',
|
||||
fields: carrierInfoRow3Fields.value
|
||||
},
|
||||
{
|
||||
fieldLayout: 'table',
|
||||
tableMode: 'triple',
|
||||
fields: carrierInfoRow2Fields.value
|
||||
}
|
||||
],
|
||||
|
||||
@@ -36,14 +36,6 @@
|
||||
|
||||
<section v-else class="pl-plan-form-section">
|
||||
<h3 class="pl-plan-form-section-title">{{ isRearrange ? '调整运输' : '运输安排' }}</h3>
|
||||
<el-alert
|
||||
v-if="rearrangeBlocked"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
:title="rearrangeBlockedMessage"
|
||||
class="pl-arrange-block-alert"
|
||||
/>
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="right" label-width="100px" class="pl-dialog-form">
|
||||
<div class="form-grid-4">
|
||||
<el-form-item label="选择车辆" prop="vehicleId">
|
||||
@@ -304,7 +296,7 @@
|
||||
<el-button @click="innerVisible = false">
|
||||
<el-icon><Close /></el-icon>取消
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" :disabled="rearrangeBlocked" @click="handleSubmit">
|
||||
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">
|
||||
<el-icon><Check /></el-icon>{{ isRearrange ? '确认调整' : '确认安排' }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -401,8 +393,6 @@ const vehicleBundle = ref<VehicleViewBundle | null>(null)
|
||||
const vehicleViewVisible = ref(false)
|
||||
const hasHistoricalDibang = ref(false)
|
||||
const hasHistoricalSiteLinks = ref(false)
|
||||
const rearrangeBlocked = ref(false)
|
||||
const rearrangeBlockedMessage = ref('')
|
||||
|
||||
const formData = reactive({
|
||||
vehicleId: '',
|
||||
@@ -488,8 +478,6 @@ const freightCalc = usePlFreightCalc({
|
||||
freightType: freightTypeRef
|
||||
})
|
||||
|
||||
const selectedVehicle = computed(() => vehicleList.value.find(item => item.id === formData.vehicleId))
|
||||
|
||||
const showDibangHint = computed(
|
||||
() => formData.generateDibangPlan && canGenerateDibangPlan.value
|
||||
)
|
||||
@@ -615,8 +603,6 @@ function resetState() {
|
||||
vehicleViewVisible.value = false
|
||||
hasHistoricalDibang.value = false
|
||||
hasHistoricalSiteLinks.value = false
|
||||
rearrangeBlocked.value = false
|
||||
rearrangeBlockedMessage.value = ''
|
||||
Object.assign(formData, {
|
||||
vehicleId: '',
|
||||
driverId: '',
|
||||
@@ -643,47 +629,13 @@ function resetState() {
|
||||
|
||||
async function loadMasterData() {
|
||||
const [vehicleRes, carrierRes] = await Promise.all([
|
||||
vehicleApi.list({ vehicleStatus: 'available', excludeIneligibleCarrier: true }),
|
||||
vehicleApi.list({ vehicleStatus: 'available' }),
|
||||
carrierApi.list({ status: '1', page: 1, pageSize: 100 })
|
||||
])
|
||||
vehicleList.value = pickBxList<Vehicle>(vehicleRes)
|
||||
carrierList.value = pickBxList<Carrier>(carrierRes)
|
||||
}
|
||||
|
||||
async function updateRearrangeBlocked() {
|
||||
rearrangeBlocked.value = false
|
||||
rearrangeBlockedMessage.value = ''
|
||||
if (!isRearrange.value) return
|
||||
|
||||
const detail = vehicleBundle.value?.detail
|
||||
const carrierId = detail?.carrierId || formData.carrierId || selectedVehicle.value?.carrierId
|
||||
if (!carrierId) return
|
||||
|
||||
let carrier = carrierList.value.find(c => c.id === carrierId)
|
||||
if (!carrier) {
|
||||
try {
|
||||
const res = await carrierApi.get(carrierId)
|
||||
carrier = pickBxData<Carrier>(res)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!carrier?.qualificationComplete) {
|
||||
rearrangeBlocked.value = true
|
||||
rearrangeBlockedMessage.value = '该承运商资质附件不完整,请先补全后再调整运输'
|
||||
return
|
||||
}
|
||||
if (carrier.auditStatus !== 'approved') {
|
||||
rearrangeBlocked.value = true
|
||||
rearrangeBlockedMessage.value = '该承运商尚未审核通过,请先完成审核后再调整运输'
|
||||
return
|
||||
}
|
||||
if (carrier.transportAgreementExpired) {
|
||||
rearrangeBlocked.value = true
|
||||
rearrangeBlockedMessage.value = '该承运商运输协议已过期,请先更新协议后再调整运输'
|
||||
}
|
||||
}
|
||||
|
||||
async function handleVehicleChange(vehicleId: string, preferredDriverId?: string) {
|
||||
if (!vehicleId) {
|
||||
formData.driverId = ''
|
||||
@@ -709,7 +661,6 @@ async function handleVehicleChange(vehicleId: string, preferredDriverId?: string
|
||||
formData.carrierId = vehicleBundle.value.detail.carrierId
|
||||
}
|
||||
applyVehiclePersonnel(vehicleBundle.value.personnelList || [], preferredDriverId)
|
||||
await updateRearrangeBlocked()
|
||||
} finally {
|
||||
vehicleLoading.value = false
|
||||
}
|
||||
@@ -746,10 +697,6 @@ function handleClosed() {
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (rearrangeBlocked.value) {
|
||||
ElMessage.warning(rearrangeBlockedMessage.value || '当前承运商不可调整运输')
|
||||
return
|
||||
}
|
||||
const valid = await formRef.value?.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
|
||||
@@ -886,10 +833,6 @@ function handlePrintSubpackSlip() {
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.pl-arrange-block-alert {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-fields {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -811,7 +811,7 @@ function handleClosed() {
|
||||
async function loadMasterData() {
|
||||
try {
|
||||
const [vehicleRes, carrierRes] = await Promise.all([
|
||||
vehicleApi.list({ vehicleStatus: 'available', excludeIneligibleCarrier: true }),
|
||||
vehicleApi.list({ vehicleStatus: 'available' }),
|
||||
carrierApi.list({ status: '1', page: 1, pageSize: 100 })
|
||||
])
|
||||
vehicleList.value = pickBxList<Vehicle>(vehicleRes)
|
||||
|
||||
@@ -24,13 +24,6 @@
|
||||
<el-option label="已终止" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核状态">
|
||||
<el-select v-model="searchForm.auditStatus" placeholder="全部" clearable>
|
||||
<el-option label="待审核" value="pending" />
|
||||
<el-option label="已通过" value="approved" />
|
||||
<el-option label="已驳回" value="rejected" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="filter-actions">
|
||||
<div class="filter-actions-end">
|
||||
@@ -67,14 +60,6 @@
|
||||
>
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
:disabled="selectedRows.length !== 1 || !canApproveCarrier(selectedRows[0])"
|
||||
:loading="selectedRows.length === 1 && auditLoadingMap[selectedRows[0].id]"
|
||||
@click="handleToolbarApprove"
|
||||
>
|
||||
<el-icon><Select /></el-icon>审核通过
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
@@ -157,19 +142,6 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('auditStatus')"
|
||||
label="审核状态"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getPlCarrierAuditStatusTagType(row.auditStatus)" size="small">
|
||||
{{ getPlCarrierAuditStatusLabel(row.auditStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('qualificationHint')"
|
||||
label="资质提示"
|
||||
@@ -322,14 +294,6 @@
|
||||
<el-button class="btn-main" type="primary" @click="handleEdit(viewingRow)">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canApproveCarrier(viewingRow)"
|
||||
class="btn-ghost"
|
||||
:loading="auditLoadingMap[viewingRow.id]"
|
||||
@click="handleApprove(viewingRow)"
|
||||
>
|
||||
<el-icon><Select /></el-icon>审核通过
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
@@ -345,7 +309,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Check, Close, Delete, Edit, Plus, RefreshLeft, Search, Select } from '@element-plus/icons-vue'
|
||||
import { Check, Close, Delete, Edit, Plus, RefreshLeft, Search } from '@element-plus/icons-vue'
|
||||
import { carrierApi, type Carrier } from '@/api/pl'
|
||||
import AttachmentUploadField from '@/components/business/attachment-upload-field/index.vue'
|
||||
import PlCarrierViewDialog from '@/components/business/pl-carrier-view-dialog/index.vue'
|
||||
@@ -356,11 +320,6 @@ import { useDbInstantSearch } from '@/composables/useDbInstantSearch'
|
||||
import { pickBxPageResult } from '@/utils/http/bx'
|
||||
import { DEFAULT_LIST_PAGE_SIZE } from '@/utils/table/tableConfig'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import {
|
||||
getPlCarrierAuditStatusLabel,
|
||||
getPlCarrierAuditStatusTagType
|
||||
} from '@/utils/pl-display'
|
||||
|
||||
const loading = ref(false)
|
||||
const quickSearchKeyword = ref('')
|
||||
|
||||
@@ -368,7 +327,6 @@ const listColumnDefs = [
|
||||
{ prop: 'contactName', label: '联系人' },
|
||||
{ prop: 'contactPhone', label: '联系电话' },
|
||||
{ prop: 'status', label: '合作状态' },
|
||||
{ prop: 'auditStatus', label: '审核状态' },
|
||||
{ prop: 'qualificationHint', label: '资质提示' },
|
||||
{ prop: 'transportAgreementExpireDate', label: '协议有效期' },
|
||||
{ prop: 'remark', label: '备注', defaultVisible: false }
|
||||
@@ -383,7 +341,6 @@ const {
|
||||
} = usePersistedListColumns('pl-carrier-list-columns', listColumnDefs)
|
||||
|
||||
const submitLoading = ref(false)
|
||||
const auditLoadingMap = reactive<Record<string, boolean>>({})
|
||||
const carrierList = ref<Carrier[]>([])
|
||||
const selectedRows = ref<Carrier[]>([])
|
||||
const dialogVisible = ref(false)
|
||||
@@ -400,8 +357,7 @@ const viewDialogRef = ref<InstanceType<typeof PlCarrierViewDialog>>()
|
||||
|
||||
const searchForm = reactive({
|
||||
q: '',
|
||||
status: '',
|
||||
auditStatus: ''
|
||||
status: ''
|
||||
})
|
||||
|
||||
const pagination = reactive({
|
||||
@@ -490,7 +446,6 @@ async function fetchData() {
|
||||
const res = await carrierApi.list({
|
||||
q: quickSearchKeyword.value.trim() || searchForm.q || undefined,
|
||||
status: searchForm.status || undefined,
|
||||
auditStatus: searchForm.auditStatus || undefined,
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize
|
||||
})
|
||||
@@ -513,7 +468,6 @@ function handleSearch() {
|
||||
function handleReset() {
|
||||
searchForm.q = ''
|
||||
searchForm.status = ''
|
||||
searchForm.auditStatus = ''
|
||||
quickSearchKeyword.value = ''
|
||||
selectedRows.value = []
|
||||
pagination.page = 1
|
||||
@@ -540,10 +494,6 @@ function handleSizeChange() {
|
||||
fetchData()
|
||||
}
|
||||
|
||||
function canApproveCarrier(row: Carrier) {
|
||||
return row.auditStatus !== 'approved' && row.qualificationComplete
|
||||
}
|
||||
|
||||
function syncViewingRowFromList() {
|
||||
if (!viewingRow.value?.id) return
|
||||
const updated = carrierList.value.find(row => row.id === viewingRow.value!.id)
|
||||
@@ -556,27 +506,6 @@ async function refreshViewIfOpen() {
|
||||
await viewDialogRef.value?.reload()
|
||||
}
|
||||
|
||||
async function handleApprove(row: Carrier) {
|
||||
if (!canApproveCarrier(row)) {
|
||||
ElMessage.warning('承运商资质不完整,无法审核通过')
|
||||
return
|
||||
}
|
||||
await ElMessageBox.confirm(
|
||||
`确认审核通过承运商「${row.carrierName}」?通过后其车辆可用于运输安排。`,
|
||||
'审核确认',
|
||||
{ type: 'info', confirmButtonText: '审核通过', cancelButtonText: '取消' }
|
||||
)
|
||||
auditLoadingMap[row.id] = true
|
||||
try {
|
||||
await carrierApi.approve(row.id)
|
||||
ElMessage.success('审核通过')
|
||||
await fetchData()
|
||||
await refreshViewIfOpen()
|
||||
} finally {
|
||||
auditLoadingMap[row.id] = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelectionChange(rows: Carrier[]) {
|
||||
selectedRows.value = rows
|
||||
}
|
||||
@@ -589,14 +518,6 @@ function handleToolbarEdit() {
|
||||
handleEdit(selectedRows.value[0])
|
||||
}
|
||||
|
||||
function handleToolbarApprove() {
|
||||
if (selectedRows.value.length !== 1) {
|
||||
ElMessage.warning('请选择一条承运商')
|
||||
return
|
||||
}
|
||||
handleApprove(selectedRows.value[0])
|
||||
}
|
||||
|
||||
function handleToolbarDelete() {
|
||||
if (selectedRows.value.length !== 1) {
|
||||
ElMessage.warning('请选择一条承运商')
|
||||
@@ -707,7 +628,7 @@ async function handleDelete(row: Carrier) {
|
||||
}
|
||||
|
||||
useDbInstantSearch(
|
||||
() => ({ q: searchForm.q, status: searchForm.status, auditStatus: searchForm.auditStatus }),
|
||||
() => ({ q: searchForm.q, status: searchForm.status }),
|
||||
handleSearch
|
||||
)
|
||||
|
||||
|
||||
Reference in new issue
Block a user