提交
This commit is contained in:
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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
Reference in new issue
Block a user