-
+
@@ -468,7 +473,7 @@
-
+
@@ -601,6 +606,7 @@ import {
} from '@/utils/crm-product-brand'
import { fetchProductDetail } from '@/api/crm/product'
import ApprovalDialog from './ApprovalDialog.vue'
+import { omitEmptyExceptPartyFields } from '../partyFields'
import { getContactByCustomerId } from '@/api/crm/customer'
import type { CustomerVO, ContactVO } from '@/api/crm/customer/types'
import { getDefaultInvoiceInfoByCustomerId } from '@/api/crm/invoiceInfo'
@@ -1348,6 +1354,31 @@ const updateContractNoBySupplier = (newSupplierCode: string | undefined) => {
}
}
+const CONTRACT_NO_STD_RE = /^([A-Z]+)\/X-JT(\d{8})(\d{3})$/
+
+/** 签订日变更时:标准编号只换日期段,保留序号;并同步名称括号内编号 */
+const syncContractNoDateFromSignDate = (signDateVal: string | null) => {
+ if (!signDateVal || !form.value.contractNo) return
+ const m = String(form.value.contractNo).match(CONTRACT_NO_STD_RE)
+ if (!m) return
+
+ const dateStr = signDateVal.replace(/-/g, '')
+ if (dateStr.length !== 8) return
+ if (m[2] === dateStr) return
+
+ const nextNo = `${m[1]}/X-JT${dateStr}${m[3]}`
+ form.value.contractNo = nextNo
+
+ if (form.value.contractName) {
+ const replaced = form.value.contractName.replace(/[((][^))]*[))]$/, `(${nextNo})`)
+ if (replaced !== form.value.contractName) {
+ form.value.contractName = replaced
+ } else {
+ rebuildContractName()
+ }
+ }
+}
+
const COMMON_SUPPLIER_SHORT_NAMES = ['山峡', 'SX']
const extractContractNameParts = (contractName: string) => {
@@ -1366,7 +1397,7 @@ const isSupplierShortNamePart = (part: string, supplierShort: string) => {
return part === supplierShort || COMMON_SUPPLIER_SHORT_NAMES.some((name) => part.includes(name))
}
-/** 从现有合同名称推断客户简称(切换合同类型时不能依赖新类型解析旧格式) */
+/** 从现有合同名称推断客户简称(统一格式:供方简称-需方简称) */
const inferCustomerShortNameFromContractName = (): string => {
if (customerShortName.value) return customerShortName.value
if (!form.value.contractName) return ''
@@ -1383,14 +1414,13 @@ const inferCustomerShortNameFromContractName = (): string => {
return isSupplierShortNamePart(parts[0], supplierShort) ? '' : parts[0]
}
+ // 统一格式:供方(交易主体)-需方(客户);供方在前则取第二段为客户简称
if (isSupplierShortNamePart(parts[0], supplierShort)) return parts[1]
if (isSupplierShortNamePart(parts[1], supplierShort)) return parts[0]
-
- if (form.value.contractType === 'purchase') return parts[0]
return parts[1]
}
-/** 按合同类型重建合同名称:销售/框架=供方简称-客户简称,采购=客户简称-供方简称 */
+/** 重建合同名称:统一为 {供方简称}-{需方简称}({合同编号}),不因采购反序 */
const rebuildContractName = () => {
if (!form.value.contractName) return
@@ -1400,10 +1430,7 @@ const rebuildContractName = () => {
const { contractNoInName } = extractContractNameParts(form.value.contractName)
const contractNo = form.value.contractNo || contractNoInName
- const isPurchase = form.value.contractType === 'purchase'
- const nameBody = isPurchase
- ? [customerShort, supplierShort].filter(Boolean).join('-')
- : [supplierShort, customerShort].filter(Boolean).join('-')
+ const nameBody = [supplierShort, customerShort].filter(Boolean).join('-')
if (!nameBody) return
@@ -1534,6 +1561,7 @@ const handleSignDateChange = (val: string | null) => {
form.value.startDate = ''
form.value.endDate = ''
}
+ syncContractNoDateFromSignDate(val)
nextTick(() => {
formRef.value?.validateField('startDate')
})
@@ -1919,11 +1947,7 @@ const handleSaveDraft = async () => {
data.attachmentFiles = attachmentJson
}
- Object.keys(data).forEach((key) => {
- if (data[key] === undefined || data[key] === '') {
- delete data[key]
- }
- })
+ omitEmptyExceptPartyFields(data)
if (data.contactsName) {
data.contactName = data.contactsName
@@ -2086,11 +2110,7 @@ const handleSubmit = async () => {
data.attachmentFiles = attachmentJson
}
- Object.keys(data).forEach((key) => {
- if (data[key] === undefined || data[key] === '') {
- delete data[key]
- }
- })
+ omitEmptyExceptPartyFields(data)
if (data.contactsName) {
data.contactName = data.contactsName
diff --git a/web-admin/src/views/crm/contract/form.vue b/web-admin/src/views/crm/contract/form.vue
index b200affbe..081d00b36 100644
--- a/web-admin/src/views/crm/contract/form.vue
+++ b/web-admin/src/views/crm/contract/form.vue
@@ -19,7 +19,12 @@