|
|
|
|
@ -76,7 +76,7 @@
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
<div class="header-left">
|
|
|
|
|
<i class="el-icon-shopping-cart-full section-icon"></i>
|
|
|
|
|
<span class="section-title">采购信息</span>
|
|
|
|
|
<span class="section-title">已采购信息</span>
|
|
|
|
|
<el-tag v-if="purchaseTotal > 0" type="info" size="small" class="count-tag"> {{ purchaseTotal }} 条 </el-tag>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="header-actions">
|
|
|
|
|
@ -128,6 +128,56 @@
|
|
|
|
|
@pagination="loadPurchaseList"
|
|
|
|
|
class="pagination-wrapper"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div class="purchase-material-section">
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
<div class="header-left">
|
|
|
|
|
<i class="el-icon-tickets section-icon"></i>
|
|
|
|
|
<span class="section-title">未采购物料清单</span>
|
|
|
|
|
<el-tag v-if="purchaseMaterialList.length > 0" type="info" size="small" class="count-tag">
|
|
|
|
|
{{ purchaseMaterialList.length }} 条
|
|
|
|
|
</el-tag>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-table
|
|
|
|
|
:data="purchaseMaterialList"
|
|
|
|
|
size="default"
|
|
|
|
|
border
|
|
|
|
|
stripe
|
|
|
|
|
v-loading="loadingPurchase"
|
|
|
|
|
class="data-table purchase-material-table"
|
|
|
|
|
:row-class-name="getPurchaseMaterialRowClass"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
|
|
|
|
<el-table-column label="物料编号" prop="materialCode" width="160" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="物料名称" prop="materialName" min-width="180" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="销售物料名称" prop="saleMaterialName" min-width="160" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="规格描述" prop="specificationDescription" min-width="180" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="单位" prop="unitName" width="100" align="center" />
|
|
|
|
|
<el-table-column label="合同数量" prop="contractAmount" width="120" align="right">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
{{ formatAmount(scope.row.contractAmount) }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="已采购数量" prop="purchasedAmount" width="120" align="right">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
{{ formatAmount(scope.row.purchasedAmount) }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="未采购数量" prop="unpurchasedAmount" width="120" align="right">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
{{ formatAmount(scope.row.unpurchasedAmount) }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
<el-empty
|
|
|
|
|
v-if="!loadingPurchase && purchaseMaterialList.length === 0"
|
|
|
|
|
description="暂无合同物料信息"
|
|
|
|
|
class="empty-state"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
|
|
@ -283,7 +333,8 @@
|
|
|
|
|
<script setup lang="ts" name="OrderLedger">
|
|
|
|
|
import { computed, reactive, ref, watch } from 'vue';
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
import { getContractOrder } from '@/api/oa/erp/contractOrder';
|
|
|
|
|
import { getContractOrder, getContractOrderPurchaseMaterialList } from '@/api/oa/erp/contractOrder';
|
|
|
|
|
import { ContractOrderPurchaseMaterialVO } from '@/api/oa/erp/contractOrder/types';
|
|
|
|
|
import { getContractInfo } from '@/api/oa/erp/contractInfo';
|
|
|
|
|
import { ContractInfoVO } from '@/api/oa/erp/contractInfo/types';
|
|
|
|
|
import { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
|
|
|
|
|
@ -346,6 +397,7 @@ const planStageList = ref<ErpProjectPlanStageForm[]>([]);
|
|
|
|
|
const paymentStageList = ref<PaymentStageVO[]>([]);
|
|
|
|
|
const purchaseList = ref<ProjectPurchaseVO[]>([]);
|
|
|
|
|
const invoiceList = ref<FinInvoiceInfoVO[]>([]);
|
|
|
|
|
const purchaseMaterialList = ref<ContractOrderPurchaseMaterialVO[]>([]);
|
|
|
|
|
|
|
|
|
|
const activeTab = ref('contract');
|
|
|
|
|
const loadedTabs = ref<Set<string>>(new Set(['contract']));
|
|
|
|
|
@ -374,6 +426,17 @@ const formatNumber = (num: number) => {
|
|
|
|
|
return num?.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formatAmount = (num?: number | string | null) => {
|
|
|
|
|
if (num === null || num === undefined || num === '') {
|
|
|
|
|
return '0.00';
|
|
|
|
|
}
|
|
|
|
|
const value = Number(num);
|
|
|
|
|
if (Number.isNaN(value)) {
|
|
|
|
|
return '0.00';
|
|
|
|
|
}
|
|
|
|
|
return value.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 返回 */
|
|
|
|
|
const handleBack = () => {
|
|
|
|
|
proxy?.$tab.closePage(route);
|
|
|
|
|
@ -442,26 +505,42 @@ const loadOrderAndContract = async () => {
|
|
|
|
|
|
|
|
|
|
/** 加载采购信息 */
|
|
|
|
|
const loadPurchaseList = async () => {
|
|
|
|
|
const contractId = orderInfo.value.contractId;
|
|
|
|
|
const contractId = orderInfo.value?.contractId ?? contractInfo.value?.contractId;
|
|
|
|
|
if (!contractId && !projectId.value) {
|
|
|
|
|
purchaseList.value = [];
|
|
|
|
|
purchaseTotal.value = 0;
|
|
|
|
|
purchaseMaterialList.value = [];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 优先按合同ID查询采购
|
|
|
|
|
purchaseQuery.relationId = contractId ? contractId : undefined;
|
|
|
|
|
loadingPurchase.value = true;
|
|
|
|
|
try {
|
|
|
|
|
const res: any = await listProjectPurchase({
|
|
|
|
|
...purchaseQuery
|
|
|
|
|
});
|
|
|
|
|
purchaseList.value = res.rows || [];
|
|
|
|
|
purchaseTotal.value = res.total || 0;
|
|
|
|
|
const [purchaseRes, materialRes] = await Promise.all([
|
|
|
|
|
listProjectPurchase({
|
|
|
|
|
...purchaseQuery
|
|
|
|
|
}),
|
|
|
|
|
getContractOrderPurchaseMaterialList(projectId.value as string | number)
|
|
|
|
|
]);
|
|
|
|
|
purchaseList.value = purchaseRes.rows || [];
|
|
|
|
|
purchaseTotal.value = purchaseRes.total || 0;
|
|
|
|
|
purchaseMaterialList.value = materialRes.data || [];
|
|
|
|
|
} finally {
|
|
|
|
|
loadingPurchase.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getPurchaseMaterialRowClass = ({ row }: { row: { unpurchasedAmount?: number | string | null } }) => {
|
|
|
|
|
const unpurchasedAmount = Number(row.unpurchasedAmount ?? 0);
|
|
|
|
|
if (unpurchasedAmount === 0) {
|
|
|
|
|
return 'purchase-row-success';
|
|
|
|
|
}
|
|
|
|
|
if (unpurchasedAmount > 0) {
|
|
|
|
|
return 'purchase-row-warning';
|
|
|
|
|
}
|
|
|
|
|
return '';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 加载开票信息 */
|
|
|
|
|
const loadInvoiceList = async () => {
|
|
|
|
|
if (!projectId.value) {
|
|
|
|
|
@ -675,6 +754,20 @@ watch(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.purchase-material-section {
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.purchase-material-table {
|
|
|
|
|
:deep(.el-table__body tr.purchase-row-success > td.el-table__cell) {
|
|
|
|
|
background-color: #f0f9eb !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.el-table__body tr.purchase-row-warning > td.el-table__cell) {
|
|
|
|
|
background-color: #fdf6ec !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.empty-state {
|
|
|
|
|
padding: 40px 0;
|
|
|
|
|
}
|
|
|
|
|
|