拆分运费审批/出款页面,补充结算发票附件与菜单 SQL,并同步前后端模型与车辆相关展示。 Co-authored-by: Cursor <cursoragent@cursor.com>
291 lines
9.7 KiB
Vue
291 lines
9.7 KiB
Vue
<template>
|
|
<div class="freight-tab-panel">
|
|
<div class="filter-block">
|
|
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
|
<div class="filter-grid">
|
|
<el-form-item label="运输公司">
|
|
<el-select v-model="searchForm.carrierId" placeholder="全部" clearable filterable>
|
|
<el-option
|
|
v-for="c in carrierList"
|
|
:key="c.id"
|
|
:label="c.carrierName"
|
|
:value="c.id"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="结算单号">
|
|
<el-input
|
|
v-model="searchForm.q"
|
|
placeholder="搜索结算单号"
|
|
clearable
|
|
@keyup.enter="handleSearch"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="结算状态">
|
|
<el-select v-model="searchForm.settlementStatus" placeholder="全部" clearable>
|
|
<el-option label="草稿" value="pending" />
|
|
<el-option label="审批中" value="approving" />
|
|
<el-option label="待发放" value="approved" />
|
|
<el-option label="已发放" value="confirmed" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</div>
|
|
<div class="filter-actions">
|
|
<div class="filter-actions-end">
|
|
<el-button class="btn-ghost" :loading="loading" @click="handleReset">
|
|
<el-icon><RefreshLeft /></el-icon>重置
|
|
</el-button>
|
|
<el-button class="btn-main" type="primary" :loading="loading" @click="handleSearch">
|
|
<el-icon><Search /></el-icon>搜索
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</el-form>
|
|
</div>
|
|
|
|
<div class="list-toolbar">
|
|
<div class="list-toolbar-row">
|
|
<div class="list-toolbar-selected">已选 <span class="sel-num">0</span> 项</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="list-body list-wrap">
|
|
<el-table class="list-table" :data="settlementList" v-loading="loading" stripe row-key="id">
|
|
<el-table-column prop="settlementNo" label="结算单号" min-width="180" show-overflow-tooltip>
|
|
<template #default="{ row }">
|
|
<el-link type="primary" @click="handleView(row)">{{ row.settlementNo }}</el-link>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="totalFreight" label="运费合计(元)" min-width="130" align="right">
|
|
<template #default="{ row }">{{ formatAmount(row.totalFreight) }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="planCount" label="关联计划数" min-width="110" align="center" />
|
|
<el-table-column prop="licensePlateSummary" label="车牌摘要" min-width="140" show-overflow-tooltip />
|
|
<el-table-column prop="settlementStatus" label="结算状态" min-width="100" align="center">
|
|
<template #default="{ row }">
|
|
<el-tag :type="getSettlementStatusTagType(row.settlementStatus)" size="small">
|
|
{{ getSettlementStatusLabel(row.settlementStatus) }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="disburseAmount" label="发放金额(元)" min-width="130" align="right">
|
|
<template #default="{ row }">{{
|
|
row.disburseAmount ? formatAmount(row.disburseAmount) : '—'
|
|
}}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="disburseTime" label="发放时间" min-width="160" align="center">
|
|
<template #default="{ row }">{{
|
|
row.disburseTime ? formatDateTime(row.disburseTime) : '—'
|
|
}}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="currentApproverName" label="当前审批人" min-width="110" align="center">
|
|
<template #default="{ row }">{{ row.currentApproverName || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="submitterName" label="创建人" min-width="100" align="center">
|
|
<template #default="{ row }">{{ row.submitterName || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="createTime" label="创建时间" min-width="160" align="center">
|
|
<template #default="{ row }">{{ formatDateTime(row.createTime) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" min-width="320" fixed="right" align="center">
|
|
<template #default="{ row }">
|
|
<el-button link type="primary" @click="handleView(row)">
|
|
<el-icon><View /></el-icon>查看
|
|
</el-button>
|
|
<el-button
|
|
v-if="row.settlementStatus === 'pending'"
|
|
link
|
|
type="primary"
|
|
@click="handleEdit(row)"
|
|
>
|
|
<el-icon><Edit /></el-icon>编辑
|
|
</el-button>
|
|
<el-button
|
|
v-if="row.settlementStatus === 'approved'"
|
|
link
|
|
type="primary"
|
|
@click="handleEdit(row)"
|
|
>
|
|
<el-icon><Edit /></el-icon>发票信息
|
|
</el-button>
|
|
<el-button
|
|
v-if="row.settlementStatus === 'pending'"
|
|
link
|
|
type="primary"
|
|
@click="handleSubmit(row)"
|
|
>
|
|
<el-icon><Promotion /></el-icon>提交审批
|
|
</el-button>
|
|
<el-button
|
|
v-if="row.settlementStatus === 'pending'"
|
|
link
|
|
type="danger"
|
|
@click="handleDelete(row)"
|
|
>
|
|
<el-icon><Delete /></el-icon>删除
|
|
</el-button>
|
|
<el-button
|
|
v-if="row.canWithdraw"
|
|
link
|
|
type="warning"
|
|
@click="handleWithdraw(row)"
|
|
>
|
|
<el-icon><RefreshLeft /></el-icon>撤回
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div class="pagination list-pager-bar">
|
|
<el-pagination
|
|
v-model:current-page="pagination.page"
|
|
v-model:page-size="pagination.pageSize"
|
|
:total="pagination.total"
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
layout="total, sizes, prev, pager, next"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handlePageChange"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<PlFreightSettlementViewDialog ref="viewDialogRef" />
|
|
<PlFreightSettlementFormDialog ref="formDialogRef" @success="fetchData" />
|
|
<PlFreightApprovalDialog ref="approvalDialogRef" @success="fetchData" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {
|
|
Delete,
|
|
Edit,
|
|
Promotion,
|
|
RefreshLeft,
|
|
Search,
|
|
View
|
|
} from '@element-plus/icons-vue'
|
|
import { carrierApi, freightApi, type Carrier, type FreightSettlement } from '@/api/pl'
|
|
import PlFreightApprovalDialog from '@/components/business/pl-freight-approval-dialog/index.vue'
|
|
import PlFreightSettlementFormDialog from '@/components/business/pl-freight-settlement-form-dialog/index.vue'
|
|
import PlFreightSettlementViewDialog from '@/components/business/pl-freight-settlement-view-dialog/index.vue'
|
|
import {
|
|
getSettlementStatusLabel,
|
|
getSettlementStatusTagType
|
|
} from '@/views/pl/freight/freight-status'
|
|
import { formatMoneyDisplay } from '@/utils/money-format'
|
|
import { formatDateTime } from '@/utils/format'
|
|
|
|
const loading = ref(false)
|
|
const carrierList = ref<Carrier[]>([])
|
|
const settlementList = ref<FreightSettlement[]>([])
|
|
const viewDialogRef = ref<InstanceType<typeof PlFreightSettlementViewDialog>>()
|
|
const formDialogRef = ref<InstanceType<typeof PlFreightSettlementFormDialog>>()
|
|
const approvalDialogRef = ref<InstanceType<typeof PlFreightApprovalDialog>>()
|
|
|
|
const searchForm = reactive({
|
|
carrierId: '',
|
|
q: '',
|
|
settlementStatus: ''
|
|
})
|
|
|
|
const pagination = reactive({
|
|
page: 1,
|
|
pageSize: 20,
|
|
total: 0
|
|
})
|
|
|
|
function formatAmount(amount: number) {
|
|
if (!amount) return '¥0.00'
|
|
return formatMoneyDisplay(amount)
|
|
}
|
|
|
|
async function fetchData() {
|
|
loading.value = true
|
|
try {
|
|
const res = await freightApi.list({
|
|
tab: 'bills',
|
|
carrierId: searchForm.carrierId || undefined,
|
|
q: searchForm.q || undefined,
|
|
settlementStatus: searchForm.settlementStatus || undefined,
|
|
page: pagination.page,
|
|
pageSize: pagination.pageSize
|
|
})
|
|
const data = res.data ?? res
|
|
settlementList.value = data.list || []
|
|
pagination.total = data.total || 0
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function handleSearch() {
|
|
pagination.page = 1
|
|
fetchData()
|
|
}
|
|
|
|
function handleReset() {
|
|
searchForm.carrierId = ''
|
|
searchForm.q = ''
|
|
searchForm.settlementStatus = ''
|
|
pagination.page = 1
|
|
fetchData()
|
|
}
|
|
|
|
async function loadCarrierList() {
|
|
try {
|
|
const res = await carrierApi.list({ status: '1' })
|
|
carrierList.value = (res.data ?? res) || []
|
|
} catch {
|
|
carrierList.value = []
|
|
}
|
|
}
|
|
|
|
function handlePageChange() {
|
|
fetchData()
|
|
}
|
|
|
|
function handleSizeChange() {
|
|
pagination.page = 1
|
|
fetchData()
|
|
}
|
|
|
|
function handleView(row: FreightSettlement) {
|
|
viewDialogRef.value?.open(row.id)
|
|
}
|
|
|
|
function handleEdit(row: FreightSettlement) {
|
|
formDialogRef.value?.open(row.id)
|
|
}
|
|
|
|
function handleSubmit(row: FreightSettlement) {
|
|
approvalDialogRef.value?.openSubmit(row.id)
|
|
}
|
|
|
|
async function handleWithdraw(row: FreightSettlement) {
|
|
await ElMessageBox.confirm('确定撤回该结算单的审批吗?', '提示', { type: 'warning' })
|
|
await freightApi.withdrawApproval(row.id)
|
|
ElMessage.success('已撤回')
|
|
fetchData()
|
|
}
|
|
|
|
async function handleDelete(row: FreightSettlement) {
|
|
await ElMessageBox.confirm('确定删除该草稿结算单吗?关联运输单将释放。', '提示', {
|
|
type: 'warning'
|
|
})
|
|
await freightApi.delete(row.id)
|
|
ElMessage.success('删除成功')
|
|
fetchData()
|
|
}
|
|
|
|
function refresh() {
|
|
fetchData()
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadCarrierList()
|
|
fetchData()
|
|
})
|
|
|
|
defineExpose({ refresh })
|
|
</script>
|