流程设置人员替换搜索迭代

master
weizong song 3 weeks ago
parent 3ae371f458
commit 89cab840d2

@ -363,6 +363,7 @@ watch(
.muted {
color: #909399;
}
.related-expenditure-block {
margin-top: 12px;
}
@ -371,4 +372,3 @@ watch(
margin-bottom: 20px;
}
</style>

@ -670,6 +670,11 @@ export const paymentAPI = {
getDetail: (id) => {
return request.get(`/budget/payments/${id}`)
},
// 获取支付审计记录
getAudits: (id, params) => {
return request.get(`/budget/payments/${id}/audits`, params)
},
// 创建支付流程
create: (data) => {

@ -72,6 +72,19 @@
</span>
</template>
</el-table-column>
<el-table-column label="关联非直接支付" width="240" show-overflow-tooltip>
<template #default="{ row }">
<template v-if="getRelatedIndirectPayments(row).length">
<el-link type="primary" @click="openViewDialog(row)">
{{ getRelatedIndirectPayments(row)[0].name || getRelatedIndirectPayments(row)[0].serial_number || `非直接支付#${getRelatedIndirectPayments(row)[0].id}` }}
</el-link>
<span v-if="getRelatedIndirectPayments(row).length > 1" class="related-payment-more">
{{ getRelatedIndirectPayments(row).length }}
</span>
</template>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="main_content" label="合同主要内容" min-width="150" />
<el-table-column prop="party_a" label="甲方" width="150" />
<el-table-column prop="party_b" label="乙方" width="150" />
@ -208,11 +221,11 @@
<el-form :model="form" :rules="rules" ref="formRef" label-width="140px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="合同编号" prop="contract_no">
<el-input v-model="form.contract_no_without_prefix">
<template #prepend>CZHT</template>
</el-input>
</el-form-item>
<el-form-item label="合同编号" prop="contract_no_without_prefix">
<el-input v-model="form.contract_no_without_prefix">
<template #prepend>CZHT</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="合同名称" prop="title">
@ -579,6 +592,43 @@
<span v-else>-</span>
</el-descriptions-item>
</el-descriptions>
<el-divider content-position="left">关联非直接支付</el-divider>
<el-table
v-if="getRelatedIndirectPayments(viewData).length"
:data="getRelatedIndirectPayments(viewData)"
border
size="small"
style="width: 100%"
>
<el-table-column prop="name" label="非直接支付名称" min-width="220" show-overflow-tooltip />
<el-table-column prop="serial_number" label="支付编号" width="180" show-overflow-tooltip />
<el-table-column prop="amount" label="金额" width="140" align="right">
<template #default="{ row }">
{{ formatAmount(row.amount) }}
</template>
</el-table-column>
<el-table-column prop="status_text" label="状态" width="110">
<template #default="{ row }">
<el-tag :type="getPaymentStatusTagType(row.status)" size="small">
{{ row.status_text || row.status || '-' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="payment_category_name" label="付款分类" width="140" show-overflow-tooltip />
<el-table-column prop="oa_flow_title" label="OA流程" min-width="180" show-overflow-tooltip />
<el-table-column prop="created_at" label="创建时间" width="170">
<template #default="{ row }">
{{ formatDateTime(row.created_at) }}
</template>
</el-table-column>
<el-table-column label="操作" width="100" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="openRelatedPayment(row)"></el-button>
</template>
</el-table-column>
</el-table>
<el-empty v-else description="暂无关联非直接支付" />
<el-divider content-position="left">付款计划</el-divider>
<el-table :data="viewData.pay_plans || []" border size="small" style="width: 100%">
@ -1271,7 +1321,18 @@ const importColumnGuide = ref([
])
const rules = {
contract_no: [{ required: true, message: '请填写合同编号', trigger: 'blur' }],
contract_no_without_prefix: [
{
validator: (rule, value, callback) => {
if (!value || !String(value).trim()) {
callback(new Error('请填写合同编号'))
} else {
callback()
}
},
trigger: ['blur', 'change']
}
],
title: [{ required: true, message: '请填写合同名称', trigger: 'blur' }],
main_content: [{ required: true, message: '请填写合同主要内容', trigger: 'blur' }],
party_a: [{ required: true, message: '请填写甲方', trigger: 'blur' }],
@ -2423,6 +2484,36 @@ function formatAmount(amount) {
})
}
function getRelatedIndirectPayments(contract) {
return Array.isArray(contract?.related_indirect_payments)
? contract.related_indirect_payments
: []
}
function formatDateTime(value) {
if (!value) return '-'
const date = new Date(value)
if (Number.isNaN(date.getTime())) return String(value)
const pad = (n) => String(n).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
}
function getPaymentStatusTagType(status) {
if (status === 'completed') return 'success'
if (status === 'rejected') return 'danger'
if (status === 'processing') return 'warning'
return 'info'
}
function openRelatedPayment(payment) {
if (!payment?.id) {
ElMessage.warning('缺少支付记录ID')
return
}
const base = `${window.location.origin}${window.location.pathname}`
window.open(`${base}#/payment/payment-detail-print/${payment.id}`, '_blank')
}
// ID
function getUserName(userId) {
if (!userId) return '-'
@ -3891,6 +3982,12 @@ onMounted(() => {
margin-top: 4px;
}
.related-payment-more {
margin-left: 6px;
color: #909399;
font-size: 12px;
}
:deep(.error-row) {
background-color: #fef0f0;
}
@ -3929,4 +4026,3 @@ onMounted(() => {
color: #606266;
}
</style>

@ -260,7 +260,7 @@
<!-- 合同选择直接支付且分类需要关联合同 -->
<el-form-item
v-if="isDirectPayment && selectedCategory?.need_contract"
v-if="isDirectPayment && allowsContractSelection(selectedCategory)"
label="关联合同"
>
<div v-if="!selectedContract" class="contract-selector-wrapper">
@ -900,6 +900,19 @@ const submitSuccessPayment = ref(null) // 成功后返回的支付单信息(
const selectedContract = ref(null)
const showContractSelector = ref(false)
const getContractRequirement = (category) => {
if (!category) return 'none'
return category.contract_requirement || (category.need_contract ? 'required' : 'none')
}
const allowsContractSelection = (category) => {
return ['optional', 'required'].includes(getContractRequirement(category))
}
const requiresContractSelection = (category) => {
return getContractRequirement(category) === 'required'
}
//
const formatAmount = (amount) => {
if (amount === null || amount === undefined) return '-'
@ -923,7 +936,7 @@ const checkFieldDisplayConditionsWithContract = (element, contract = null) => {
// need_contract amount_total
// amount
let contractTotalAmount
if (selectedCategory.value?.need_contract && contract) {
if (allowsContractSelection(selectedCategory.value) && contract) {
contractTotalAmount = contract.amount_total || 0
} else {
contractTotalAmount = currentPaymentAmount
@ -984,7 +997,7 @@ const checkFieldDisplayConditionsWithContract = (element, contract = null) => {
//
const checkFieldDisplayChangeByContract = (newContract) => {
if (!selectedCategory.value?.need_contract || !templateElements.value || templateElements.value.length === 0) {
if (!allowsContractSelection(selectedCategory.value) || !templateElements.value || templateElements.value.length === 0) {
return { hasChange: false, changedFields: [] }
}
@ -1269,7 +1282,7 @@ const checkFieldDisplayConditions = (element) => {
display_conditions: element?.display_conditions,
formDataAmount: formData.amount,
selectedCategory: selectedCategory.value,
need_contract: selectedCategory.value?.need_contract,
contract_requirement: getContractRequirement(selectedCategory.value),
selectedContract: selectedContract.value,
contractAmountTotal: selectedContract.value?.amount_total
})
@ -1287,7 +1300,7 @@ const checkFieldDisplayConditions = (element) => {
// need_contract amount_total
// amount
let contractTotalAmount
if (selectedCategory.value?.need_contract && selectedContract.value) {
if (allowsContractSelection(selectedCategory.value) && selectedContract.value) {
contractTotalAmount = selectedContract.value.amount_total || 0
console.log('[checkFieldDisplayConditions] 使用合同总金额:', contractTotalAmount)
} else {
@ -2300,12 +2313,12 @@ const handleNextStep = async () => {
return
}
//
if (isDirectPayment.value && selectedCategory.value?.need_contract) {
if (!selectedContract.value) {
ElMessage.warning('请选择关联合同')
return
}
//
if (isDirectPayment.value && requiresContractSelection(selectedCategory.value) && !selectedContract.value) {
ElMessage.warning('请选择关联合同')
return
}
if (isDirectPayment.value && selectedContract.value) {
//
if (selectedContract.value.amount_type === 'open') {
ElMessageBox.alert(
@ -2662,13 +2675,13 @@ const autoCreatePayment = async () => {
return
}
//
if (isDirectPayment.value && selectedCategory.value?.need_contract) {
if (!selectedContract.value) {
ElMessage.warning('已创建OA流程但缺少关联合同请选择合同后手动提交')
autoSubmitFailed.value = true
return
}
//
if (isDirectPayment.value && requiresContractSelection(selectedCategory.value) && !selectedContract.value) {
ElMessage.warning('已创建OA流程但缺少关联合同请选择合同后手动提交')
autoSubmitFailed.value = true
return
}
if (isDirectPayment.value && selectedContract.value) {
if (selectedContract.value.amount_type === 'open') {
ElMessage.warning('已创建OA流程但合同类型不符合要求请手动提交')
autoSubmitFailed.value = true
@ -2873,12 +2886,12 @@ const handleSubmit = async () => {
return
}
//
if (isDirectPayment.value && selectedCategory.value?.need_contract) {
if (!selectedContract.value) {
ElMessage.warning('请选择关联合同')
return
}
//
if (isDirectPayment.value && requiresContractSelection(selectedCategory.value) && !selectedContract.value) {
ElMessage.warning('请选择关联合同')
return
}
if (isDirectPayment.value && selectedContract.value) {
//
if (selectedContract.value.amount_type === 'open') {
ElMessageBox.alert(
@ -3627,4 +3640,3 @@ onUnmounted(() => {
justify-content: flex-end;
}
</style>

@ -594,9 +594,9 @@
</template>
</el-card>
<!-- 合同选择如果所选的事前流程分支的need_contract为true -->
<!-- 合同选择如果所选的事前流程分支允许关联合同 -->
<el-card
v-if="selectedCategory?.need_contract"
v-if="allowsContractSelection(selectedCategory)"
class="form-section"
shadow="never"
>
@ -886,9 +886,9 @@
</div>
</el-form-item>
<!-- 合同选择支付分类需要关联合同时 -->
<!-- 合同选择支付分类允许关联合同时 -->
<el-form-item
v-if="selectedPaymentCategory?.need_contract"
v-if="allowsContractSelection(selectedPaymentCategory)"
label="关联合同"
>
<!-- 如果第三步已选择合同则复用第三步的合同且不可更改 -->
@ -1979,6 +1979,19 @@ const loadingCategoryTree = ref(false)
const categoryTreeData = ref(null)
const selectedCategory = ref(null)
const getContractRequirement = (category) => {
if (!category) return 'none'
return category.contract_requirement || (category.need_contract ? 'required' : 'none')
}
const allowsContractSelection = (category) => {
return ['optional', 'required'].includes(getContractRequirement(category))
}
const requiresContractSelection = (category) => {
return getContractRequirement(category) === 'required'
}
// need_contract true
const selectedExpenditureContract = ref(null)
const showExpenditureContractSelector = ref(false)
@ -4392,20 +4405,20 @@ const nextStep = async () => {
return
}
// need_contracttrue
if (selectedCategory.value?.need_contract) {
if (!selectedExpenditureContract.value) {
ElMessage.warning('请选择关联合同')
return
}
//
if (requiresContractSelection(selectedCategory.value) && !selectedExpenditureContract.value) {
ElMessage.warning('请选择关联合同')
return
}
if (selectedExpenditureContract.value) {
const paymentCount = selectedExpenditureContract.value.payment_stats?.payment_count || 0
const paidAmount = Number(selectedExpenditureContract.value.payment_stats?.paid_amount || 0)
//
if (paidAmount > 0 || paymentCount > 0) {
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
await ElMessageBox.alert(
'该合同已关联过非直接支付,不允许再次关联。请选择其他合同。',
buildContractLinkedIndirectPaymentMessage(selectedExpenditureContract.value),
'提示',
{
confirmButtonText: '确定',
@ -4460,20 +4473,20 @@ const nextStep = async () => {
return
}
// need_contracttrue
if (selectedCategory.value?.need_contract) {
if (!selectedExpenditureContract.value) {
ElMessage.warning('请选择关联合同')
return
}
//
if (requiresContractSelection(selectedCategory.value) && !selectedExpenditureContract.value) {
ElMessage.warning('请选择关联合同')
return
}
if (selectedExpenditureContract.value) {
const paymentCount = selectedExpenditureContract.value.payment_stats?.payment_count || 0
const paidAmount = Number(selectedExpenditureContract.value.payment_stats?.paid_amount || 0)
//
if (paidAmount > 0 || paymentCount > 0) {
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
await ElMessageBox.alert(
'该合同已关联过非直接支付,不允许再次关联。请选择其他合同。',
buildContractLinkedIndirectPaymentMessage(selectedExpenditureContract.value),
'提示',
{
confirmButtonText: '确定',
@ -4519,7 +4532,7 @@ const nextStep = async () => {
currentStep.value++
//
if (selectedPaymentCategory.value?.need_contract) {
if (allowsContractSelection(selectedPaymentCategory.value)) {
// 使使使
const actualContract = isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value
@ -4530,9 +4543,9 @@ const nextStep = async () => {
const paidAmount = Number(actualContract.payment_stats?.paid_amount || 0)
//
if (paidAmount > 0 || paymentCount > 0) {
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
await ElMessageBox.alert(
'该合同已关联过非直接支付,不允许再次关联。请选择其他合同。',
buildContractLinkedIndirectPaymentMessage(actualContract),
'提示',
{
confirmButtonText: '确定',
@ -4568,21 +4581,23 @@ const nextStep = async () => {
}
//
if (selectedPaymentCategory.value?.need_contract) {
if (requiresContractSelection(selectedPaymentCategory.value) && !(isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value)) {
ElMessage.warning('请选择关联合同')
return
}
if (allowsContractSelection(selectedPaymentCategory.value)) {
// 使使使
const actualContract = isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value
if (!actualContract) {
ElMessage.warning('请选择关联合同')
return
}
const paymentCount = actualContract.payment_stats?.payment_count || 0
const paidAmount = Number(actualContract.payment_stats?.paid_amount || 0)
//
if (paidAmount > 0 || paymentCount > 0) {
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
await ElMessageBox.alert(
'该合同已关联过非直接支付,不允许再次关联。请选择其他合同。',
buildContractLinkedIndirectPaymentMessage(actualContract),
'提示',
{
confirmButtonText: '确定',
@ -4672,10 +4687,8 @@ const canNextStep = computed(() => {
}
// need_contracttrue
if (selectedCategory.value?.need_contract) {
if (!selectedExpenditureContract.value) {
return false
}
if (requiresContractSelection(selectedCategory.value) && !selectedExpenditureContract.value) {
return false
}
return true
}
@ -4693,7 +4706,7 @@ const canNextStep = computed(() => {
return false
}
//
if (selectedPaymentCategory.value?.need_contract) {
if (requiresContractSelection(selectedPaymentCategory.value)) {
// 使使
const actualContract = isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value
if (!actualContract) {
@ -5369,8 +5382,8 @@ const loadPaymentTemplateElements = async () => {
if (response.code === 0) {
paymentTemplateElements.value = response.data || []
//
if (selectedCategory.value?.need_contract && selectedExpenditureContract.value && selectedPaymentCategory.value?.need_contract) {
//
if (allowsContractSelection(selectedCategory.value) && selectedExpenditureContract.value && allowsContractSelection(selectedPaymentCategory.value)) {
selectedPaymentContract.value = selectedExpenditureContract.value
}
@ -5435,33 +5448,36 @@ const checkAndAutoProceedFromStep5 = async () => {
return //
}
//
if (selectedPaymentCategory.value?.need_contract) {
//
if (allowsContractSelection(selectedPaymentCategory.value)) {
// 使使使
const actualContract = isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value
if (!actualContract) {
if (requiresContractSelection(selectedPaymentCategory.value)) {
console.log('checkAndAutoProceedFromStep5: 合同未选择,跳过')
return
}
console.log('checkAndAutoProceedFromStep5: 合同未选择,跳过')
return //
}
const paymentCount = actualContract.payment_stats?.payment_count || 0
const paidAmount = Number(actualContract.payment_stats?.paid_amount || 0)
//
if (paidAmount > 0 || paymentCount > 0) {
console.log('checkAndAutoProceedFromStep5: 合同已关联过,跳过')
return //
}
//
const remainingAmount = isPaymentContractReused.value
? reusedPaymentContractRemainingAmount.value
: paymentContractRemainingAmount.value
const paymentAmount = Number(paymentFormData.amount) || 0
if (paymentAmount > remainingAmount) {
console.log('checkAndAutoProceedFromStep5: 金额超过剩余金额,跳过', paymentAmount, remainingAmount)
return //
} else {
const paymentCount = actualContract.payment_stats?.payment_count || 0
const paidAmount = Number(actualContract.payment_stats?.paid_amount || 0)
//
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
console.log('checkAndAutoProceedFromStep5: 合同已关联过,跳过')
return //
}
//
const remainingAmount = isPaymentContractReused.value
? reusedPaymentContractRemainingAmount.value
: paymentContractRemainingAmount.value
const paymentAmount = Number(paymentFormData.amount) || 0
if (paymentAmount > remainingAmount) {
console.log('checkAndAutoProceedFromStep5: 金额超过剩余金额,跳过', paymentAmount, remainingAmount)
return //
}
}
}
@ -6036,15 +6052,17 @@ const autoFinalSubmit = async () => {
return
}
//
if (selectedPaymentCategory.value?.need_contract) {
//
if (requiresContractSelection(selectedPaymentCategory.value) && !(isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value)) {
ElMessage.warning('已创建OA流程但缺少关联合同请选择合同后手动提交')
autoSubmitFailed.value = true
return
}
if (allowsContractSelection(selectedPaymentCategory.value)) {
const actualContract = isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value
if (!actualContract) {
ElMessage.warning('已创建OA流程但缺少关联合同请选择合同后手动提交')
autoSubmitFailed.value = true
return
}
if (actualContract.amount_type === 'fixed') {
//
} else if (actualContract.amount_type === 'fixed') {
const remainingAmount = isPaymentContractReused.value
? reusedPaymentContractRemainingAmount.value
: paymentContractRemainingAmount.value
@ -6065,12 +6083,12 @@ const autoFinalSubmit = async () => {
const amountNumber = Number(paymentFormData.amount)
// IDneed_contracttrue
const expenditureContractId = selectedCategory.value?.need_contract && selectedExpenditureContract.value
const expenditureContractId = allowsContractSelection(selectedCategory.value) && selectedExpenditureContract.value
? selectedExpenditureContract.value.id
: null
// IDneed_contracttrue
const paymentDetailContractId = selectedPaymentCategory.value?.need_contract
const paymentDetailContractId = allowsContractSelection(selectedPaymentCategory.value)
? (isPaymentContractReused.value
? reusedPaymentContract.value?.id
: selectedPaymentContract.value?.id)
@ -6198,24 +6216,27 @@ const handleFinalSubmit = async () => {
return
}
//
if (selectedPaymentCategory.value?.need_contract) {
//
if (requiresContractSelection(selectedPaymentCategory.value) && !(isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value)) {
ElMessage.warning('请选择关联合同')
return
}
if (allowsContractSelection(selectedPaymentCategory.value)) {
// 使使使
const actualContract = isPaymentContractReused.value ? reusedPaymentContract.value : selectedPaymentContract.value
if (!actualContract) {
ElMessage.warning('请选择关联合同')
return
}
//
} else {
//
if (actualContract.amount_type === 'fixed') {
const remainingAmount = isPaymentContractReused.value
? reusedPaymentContractRemainingAmount.value
: paymentContractRemainingAmount.value
const paymentAmount = Number(paymentFormData.amount) || 0
if (paymentAmount > remainingAmount) {
ElMessage.warning(`本次支付金额不能超过合同剩余金额 ${formatAmount(remainingAmount)}`)
return
if (actualContract.amount_type === 'fixed') {
const remainingAmount = isPaymentContractReused.value
? reusedPaymentContractRemainingAmount.value
: paymentContractRemainingAmount.value
const paymentAmount = Number(paymentFormData.amount) || 0
if (paymentAmount > remainingAmount) {
ElMessage.warning(`本次支付金额不能超过合同剩余金额 ${formatAmount(remainingAmount)}`)
return
}
}
}
}
@ -6243,12 +6264,12 @@ const handleFinalSubmit = async () => {
const amountNumber = Number(paymentFormData.amount)
// IDneed_contracttrue
const expenditureContractId = selectedCategory.value?.need_contract && selectedExpenditureContract.value
const expenditureContractId = allowsContractSelection(selectedCategory.value) && selectedExpenditureContract.value
? selectedExpenditureContract.value.id
: null
// IDneed_contracttrue
const paymentDetailContractId = selectedPaymentCategory.value?.need_contract
const paymentDetailContractId = allowsContractSelection(selectedPaymentCategory.value)
? (isPaymentContractReused.value
? reusedPaymentContract.value?.id
: selectedPaymentContract.value?.id)
@ -6445,7 +6466,7 @@ const getBreadcrumbPath = () => {
//
const getPreviewContract = () => {
//
if (selectedPaymentCategory.value?.need_contract) {
if (allowsContractSelection(selectedPaymentCategory.value)) {
// 使
if (isPaymentContractReused.value && reusedPaymentContract.value) {
return reusedPaymentContract.value
@ -6456,7 +6477,7 @@ const getPreviewContract = () => {
}
}
//
if (selectedCategory.value?.need_contract && selectedExpenditureContract.value) {
if (allowsContractSelection(selectedCategory.value) && selectedExpenditureContract.value) {
return selectedExpenditureContract.value
}
return null
@ -6499,6 +6520,27 @@ const formatAmount = (amount) => {
return '¥' + numAmount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}
const buildContractLinkedIndirectPaymentMessage = (contract) => {
const payments = Array.isArray(contract?.related_indirect_payments)
? contract.related_indirect_payments
: []
if (payments.length === 0) {
return '该合同已关联过非直接支付,不允许再次关联。请选择其他合同。'
}
const names = payments
.slice(0, 3)
.map((payment) => {
const name = payment.name || payment.oa_flow_title || payment.planned_expenditure_title || payment.serial_number || `非直接支付#${payment.id}`
const serial = payment.serial_number ? `${payment.serial_number}` : ''
return `${name}${serial}`
})
const more = payments.length > names.length ? `${payments.length}` : ''
return `该合同已关联过非直接支付:${names.join('、')}${more},不允许再次关联。请选择其他合同。`
}
const shouldBlockAlreadyLinkedContract = () => false
//
const formatUppercaseAmount = (amount) => {
const n = Number(amount)
@ -6515,9 +6557,9 @@ const handleExpenditureContractSelected = async (contract) => {
//
const paymentCount = contract.payment_stats?.payment_count || 0
const paidAmount = Number(contract.payment_stats?.paid_amount || 0)
if (paidAmount > 0 || paymentCount > 0) {
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
await ElMessageBox.alert(
'该合同已关联过非直接支付,不允许再次关联。请选择其他合同。',
buildContractLinkedIndirectPaymentMessage(contract),
'提示',
{
confirmButtonText: '确定',
@ -6574,9 +6616,9 @@ const handlePaymentContractSelected = async (contract) => {
//
const paymentCount = contract.payment_stats?.payment_count || 0
const paidAmount = Number(contract.payment_stats?.paid_amount || 0)
if (paidAmount > 0 || paymentCount > 0) {
if (shouldBlockAlreadyLinkedContract() && (paidAmount > 0 || paymentCount > 0)) {
await ElMessageBox.alert(
'该合同已关联过非直接支付,不允许再次关联。请选择其他合同。',
buildContractLinkedIndirectPaymentMessage(contract),
'提示',
{
confirmButtonText: '确定',
@ -6607,9 +6649,9 @@ const paymentContractRemainingAmount = computed(() => {
//
const isPaymentContractReused = computed(() => {
return selectedCategory.value?.need_contract &&
return allowsContractSelection(selectedCategory.value) &&
selectedExpenditureContract.value &&
selectedPaymentCategory.value?.need_contract
allowsContractSelection(selectedPaymentCategory.value)
})
//

File diff suppressed because it is too large Load Diff

@ -69,10 +69,10 @@
<!-- 筛选表单 -->
<el-form :model="filterForm" inline style="margin-top: 16px">
<el-form-item label="流程编号">
<el-form-item label="关键词">
<el-input
v-model="filterForm.keyword"
placeholder="请输入流程编号或关键词"
placeholder="请输入流程编号、标题、发起人或关键词"
style="width: 200px"
clearable
/>

@ -99,8 +99,14 @@
<el-tag v-if="data.is_leaf" size="small" type="success" effect="plain" class="inline-tag">
叶子节点
</el-tag>
<el-tag v-if="data.need_contract" size="small" type="warning" effect="plain" class="inline-tag">
需关联合同
<el-tag
v-if="getContractRequirementTag(data)"
size="small"
:type="getContractRequirementTag(data).type"
effect="plain"
class="inline-tag"
>
{{ getContractRequirementTag(data).label }}
</el-tag>
<el-tag v-if="!data.is_active" size="small" type="info" effect="plain" class="inline-tag">
已禁用
@ -221,10 +227,14 @@
</el-form-item>
<el-form-item
v-if="isEditingLeafNode"
label="是否要关联合同"
prop="need_contract"
label="关联合同要求"
prop="contract_requirement"
>
<el-switch v-model="formData.need_contract" />
<el-radio-group v-model="formData.contract_requirement">
<el-radio label="none"></el-radio>
<el-radio label="required">必须</el-radio>
<el-radio label="optional">可选</el-radio>
</el-radio-group>
<span style="margin-left: 10px; color: #909399; font-size: 12px;">
仅叶子节点可设置
</span>
@ -424,6 +434,7 @@ const formData = reactive({
sort_order: 0,
is_active: true,
need_contract: false,
contract_requirement: 'none',
amount_limit_conditions: []
})
@ -522,6 +533,22 @@ const formRules = {
]
}
const getContractRequirement = (category) => {
if (!category) return 'none'
return category.contract_requirement || (category.need_contract ? 'required' : 'none')
}
const getContractRequirementTag = (category) => {
const requirement = getContractRequirement(category)
if (requirement === 'required') {
return { label: '必须关联合同', type: 'danger' }
}
if (requirement === 'optional') {
return { label: '可关联合同', type: 'warning' }
}
return null
}
//
const loadCategoryTree = async () => {
try {
@ -592,6 +619,7 @@ const handleCreate = () => {
sort_order: 0,
is_active: true,
need_contract: false,
contract_requirement: 'none',
amount_limit_conditions: []
})
dialogVisible.value = true
@ -610,6 +638,7 @@ const handleCreateChild = (row) => {
sort_order: 0,
is_active: true,
need_contract: false,
contract_requirement: 'none',
amount_limit_conditions: []
})
dialogVisible.value = true
@ -636,6 +665,7 @@ const handleEdit = async (row) => {
sort_order: response.data.sort_order,
is_active: response.data.is_active,
need_contract: response.data.need_contract ?? false,
contract_requirement: getContractRequirement(response.data),
amount_limit_conditions: Array.isArray(response.data.amount_limit_conditions)
? response.data.amount_limit_conditions.map(c => ({
field: c.field || 'current_payment_amount',
@ -877,6 +907,7 @@ const handleSubmit = async () => {
sort_order: formData.sort_order,
is_active: formData.is_active,
need_contract: isEditingLeafNode.value ? (formData.need_contract ?? false) : false,
contract_requirement: isEditingLeafNode.value ? getContractRequirement(formData) : 'none',
amount_limit_conditions: isEditingLeafNode.value ? normalizedAmountLimitConditions : null
}

@ -94,8 +94,14 @@
<el-tag v-if="data.is_leaf" size="small" type="success" effect="plain" class="inline-tag">
叶子节点
</el-tag>
<el-tag v-if="data.need_contract" size="small" type="warning" effect="plain" class="inline-tag">
需关联合同
<el-tag
v-if="getContractRequirementTag(data)"
size="small"
:type="getContractRequirementTag(data).type"
effect="plain"
class="inline-tag"
>
{{ getContractRequirementTag(data).label }}
</el-tag>
<el-tag v-if="!data.is_active" size="small" type="info" effect="plain" class="inline-tag">
已禁用
@ -202,10 +208,14 @@
</el-form-item>
<el-form-item
v-if="isEditingLeafNode"
label="是否要关联合同"
prop="need_contract"
label="关联合同要求"
prop="contract_requirement"
>
<el-switch v-model="formData.need_contract" />
<el-radio-group v-model="formData.contract_requirement">
<el-radio label="none"></el-radio>
<el-radio label="required">必须</el-radio>
<el-radio label="optional">可选</el-radio>
</el-radio-group>
<span style="margin-left: 10px; color: #909399; font-size: 12px;">
仅叶子节点可设置
</span>
@ -325,6 +335,7 @@ const formData = reactive({
sort_order: 0,
is_active: true,
need_contract: false,
contract_requirement: 'none',
amount_limit_conditions: []
// level is_leaf
})
@ -348,6 +359,22 @@ const formRules = {
]
}
const getContractRequirement = (category) => {
if (!category) return 'none'
return category.contract_requirement || (category.need_contract ? 'required' : 'none')
}
const getContractRequirementTag = (category) => {
const requirement = getContractRequirement(category)
if (requirement === 'required') {
return { label: '必须关联合同', type: 'danger' }
}
if (requirement === 'optional') {
return { label: '可关联合同', type: 'warning' }
}
return null
}
//
const parentOptions = ref([])
@ -564,6 +591,7 @@ const handleCreate = () => {
sort_order: 0,
is_active: true,
need_contract: false,
contract_requirement: 'none',
amount_limit_conditions: []
})
dialogVisible.value = true
@ -581,6 +609,7 @@ const handleCreateChild = (row) => {
sort_order: 0,
is_active: true,
need_contract: false,
contract_requirement: 'none',
amount_limit_conditions: []
})
dialogVisible.value = true
@ -606,6 +635,7 @@ const handleEdit = async (row) => {
sort_order: response.data.sort_order,
is_active: response.data.is_active,
need_contract: response.data.need_contract ?? false,
contract_requirement: getContractRequirement(response.data),
amount_limit_conditions: Array.isArray(response.data.amount_limit_conditions)
? response.data.amount_limit_conditions.map(c => ({
field: c.field || '',
@ -691,6 +721,7 @@ const handleSubmit = async () => {
sort_order: formData.sort_order,
is_active: formData.is_active,
need_contract: isEditingLeafNode.value ? (formData.need_contract ?? false) : false,
contract_requirement: isEditingLeafNode.value ? getContractRequirement(formData) : 'none',
amount_limit_conditions: isEditingLeafNode.value ? normalizedAmountLimitConditions : null
// level is_leaf
}

Loading…
Cancel
Save