| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- <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.planType" placeholder="全部" clearable>
- <el-option label="直销单" value="direct" />
- <el-option label="入库单" value="inbound" />
- <el-option label="出库单" value="outbound" />
- </el-select>
- </el-form-item>
- <el-form-item label="车牌号">
- <el-input v-model="searchForm.licensePlate" placeholder="搜索车牌号" clearable />
- </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">{{ selectedRows.length }}</span> 项
- </div>
- <el-button
- class="btn-main"
- type="primary"
- :disabled="!selectedRows.length"
- :loading="createLoading"
- @click="handleCreateSettlement"
- >
- <el-icon><DocumentAdd /></el-icon>生成结算单
- </el-button>
- </div>
- </div>
- <div class="list-body list-wrap">
- <el-table
- class="list-table"
- :data="planList"
- v-loading="loading"
- stripe
- row-key="id"
- @selection-change="handleSelectionChange"
- >
- <el-table-column type="selection" min-width="48" align="center" />
- <el-table-column prop="planNo" label="计划编号" min-width="160" show-overflow-tooltip />
- <el-table-column prop="planDate" label="计划日期" min-width="120" align="center" />
- <el-table-column prop="planType" label="单据类型" min-width="100" align="center">
- <template #default="{ row }">
- <el-tag :type="getPlanTypeTagType(row.planType)" size="small">
- {{ getPlanTypeLabel(row.planType) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="客户/供应商" min-width="140" show-overflow-tooltip>
- <template #default="{ row }">
- {{ row.customerName || row.supplierName || '—' }}
- </template>
- </el-table-column>
- <el-table-column prop="licensePlate" label="车牌号" min-width="110" align="center" />
- <el-table-column prop="transportCompany" label="运输公司" min-width="140" show-overflow-tooltip />
- <el-table-column prop="freightAmount" label="运费(元)" min-width="120" align="right">
- <template #default="{ row }">{{ formatAmount(row.freightAmount) }}</template>
- </el-table-column>
- <el-table-column prop="archiveTime" label="归档时间" min-width="160" align="center">
- <template #default="{ row }">{{
- row.archiveTime ? formatDateTime(row.archiveTime) : '—'
- }}</template>
- </el-table-column>
- <el-table-column label="操作" min-width="100" fixed="right" align="center">
- <template #default="{ row }">
- <el-button link type="primary" @click="handleViewPlan(row)">
- <el-icon><View /></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>
- <PlPlanViewDialog v-model:visible="planViewVisible" :plan-id="viewPlanId" />
- </div>
- </template>
- <script setup lang="ts">
- import { DocumentAdd, RefreshLeft, Search, View } from '@element-plus/icons-vue'
- import { carrierApi, freightApi, type Carrier, type UnsettledPlanItem } from '@/api/pl'
- import PlPlanViewDialog from '@/components/business/pl-plan-view-dialog/index.vue'
- import { getPlanTypeLabel, getPlanTypeTagType } from '@/views/pl/freight/freight-status'
- import { formatMoneyDisplay } from '@/utils/money-format'
- import { formatDateTime } from '@/utils/format'
- const emit = defineEmits<{ created: [settlementId: string] }>()
- const loading = ref(false)
- const createLoading = ref(false)
- const carrierList = ref<Carrier[]>([])
- const planList = ref<UnsettledPlanItem[]>([])
- const selectedRows = ref<UnsettledPlanItem[]>([])
- const planViewVisible = ref(false)
- const viewPlanId = ref('')
- const searchForm = reactive({
- carrierId: '',
- q: '',
- planType: '',
- licensePlate: ''
- })
- 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.listUnsettledPlans({
- carrierId: searchForm.carrierId || undefined,
- q: searchForm.q || undefined,
- planType: searchForm.planType || undefined,
- licensePlate: searchForm.licensePlate || undefined,
- page: pagination.page,
- pageSize: pagination.pageSize
- })
- const data = res.data ?? res
- planList.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.planType = ''
- searchForm.licensePlate = ''
- 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 handleSelectionChange(rows: UnsettledPlanItem[]) {
- selectedRows.value = rows
- }
- function handleViewPlan(row: UnsettledPlanItem) {
- viewPlanId.value = row.id
- planViewVisible.value = true
- }
- async function handleCreateSettlement() {
- if (!selectedRows.value.length) return
- await ElMessageBox.confirm(
- `确定将选中的 ${selectedRows.value.length} 条计划生成一张结算单吗?`,
- '提示',
- { type: 'warning' }
- )
- createLoading.value = true
- try {
- const res = await freightApi.create({
- planIds: selectedRows.value.map((r) => r.id)
- })
- const settlement = (res.data ?? res) as { id: string; settlementNo?: string }
- ElMessage.success(`结算单 ${settlement.settlementNo || ''} 创建成功`)
- selectedRows.value = []
- emit('created', settlement.id)
- fetchData()
- } finally {
- createLoading.value = false
- }
- }
- function refresh() {
- fetchData()
- }
- onMounted(() => {
- loadCarrierList()
- fetchData()
- })
- defineExpose({ refresh })
- </script>
|