feat: 开票付款申请发票冲销改底部弹窗展示并选结算单带出项目利润率
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<teleport to="body">
|
||||
<transition name="el-fade-in-linear">
|
||||
<section v-if="modelValue" class="bottom-detail-panel" aria-label="详情面板">
|
||||
<header class="bottom-detail-panel__header">
|
||||
<h3>{{ title }}</h3>
|
||||
<el-tooltip content="关闭" placement="top">
|
||||
<el-button :icon="Close" text aria-label="关闭详情面板" @click="close" />
|
||||
</el-tooltip>
|
||||
</header>
|
||||
<div class="bottom-detail-panel__body">
|
||||
<slot />
|
||||
</div>
|
||||
<footer class="bottom-detail-panel__footer">
|
||||
<el-button @click="close">关闭</el-button>
|
||||
</footer>
|
||||
</section>
|
||||
</transition>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Close } from '@element-plus/icons-vue';
|
||||
|
||||
/**
|
||||
* 底部弹出详情面板(表单页通用)
|
||||
* 固定于视口底部并避让侧边栏,交互对齐应收/应付明细页点「单据号」弹出的单据详情面板
|
||||
*/
|
||||
export default {
|
||||
name: 'BottomDetailPanel',
|
||||
props: {
|
||||
modelValue: { type: Boolean, default: false },
|
||||
title: { type: String, default: '详情' },
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return { Close };
|
||||
},
|
||||
watch: {
|
||||
// 表单页多被 keep-alive 缓存,切换菜单时组件不销毁,需监听路由收起 teleport 到 body 的面板
|
||||
$route() {
|
||||
this.close();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('update:modelValue', false);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.bottom-detail-panel {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
bottom: 0;
|
||||
left: $sidebar_width;
|
||||
width: calc(100% - #{$sidebar_width});
|
||||
max-height: min(60vh, 560px);
|
||||
border-top: 1px solid #eff1f7;
|
||||
background: #fff;
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
:global(.avue--collapse) .bottom-detail-panel {
|
||||
left: $sidebar_collapse;
|
||||
width: calc(100% - #{$sidebar_collapse});
|
||||
}
|
||||
|
||||
:global(.avue-layout--horizontal) .bottom-detail-panel {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bottom-detail-panel__header {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #eff1f7;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
padding-left: 12px;
|
||||
border-left: 4px solid #409eff;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-detail-panel__body {
|
||||
max-height: calc(min(60vh, 560px) - 106px);
|
||||
padding: 16px 20px;
|
||||
overflow: auto;
|
||||
|
||||
:deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
}
|
||||
|
||||
:deep(.el-table__row:nth-child(even) td.el-table__cell) {
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-detail-panel__footer {
|
||||
display: flex;
|
||||
min-height: 57px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding: 0 20px;
|
||||
border-top: 1px solid #eff1f7;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 992px) {
|
||||
.bottom-detail-panel {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -43,7 +43,6 @@
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="!loading && !rows.length" class="invoice-write-off-table__empty">暂无冲销明细</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -134,12 +133,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.invoice-write-off-table__empty {
|
||||
padding: 24px 0;
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<el-input
|
||||
:model-value="profitRatePercent"
|
||||
:disabled="readonly"
|
||||
placeholder="选结算单后自动带出,可修改"
|
||||
placeholder="选结算单带出,可修改"
|
||||
@input="handleProfitRateInput"
|
||||
>
|
||||
<template #append>%</template>
|
||||
@@ -363,6 +363,11 @@
|
||||
</section-card>
|
||||
|
||||
<section-card title="开票明细">
|
||||
<template #extra>
|
||||
<el-button v-if="recordId" type="primary" @click="writeOffPanelVisible = true"
|
||||
>发票冲销</el-button
|
||||
>
|
||||
</template>
|
||||
<el-table
|
||||
ref="detailTable"
|
||||
:data="detailRows"
|
||||
@@ -412,9 +417,9 @@
|
||||
</el-table>
|
||||
</section-card>
|
||||
|
||||
<section-card v-if="recordId" title="发票冲销明细">
|
||||
<bottom-detail-panel v-model="writeOffPanelVisible" title="发票冲销明细">
|
||||
<invoice-write-off-table biz-type="invoice_apply" :biz-id="recordId" />
|
||||
</section-card>
|
||||
</bottom-detail-panel>
|
||||
|
||||
<section-card title="附件信息">
|
||||
<vehicle-attachment-table v-model="form.attachments" :readonly="readonly" />
|
||||
@@ -519,10 +524,12 @@ import * as api from '@/api/payment/invoiceApplication';
|
||||
import { getAll as getInvoiceItems } from '@/api/base/invoice-item';
|
||||
import { getList as getWaybillList } from '@/api/business/waybill-manage';
|
||||
import { getList as getReceivablePayableDetailList } from '@/api/settlement/receivable-payable-detail';
|
||||
import { getDetail as getProjectApplyDetail } from '@/api/business/project-apply';
|
||||
import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { invoiceApplicationDetailColumns } from '@/option/payment/invoiceApplication';
|
||||
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
|
||||
import InvoiceWriteOffTable from '@/components/invoice-write-off-table/main.vue';
|
||||
import BottomDetailPanel from '@/components/bottom-detail-panel/main.vue';
|
||||
import { getMkPublicDetail } from '@/api/mk-process';
|
||||
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
|
||||
|
||||
@@ -579,12 +586,14 @@ export default {
|
||||
components: {
|
||||
VehicleAttachmentTable,
|
||||
InvoiceWriteOffTable,
|
||||
BottomDetailPanel,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: emptyForm(),
|
||||
detailRows: [],
|
||||
selectedDetailIds: [],
|
||||
writeOffPanelVisible: false,
|
||||
receiverInvoiceOptions: [],
|
||||
contactOptions: [],
|
||||
departmentEmailOptions: [],
|
||||
@@ -978,11 +987,27 @@ export default {
|
||||
allocatedInvoiceAmount: 0,
|
||||
}));
|
||||
this.form.projectName = first.projectName;
|
||||
this.form.projectId = first.projectId;
|
||||
this.form.deptName = first.deptName;
|
||||
this.form.issuerName = first.issuerName;
|
||||
this.form.undertakingDeptName = first.deptName;
|
||||
this.settlementDialog.visible = false;
|
||||
await Promise.all([this.loadSettlementDetails(), this.loadReceiverInformation()]);
|
||||
await Promise.all([
|
||||
this.loadSettlementDetails(),
|
||||
this.loadReceiverInformation(),
|
||||
this.loadProjectProfitRate(),
|
||||
]);
|
||||
},
|
||||
// 项目利润率:选结算单后带出项目立项利润率(百分数转小数存 form),已手填时不覆盖
|
||||
async loadProjectProfitRate() {
|
||||
if (!this.form.projectId || Number(this.form.profitRate) > 0) return;
|
||||
try {
|
||||
const data = this.unwrapData(await getProjectApplyDetail(this.form.projectId));
|
||||
const rate = Number(data?.profitRate);
|
||||
if (Number.isFinite(rate) && rate > 0) this.form.profitRate = rate / 100;
|
||||
} catch {
|
||||
// 带出失败不阻断选单,保存时后端仍会兜底取项目立项利润率
|
||||
}
|
||||
},
|
||||
async loadSettlementDetails(resetSelection = true) {
|
||||
this.detailRows =
|
||||
|
||||
@@ -290,6 +290,11 @@
|
||||
</el-table>
|
||||
</section-card>
|
||||
<section-card v-if="showInvoiceSection" title="发票信息">
|
||||
<template #extra>
|
||||
<el-button v-if="recordId" type="primary" @click="writeOffPanelVisible = true"
|
||||
>发票冲销</el-button
|
||||
>
|
||||
</template>
|
||||
<el-table :data="form.invoices" border>
|
||||
<el-table-column type="index" label="序号" width="70" />
|
||||
<el-table-column prop="settlementNo" label="结算单号" min-width="120">
|
||||
@@ -350,9 +355,9 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
<section-card v-if="recordId" title="发票冲销明细">
|
||||
<bottom-detail-panel v-model="writeOffPanelVisible" title="发票冲销明细">
|
||||
<invoice-write-off-table biz-type="payment_receipt" :biz-id="recordId" />
|
||||
</section-card>
|
||||
</bottom-detail-panel>
|
||||
<section-card title="付款记录">
|
||||
<el-table :data="paymentRecords" border
|
||||
><el-table-column type="index" label="序号" width="70" /><el-table-column
|
||||
@@ -764,6 +769,7 @@ import {
|
||||
} from '@/utils/kingdee-attachment';
|
||||
import PdfPreview from '@/components/pdf-preview/main.vue';
|
||||
import InvoiceWriteOffTable from '@/components/invoice-write-off-table/main.vue';
|
||||
import BottomDetailPanel from '@/components/bottom-detail-panel/main.vue';
|
||||
|
||||
const attachmentViewerPlugins = [
|
||||
imagePlugin(),
|
||||
@@ -841,12 +847,14 @@ export default {
|
||||
OpenFileViewer,
|
||||
PdfPreview,
|
||||
InvoiceWriteOffTable,
|
||||
BottomDetailPanel,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: emptyForm(),
|
||||
amountSyncing: false,
|
||||
transferPayload: null,
|
||||
writeOffPanelVisible: false,
|
||||
// 金蝶侧发票附件查看/下载进行中(行组级 loading 守卫)
|
||||
kingdeeAttachmentBusy: false,
|
||||
referenceRows: [],
|
||||
|
||||
Reference in New Issue
Block a user