单方协议
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
<div class="section-title-row counterparty-toolbar">
|
||||
<div class="section-title">我方主体</div>
|
||||
<a-button
|
||||
v-if="!isViewMode"
|
||||
v-if="!isViewMode && !isSingleAgreementChecked"
|
||||
type="link"
|
||||
class="text-action-btn"
|
||||
@click="handleAddOurParty"
|
||||
@@ -46,7 +46,7 @@
|
||||
</a-button>
|
||||
</div>
|
||||
<div class="party-empty-state" style="margin-bottom: 12px">
|
||||
当前登录主体必须包含在我方主体中
|
||||
{{ isSingleAgreementChecked ? "单方协议默认使用当前登录主体,且不可修改" : "当前登录主体必须包含在我方主体中" }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -59,7 +59,7 @@
|
||||
{{ party.displayName }}
|
||||
</div>
|
||||
<a-button
|
||||
v-if="!isViewMode && ourParties.length > 1"
|
||||
v-if="!isViewMode && !isSingleAgreementChecked && ourParties.length > 1"
|
||||
type="link"
|
||||
danger
|
||||
class="text-action-btn"
|
||||
@@ -73,6 +73,7 @@
|
||||
v-model:value="party.companyName"
|
||||
:options="getPartyOptions(party.roleCode)"
|
||||
show-search
|
||||
:disabled="isSingleAgreementChecked"
|
||||
:placeholder="`请选择${party.displayName}`"
|
||||
:filter-option="filterPartnerOption"
|
||||
@change="
|
||||
@@ -116,13 +117,6 @@
|
||||
<SearchOutlined />
|
||||
</a-button>
|
||||
</div>
|
||||
<a-button
|
||||
class="invoice-btn"
|
||||
@click="showInvoiceTitles(party, party.displayName)"
|
||||
>
|
||||
<PlusOutlined />
|
||||
备选开票抬头选择
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<div class="section-title-row counterparty-toolbar">
|
||||
@@ -365,7 +359,7 @@
|
||||
</div>
|
||||
<div class="summary-line">
|
||||
<span>相对方</span
|
||||
><strong>{{ counterpartySummaryText }}</strong>
|
||||
><strong>{{ isSingleAgreementChecked ? "单方协议,无相对方" : counterpartySummaryText }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -401,7 +395,7 @@
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<div class="upload-block">
|
||||
<div v-if="!isSingleAgreementChecked" class="upload-block">
|
||||
<div class="upload-label">签订依据附件</div>
|
||||
<a-upload-dragger
|
||||
:file-list="gistAttachmentList"
|
||||
@@ -437,7 +431,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="requiresAuthAttachment" class="upload-block">
|
||||
<div
|
||||
v-if="!isSingleAgreementChecked && requiresAuthAttachment"
|
||||
class="upload-block"
|
||||
>
|
||||
<div class="upload-label">授权委托书附件</div>
|
||||
<a-upload-dragger
|
||||
:file-list="authAttachmentUploadList"
|
||||
@@ -994,86 +991,6 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<a-collapse class="detail-collapse">
|
||||
<a-collapse-panel
|
||||
v-for="party in allPartyDetails"
|
||||
:key="party.localId"
|
||||
:header="`${party.displayName}详细字段维护`"
|
||||
>
|
||||
<div class="field-grid field-grid-3">
|
||||
<a-form-item class="tight-item" label="公司类型">
|
||||
<a-select
|
||||
v-model:value="party.companyType"
|
||||
:options="companyTypeOptions"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="公司性质">
|
||||
<a-select
|
||||
v-model:value="party.companyNature"
|
||||
:options="companyNatureOptions"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="组织性质">
|
||||
<a-select
|
||||
v-model:value="party.organizationNature"
|
||||
:options="organizationNatureOptions"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="组织性质企业二级">
|
||||
<a-select
|
||||
v-model:value="party.enterpriseNatureLevel2"
|
||||
:options="enterpriseNatureLevel2Options"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="统一社会信用代码">
|
||||
<a-input v-model:value="party.creditCode" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="TIN号">
|
||||
<a-input v-model:value="party.tinNo" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="国家/地区">
|
||||
<a-select
|
||||
v-model:value="party.countryCode"
|
||||
:options="countryOptions"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="法定代表人">
|
||||
<a-input v-model:value="party.legalRepresentative" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item field-span-3" label="注册地址">
|
||||
<a-input v-model:value="party.registeredAddress" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="注册资本">
|
||||
<a-input v-model:value="party.registeredCapital" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="联系电话">
|
||||
<a-input v-model:value="party.contactPhone" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="电子邮箱">
|
||||
<a-input v-model:value="party.contactEmail" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item field-span-3" label="通讯地址">
|
||||
<a-input v-model:value="party.contactAddress" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="开户行">
|
||||
<a-input v-model:value="party.bankName" />
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item field-span-2" label="银行账号">
|
||||
<a-input v-model:value="party.bankAccount" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
class="tight-item field-span-3"
|
||||
label="备选开票抬头"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="party.invoiceTitleOptions"
|
||||
mode="tags"
|
||||
:token-separators="[',', ',']"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
@@ -1131,11 +1048,6 @@ import {
|
||||
|
||||
// ========== 合同方相关字典 ==========
|
||||
|
||||
const partyCharacterOptions = [
|
||||
{ label: "企业", value: "QY" },
|
||||
{ label: "自然人", value: "ZZR" },
|
||||
];
|
||||
|
||||
const companyTypeOptions = [
|
||||
{ label: "客户", value: "客户" },
|
||||
{ label: "供应商", value: "供应商" },
|
||||
@@ -1144,38 +1056,6 @@ const companyTypeOptions = [
|
||||
{ label: "其他", value: "其他" },
|
||||
];
|
||||
|
||||
const companyNatureOptions = [
|
||||
{ label: "境内组织", value: "境内组织" },
|
||||
{ label: "境内个人", value: "境内个人" },
|
||||
{ label: "境外组织", value: "境外组织" },
|
||||
{ label: "境外个人", value: "境外个人" },
|
||||
];
|
||||
|
||||
const organizationNatureOptions = [
|
||||
{ label: "政府", value: "政府" },
|
||||
{ label: "企业", value: "企业" },
|
||||
{ label: "其他组织", value: "其他组织" },
|
||||
];
|
||||
|
||||
const enterpriseNatureLevel2Options = [
|
||||
{ label: "国有企业", value: "国有企业" },
|
||||
{ label: "民营企业", value: "民营企业" },
|
||||
{ label: "外资企业", value: "外资企业" },
|
||||
{ label: "合资企业", value: "合资企业" },
|
||||
{ label: "国有全资和控股企业", value: "国有全资和控股企业" },
|
||||
];
|
||||
|
||||
const countryOptions = [
|
||||
{ label: "中国", value: "GJ156" },
|
||||
{ label: "中国香港", value: "GJ344" },
|
||||
{ label: "中国澳门", value: "GJ446" },
|
||||
{ label: "中国台湾", value: "GJ158" },
|
||||
{ label: "新加坡", value: "GJ702" },
|
||||
{ label: "美国", value: "GJ840" },
|
||||
{ label: "英国", value: "GJ826" },
|
||||
{ label: "日本", value: "GJ392" },
|
||||
];
|
||||
|
||||
const contractCompanyOptions = ref([
|
||||
{ label: "扬州宏富特种材料有限公司", value: "扬州宏富特种材料有限公司" },
|
||||
{ label: "宁波港船务货运代理有限公司", value: "宁波港船务货运代理有限公司" },
|
||||
@@ -1382,9 +1262,6 @@ function createEmptyParty(roleCode, index = 0) {
|
||||
companyType: "",
|
||||
oppositeCharacter: "",
|
||||
oppCharacter: "",
|
||||
companyNature: "",
|
||||
organizationNature: "",
|
||||
enterpriseNatureLevel2: "",
|
||||
contactName: "",
|
||||
contactPhone: "",
|
||||
contactEmail: "",
|
||||
@@ -1398,7 +1275,6 @@ function createEmptyParty(roleCode, index = 0) {
|
||||
naturalPersonIdNumber: "",
|
||||
isGroupInternal: false,
|
||||
isHongKongMacaoTaiwan: false,
|
||||
invoiceTitleOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1417,9 +1293,6 @@ function mapLaunchPartyToFormParty(item = {}) {
|
||||
roleCode,
|
||||
roleName: roleCode === PARTY_ROLE_OUR ? "我方" : "相对方",
|
||||
subjectCode: item.subjectCode || "",
|
||||
companyNature: getCompanyNatureByOppositeCharacter(
|
||||
item.oppositeCharacter || item.oppCharacter,
|
||||
),
|
||||
oppCharacter: item.oppositeCharacter || item.oppCharacter || "",
|
||||
oppositeCharacter: item.oppositeCharacter || item.oppCharacter || "",
|
||||
displayName: "",
|
||||
@@ -1445,16 +1318,6 @@ function buildPartyStateFromList(list = []) {
|
||||
return normalizePartyState(result);
|
||||
}
|
||||
|
||||
function getCompanyNatureByOppositeCharacter(value) {
|
||||
const map = {
|
||||
1: "境内组织",
|
||||
2: "境内个人",
|
||||
3: "境外组织",
|
||||
4: "境外个人",
|
||||
};
|
||||
return map[String(value || "")] || "";
|
||||
}
|
||||
|
||||
function isPartyFilled(party = {}) {
|
||||
const ignoreKeys = new Set([
|
||||
"localId",
|
||||
@@ -1834,11 +1697,6 @@ const ourPartySummaryText = computed(() =>
|
||||
: "未填写",
|
||||
);
|
||||
|
||||
const allPartyDetails = computed(() => [
|
||||
...ourParties.value,
|
||||
...counterpartyParties.value,
|
||||
]);
|
||||
|
||||
const signingSubjectCodeText = computed(() =>
|
||||
ourParties.value
|
||||
.map((party) => String(party.subjectCode || "").trim())
|
||||
@@ -1870,6 +1728,23 @@ const requiresAuthAttachment = computed(() =>
|
||||
["GZBSQRQZ", "HTZYZBSQRQZ"].includes(detailState.value.sealType),
|
||||
);
|
||||
|
||||
function forceSingleAgreementDefaults() {
|
||||
if (!isSingleAgreementChecked.value || !currentSelfParty.value) return;
|
||||
detailState.value.isElectron = "0";
|
||||
detailState.value.sealType = "YWZ";
|
||||
detailState.value.partyState.ourPartyList = [
|
||||
{
|
||||
...createEmptyParty(PARTY_ROLE_OUR, 0),
|
||||
...currentSelfParty.value,
|
||||
localId:
|
||||
detailState.value.partyState.ourPartyList?.[0]?.localId ||
|
||||
createLocalId("our"),
|
||||
},
|
||||
];
|
||||
detailState.value.partyState.counterpartyList = [];
|
||||
refreshPartyDisplayMeta();
|
||||
}
|
||||
|
||||
function syncUploadLists() {
|
||||
otherAttachmentList.value = (detailState.value.otherAttachmentList || []).map(
|
||||
(item, index) => ({
|
||||
@@ -1943,15 +1818,6 @@ function showSearchTip(title) {
|
||||
message.info(`${title}数据已从客户/主体库加载,可直接在下拉框搜索选择。`);
|
||||
}
|
||||
|
||||
function showInvoiceTitles(party, roleName) {
|
||||
const titles = party.invoiceTitleOptions || [];
|
||||
message.info(
|
||||
titles.length
|
||||
? `${roleName}备选开票抬头:${titles.join(";")}`
|
||||
: `${roleName}暂无备选开票抬头`,
|
||||
);
|
||||
}
|
||||
|
||||
function filterPartnerOption(input, option) {
|
||||
const keyword = String(input || "")
|
||||
.trim()
|
||||
@@ -1978,27 +1844,6 @@ function getRelativeTypeLabel(value) {
|
||||
return map[value] || value || "";
|
||||
}
|
||||
|
||||
function getOrganizationNatureLabel(value) {
|
||||
const map = {
|
||||
ZY: "政府",
|
||||
QY: "企业",
|
||||
QT: "其他组织",
|
||||
};
|
||||
return map[value] || value || "";
|
||||
}
|
||||
|
||||
function getEnterpriseNatureLevel2Label(value) {
|
||||
const map = {
|
||||
GNQY: "国有企业",
|
||||
MYQY: "民营企业",
|
||||
WZQY: "外资企业",
|
||||
HZQY: "合资企业",
|
||||
GYQZHKGQY: "国有全资和控股企业",
|
||||
QT: "其他",
|
||||
};
|
||||
return map[value] || value || "";
|
||||
}
|
||||
|
||||
function mapPartnerToParty(raw = {}, roleKey, companyName) {
|
||||
const firstContact = raw.contacts?.[0] || {};
|
||||
const roleCode =
|
||||
@@ -2013,17 +1858,9 @@ function mapPartnerToParty(raw = {}, roleKey, companyName) {
|
||||
companyType: getRelativeTypeLabel(raw.relativeType),
|
||||
oppositeCharacter: raw.oppositeCharacter || "",
|
||||
oppCharacter: raw.oppositeCharacter || "",
|
||||
companyNature: getCompanyNatureByOppositeCharacter(raw.oppositeCharacter),
|
||||
organizationNature: getOrganizationNatureLabel(raw.natureOfEnterpriseOrg),
|
||||
enterpriseNatureLevel2: getEnterpriseNatureLevel2Label(
|
||||
raw.natureOfEnterpriseOrgLev,
|
||||
),
|
||||
creditCode: raw.customerTaxno || "",
|
||||
tinNo: raw.tinCode || "",
|
||||
countryCode: raw.country || "",
|
||||
legalRepresentative: raw.legalPersonName || "",
|
||||
registeredAddress: raw.customerRegaddr || "",
|
||||
registeredCapital: raw.regCapital || raw.registeredCapital || "",
|
||||
contactName: firstContact.contactName || "",
|
||||
contactPhone: firstContact.contactPhone || raw.officephone || "",
|
||||
contactEmail: firstContact.email || raw.emailAddress || "",
|
||||
@@ -2034,7 +1871,6 @@ function mapPartnerToParty(raw = {}, roleKey, companyName) {
|
||||
naturalPersonIdNumber: raw.certificateNum || "",
|
||||
isGroupInternal: raw.groupFlag === "Y" || raw.isJtn === "1",
|
||||
isHongKongMacaoTaiwan: raw.gatFlag === "Y" || raw.isSgat === "1",
|
||||
invoiceTitleOptions: raw.customerNameC ? [raw.customerNameC] : [],
|
||||
roleCode,
|
||||
roleName: roleCode === PARTY_ROLE_OUR ? "我方" : "相对方",
|
||||
};
|
||||
@@ -2109,13 +1945,12 @@ function handleCompanySelect(party, companyName, option = {}) {
|
||||
legalRepresentative:
|
||||
party.legalRepresentative || profile.legalRepresentative,
|
||||
creditCode: party.creditCode || profile.creditCode,
|
||||
oppCharacter:
|
||||
party.oppCharacter ||
|
||||
(String(party.companyNature || "").includes("个人") ? "2" : "1"),
|
||||
oppCharacter: party.oppCharacter || "1",
|
||||
});
|
||||
}
|
||||
|
||||
function handleAddOurParty() {
|
||||
if (isSingleAgreementChecked.value) return;
|
||||
detailState.value.partyState.ourPartyList =
|
||||
detailState.value.partyState.ourPartyList || [];
|
||||
detailState.value.partyState.ourPartyList.push(
|
||||
@@ -2136,6 +1971,7 @@ function handleContractTypeCodeChange(value) {
|
||||
}
|
||||
|
||||
function handleAddCounterparty() {
|
||||
if (isSingleAgreementChecked.value) return;
|
||||
detailState.value.partyState.counterpartyList =
|
||||
detailState.value.partyState.counterpartyList || [];
|
||||
detailState.value.partyState.counterpartyList.push(
|
||||
@@ -2148,6 +1984,7 @@ function handleAddCounterparty() {
|
||||
}
|
||||
|
||||
function handleRemoveOurParty(localId) {
|
||||
if (isSingleAgreementChecked.value) return;
|
||||
detailState.value.partyState.ourPartyList = (
|
||||
detailState.value.partyState.ourPartyList || []
|
||||
).filter((item) => item.localId !== localId);
|
||||
@@ -2160,6 +1997,7 @@ function handleRemoveOurParty(localId) {
|
||||
}
|
||||
|
||||
function handleRemoveCounterparty(localId) {
|
||||
if (isSingleAgreementChecked.value) return;
|
||||
detailState.value.partyState.counterpartyList = (
|
||||
detailState.value.partyState.counterpartyList || []
|
||||
).filter((item) => item.localId !== localId);
|
||||
@@ -2247,7 +2085,7 @@ async function downloadFile(filePath, fileName = "附件") {
|
||||
}
|
||||
try {
|
||||
const resp = await downloadLaunchFile(filePath);
|
||||
const arrayBuffer = resp.data;
|
||||
const arrayBuffer = resp?.data ?? resp;
|
||||
const blob = new Blob([arrayBuffer]);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
@@ -2336,6 +2174,16 @@ function validateState() {
|
||||
) {
|
||||
return "当前登录主体必须包含在我方主体中";
|
||||
}
|
||||
if (
|
||||
isSingleAgreementChecked.value &&
|
||||
currentSelfSubjectCode.value &&
|
||||
ourParties.value.some(
|
||||
(party) =>
|
||||
String(party.subjectCode || "").trim() !== currentSelfSubjectCode.value,
|
||||
)
|
||||
) {
|
||||
return "单方协议仅允许使用当前登录主体";
|
||||
}
|
||||
if (!isSingleAgreementChecked.value && !counterpartyParties.value.length)
|
||||
return "请至少添加一个相对方";
|
||||
if (
|
||||
@@ -2405,6 +2253,7 @@ function validateState() {
|
||||
if (!detailState.value.contractBodyFileName?.trim())
|
||||
return "请先配置合同正文";
|
||||
if (
|
||||
!isSingleAgreementChecked.value &&
|
||||
requiresAuthAttachment.value &&
|
||||
!(detailState.value.authAttachmentList || []).length
|
||||
)
|
||||
@@ -2473,9 +2322,7 @@ function buildLaunchRecord() {
|
||||
oppositeId: party.oppositeId,
|
||||
companyName: party.companyName,
|
||||
companyType: party.companyType,
|
||||
oppositeCharacter:
|
||||
party.oppCharacter ||
|
||||
(String(party.companyNature || "").includes("个人") ? "2" : "1"),
|
||||
oppositeCharacter: party.oppCharacter || "1",
|
||||
contactName: party.contactName,
|
||||
contactPhone: party.contactPhone,
|
||||
contactEmail: party.contactEmail,
|
||||
@@ -2501,9 +2348,7 @@ function buildLaunchRecord() {
|
||||
oppositeId: party.oppositeId,
|
||||
companyName: party.companyName,
|
||||
companyType: party.companyType,
|
||||
oppositeCharacter:
|
||||
party.oppCharacter ||
|
||||
(String(party.companyNature || "").includes("个人") ? "2" : "1"),
|
||||
oppositeCharacter: party.oppCharacter || "1",
|
||||
contactName: party.contactName,
|
||||
contactPhone: party.contactPhone,
|
||||
contactEmail: party.contactEmail,
|
||||
@@ -2675,7 +2520,6 @@ function applySelfProfile(profile = {}) {
|
||||
bankAccount: profile.bankAccount || "",
|
||||
legalRepresentative: profile.legalRepresentative || "",
|
||||
creditCode: profile.creditCode || "",
|
||||
invoiceTitleOptions: profile.invoiceTitleOptions || [],
|
||||
};
|
||||
const shouldHydrateFirstParty =
|
||||
!firstOurParty.companyName ||
|
||||
@@ -2699,12 +2543,11 @@ function applySelfProfile(profile = {}) {
|
||||
legalRepresentative:
|
||||
profile.legalRepresentative || firstOurParty.legalRepresentative,
|
||||
creditCode: profile.creditCode || firstOurParty.creditCode,
|
||||
invoiceTitleOptions:
|
||||
profile.invoiceTitleOptions || firstOurParty.invoiceTitleOptions || [],
|
||||
},
|
||||
...(detailState.value.partyState.ourPartyList || []).slice(1),
|
||||
];
|
||||
refreshPartyDisplayMeta();
|
||||
forceSingleAgreementDefaults();
|
||||
}
|
||||
|
||||
async function showModal(context = {}, mode = "create") {
|
||||
@@ -2724,6 +2567,7 @@ async function showModal(context = {}, mode = "create") {
|
||||
detailState.value = copyContractFormData(source);
|
||||
const selfProfile = await getLaunchSelfProfile();
|
||||
applySelfProfile(selfProfile || {});
|
||||
forceSingleAgreementDefaults();
|
||||
syncCounterpartyState();
|
||||
syncUploadLists();
|
||||
loadPartnerOptions();
|
||||
|
||||
Reference in New Issue
Block a user