This commit is contained in:
zlwu committed 2026-08-30 18:33:13 +08:00
1 parent c8cec132bf
commit 19c5aaa8f5
95 files changed
+309129 -9838

No files matched your search

@@ -262,6 +262,42 @@
<span v-else class="money-display">¥{{ parseFloat(scope.row.taxAmount || 0).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column
label="已归档数量"
prop="archivedQty"
min-width="110"
align="right"
class-name="col-plan-qty"
label-class-name="col-plan-qty"
>
<template #default="{ row }">
<span class="plan-qty-num">{{ formatPlanQty(row.archivedQty) }}</span>
</template>
</el-table-column>
<el-table-column
label="未归档已安排"
prop="arrangedUnarchivedQty"
min-width="120"
align="right"
class-name="col-plan-qty"
label-class-name="col-plan-qty"
>
<template #default="{ row }">
<span class="plan-qty-num">{{ formatPlanQty(row.arrangedUnarchivedQty) }}</span>
</template>
</el-table-column>
<el-table-column
label="已安排合计"
prop="arrangedTotalQty"
min-width="110"
align="right"
class-name="col-plan-qty"
label-class-name="col-plan-qty"
>
<template #default="{ row }">
<span class="plan-qty-num">{{ formatPlanQty(row.arrangedTotalQty) }}</span>
</template>
</el-table-column>
<el-table-column label="包装规格" prop="packageSpec" min-width="150" :show-overflow-tooltip="true">
<template #default="scope">
<span>{{ scope.row.packageSpec || '-' }}</span>
@@ -397,6 +433,14 @@
<el-empty v-else description="加载中..." />
</el-tab-pane>
<!-- 运输计划 -->
<el-tab-pane label="运输计划" name="plans">
<PlContractLinkedPlansPanel
:contract-id="detailContract?.id"
:active="detailActiveTab === 'plans'"
/>
</el-tab-pane>
<!-- 回款记录 -->
<el-tab-pane label="回款记录" name="payment">
<div class="panel dialog-list-panel">
@@ -917,6 +961,7 @@ import UploadDialog from './UploadDialog.vue';
import ContractFormDialog from './ContractFormDialog.vue';
import ViewKvTable from '@/components/business/system-view-dialog/ViewKvTable.vue';
import type { ViewField } from '@/components/business/system-view-dialog/types';
import PlContractLinkedPlansPanel from '@/components/business/pl-contract-linked-plans-panel/index.vue';
import {
parseSettlementClauseDrafts,
resolveSettlementClauseContent
@@ -3092,6 +3137,12 @@ const handleGeneratePdfFromDialog = async () => {
onMounted(async () => {
await dictStore.loadAllDict();
});
function formatPlanQty(value: unknown) {
const n = parseFloat(String(value ?? 0))
if (Number.isNaN(n)) return '0.000'
return n.toFixed(3)
}
</script>
<style scoped lang="scss">
.framework-tier-detail-block {
@@ -3102,6 +3153,20 @@ onMounted(async () => {
color: var(--el-text-color-primary);
}
}
:deep(th.col-plan-qty),
:deep(td.col-plan-qty) {
color: #059669 !important;
font-weight: 600;
}
:deep(th.col-plan-qty) {
background: #ecfdf5 !important;
}
.plan-qty-num {
color: #059669;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.tier-letter-thumbs {
display: flex;
flex-wrap: wrap;
@@ -336,6 +336,42 @@
<span v-else>¥{{ parseFloat(scope.row.taxAmount || 0).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column
label="已归档数量"
prop="archivedQty"
min-width="110"
align="right"
class-name="col-plan-qty"
label-class-name="col-plan-qty"
>
<template #default="{ row }">
<span class="plan-qty-num">{{ formatPlanQty(row.archivedQty) }}</span>
</template>
</el-table-column>
<el-table-column
label="未归档已安排"
prop="arrangedUnarchivedQty"
min-width="120"
align="right"
class-name="col-plan-qty"
label-class-name="col-plan-qty"
>
<template #default="{ row }">
<span class="plan-qty-num">{{ formatPlanQty(row.arrangedUnarchivedQty) }}</span>
</template>
</el-table-column>
<el-table-column
label="已安排合计"
prop="arrangedTotalQty"
min-width="110"
align="right"
class-name="col-plan-qty"
label-class-name="col-plan-qty"
>
<template #default="{ row }">
<span class="plan-qty-num">{{ formatPlanQty(row.arrangedTotalQty) }}</span>
</template>
</el-table-column>
<el-table-column label="包装规格" prop="packageSpec" min-width="150" :show-overflow-tooltip="true">
<template #default="scope">
<span>{{ scope.row.packageSpec || '-' }}</span>
@@ -462,6 +498,14 @@
<el-empty v-else description="加载中..." />
</el-tab-pane>
<!-- 运输计划 -->
<el-tab-pane label="运输计划" name="plans">
<PlContractLinkedPlansPanel
:contract-id="contract?.id"
:active="activeTab === 'plans'"
/>
</el-tab-pane>
<!-- 回款记录 -->
<el-tab-pane label="回款记录" name="payment">
<el-button type="primary" icon="Plus" @click="handleAddPayment" class="mb-3">新增回款</el-button>
@@ -1092,6 +1136,7 @@ import ExecuteDialog from './components/ExecuteDialog.vue';
import InvalidDialog from './components/InvalidDialog.vue';
import RenewDialog from './components/RenewDialog.vue';
import UploadDialog from './components/UploadDialog.vue';
import PlContractLinkedPlansPanel from '@/components/business/pl-contract-linked-plans-panel/index.vue';
import CustomerDetailDialog from '@/views/crm/customer/CustomerDetailDialog.vue';
import ImagePreview from '@/components/ImagePreview/index.vue';
import TinyMceEditor from '@/components/TinyMceEditor/index.vue';
@@ -2902,10 +2947,30 @@ const handleGeneratePdfFile = async () => {
pdfGenerating.value = false;
}
};
function formatPlanQty(value: unknown) {
const n = parseFloat(String(value ?? 0))
if (Number.isNaN(n)) return '0.000'
return n.toFixed(3)
}
</script>
<style scoped lang="scss">
.contract-detail-page {
:deep(th.col-plan-qty),
:deep(td.col-plan-qty) {
color: #059669 !important;
font-weight: 600;
}
:deep(th.col-plan-qty) {
background: #ecfdf5 !important;
}
.plan-qty-num {
color: #059669;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.detail-subtitle {
margin: 0;
padding: 0 16px 12px;
+9 -59
View File
@@ -298,16 +298,8 @@
header-align="center"
>
<template #default="{ row }">
<div
v-if="
row.plan.canCopyToDriver ||
row.plan.canCopyToSite ||
row.plan.canCopyPoundQrcode
"
class="pl-plan-arrange-copy-cell"
>
<div v-if="row.plan.canCopyPoundQrcode" class="pl-plan-arrange-copy-cell">
<el-button
v-if="row.plan.canCopyPoundQrcode"
class="btn-ghost"
title="复制磅单二维码"
:loading="
@@ -317,28 +309,6 @@
>
磅单码
</el-button>
<el-button
v-if="row.plan.canCopyToDriver"
class="btn-ghost"
title="复制给司机"
:loading="
arrangeCopyLoadingId === row.plan.id && arrangeCopyLoadingAction === 'driver'
"
@click.stop="handleListCopyDriver(row.plan)"
>
司机
</el-button>
<el-button
v-if="row.plan.canCopyToSite"
class="btn-ghost"
title="复制给现场"
:loading="
arrangeCopyLoadingId === row.plan.id && arrangeCopyLoadingAction === 'site'
"
@click.stop="handleListCopySite(row.plan)"
>
现场
</el-button>
</div>
<span v-else>—</span>
</template>
@@ -932,31 +902,21 @@
poundQrcodePickVisible,
poundQrcodePickRecords,
loadArrangeActions,
copySiteSummary,
copyPlanSummary,
copyPoundSlipQrcode,
handlePoundQrcodePickCopy,
handlePoundQrcodePickPreview
} = usePlPlanArrangeActions()
const arrangeCopyLoadingId = ref('')
const arrangeCopyLoadingAction = ref<'driver' | 'site' | 'qrcode' | ''>('')
const arrangeCopyLoadingAction = ref<'qrcode' | ''>('')
type ArrangeCopyAction = 'driver' | 'site' | 'qrcode'
async function runListArrangeCopy(row: Plan, action: ArrangeCopyAction) {
async function handleListCopyPoundQrcode(row: Plan) {
if (!row.id || arrangeCopyLoadingId.value) return
arrangeCopyLoadingId.value = row.id
arrangeCopyLoadingAction.value = action
arrangeCopyLoadingAction.value = 'qrcode'
try {
await loadArrangeActions(row.id)
if (action === 'driver') {
await copyPlanSummary()
} else if (action === 'site') {
await copySiteSummary()
} else {
await copyPoundSlipQrcode()
}
await copyPoundSlipQrcode()
} catch {
ElMessage.error('复制失败,请稍后重试')
} finally {
@@ -965,18 +925,6 @@
}
}
function handleListCopyDriver(row: Plan) {
void runListArrangeCopy(row, 'driver')
}
function handleListCopySite(row: Plan) {
void runListArrangeCopy(row, 'site')
}
function handleListCopyPoundQrcode(row: Plan) {
void runListArrangeCopy(row, 'qrcode')
}
const selectedRows = ref<Plan[]>([])
const planStatsRowColumns = computed((): StatsRowColumn[] => {
@@ -1756,8 +1704,10 @@
background-color: #ecfdf5 !important;
}
tbody tr.pl-plan-list-row:hover > td.el-table__cell {
background-color: var(--el-table-row-hover-bg-color, #f1f5f9) !important;
/* 悬停用浅红;须压过斑马纹/装货段 !important 底色 */
tbody tr.pl-plan-list-row:hover > td.el-table__cell,
tbody tr.pl-plan-list-row.hover-row > td.el-table__cell {
background-color: #fee2e2 !important;
}
.pl-plan-list-row--plan-end > td {
+6 -1
View File
@@ -194,6 +194,10 @@
import { useMenuFavoriteStore } from '@/store/modules/menuFavorite'
import { useUserStore } from '@/store/modules/user'
import { refreshMenuBadges } from '@/utils/menu-badge-registry'
import {
getPortalHomeActiveModule,
setPortalHomeActiveModule
} from '@/utils/navigation/portal-home-active-module'
import {
collectPortalHomeSections,
findHomeCardByPath,
@@ -232,7 +236,7 @@
const { items: favItems } = storeToRefs(favStore)
const { counts: badgeCounts, loaded: badgeLoaded } = storeToRefs(badgeStore)
const activeModule = ref(FAV_KEY)
const activeModule = ref(getPortalHomeActiveModule() || FAV_KEY)
const favoriteList = ref<PortalHomeCardItem[]>([])
const favDragging = ref(false)
const suppressFavClick = ref(false)
@@ -393,6 +397,7 @@
}
watch(modules, ensureActiveModule, { immediate: true, deep: true })
watch(activeModule, (key) => setPortalHomeActiveModule(key))
watch([favItems, modules], syncFavoriteList, { immediate: true, deep: true })
onMounted(async () => {