feat: 接入新华社工商信息同步
This commit is contained in:
@@ -148,6 +148,17 @@
|
||||
>查看导入失败记录</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-refresh"
|
||||
size="mini"
|
||||
:loading="profileBackfillLoading"
|
||||
@click="handleProfileBackfill"
|
||||
v-hasPermi="['ccdi:enterpriseBaseInfo:backfill']"
|
||||
>工商历史补全</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
@@ -407,6 +418,12 @@
|
||||
<el-descriptions-item label="成立日期">{{ parseTime(detailData.establishDate, '{y}-{m}-{d}') || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册地址">{{ detailData.registerAddress || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="法定代表人">{{ detailData.legalRepresentative || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册资本">{{ formatCapital(detailData.registeredCapital, detailData.registeredCapitalUnit) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册日期">{{ parseTime(detailData.registerDate, '{y}-{m}-{d}') || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="区域">{{ detailData.regionName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="区域编码">{{ detailData.regionCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="从业人数">{{ detailData.employeeCount == null ? '-' : detailData.employeeCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="工商同步时间">{{ parseTime(detailData.enterpriseSyncTime) || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="法定代表人证件类型">{{ detailData.legalCertType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="法定代表人证件号码">{{ detailData.legalCertNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="经营状态">{{ formatStatus(detailData.status) }}</el-descriptions-item>
|
||||
@@ -420,7 +437,24 @@
|
||||
<el-descriptions-item label="股东4">{{ detailData.shareholder4 || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="股东5">{{ detailData.shareholder5 || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="shareholder-title">完整股东信息</div>
|
||||
<el-table :data="detailData.shareholders || []" border size="small">
|
||||
<el-table-column label="序号" prop="shareholderSeq" width="70" align="center" />
|
||||
<el-table-column label="股东名称" prop="shareholderName" min-width="220" />
|
||||
<el-table-column label="持股比例(%)" prop="stockPercent" width="130" align="right" />
|
||||
<el-table-column label="认缴金额" min-width="150" align="right">
|
||||
<template slot-scope="scope">{{ formatCapital(scope.row.subscribedCapital, scope.row.capitalUnit) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button
|
||||
v-if="detailData.canRefreshEnterpriseProfile"
|
||||
type="primary"
|
||||
icon="el-icon-refresh"
|
||||
:loading="profileRefreshing"
|
||||
@click="handleProfileRefresh"
|
||||
v-hasPermi="['ccdi:enterpriseBaseInfo:refresh']"
|
||||
>重新查询</el-button>
|
||||
<el-button @click="detailOpen = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -506,9 +540,12 @@ import {
|
||||
addEnterpriseBaseInfo,
|
||||
delEnterpriseBaseInfo,
|
||||
getEnterpriseBaseInfo,
|
||||
getEnterpriseProfileBackfillStatus,
|
||||
getImportFailures,
|
||||
getImportStatus,
|
||||
listEnterpriseBaseInfo,
|
||||
refreshEnterpriseProfile,
|
||||
startEnterpriseProfileBackfill,
|
||||
updateEnterpriseBaseInfo
|
||||
} from "@/api/ccdiEnterpriseBaseInfo";
|
||||
import {
|
||||
@@ -546,6 +583,9 @@ export default {
|
||||
detailOpen: false,
|
||||
isAdd: true,
|
||||
detailData: {},
|
||||
profileRefreshing: false,
|
||||
profileBackfillLoading: false,
|
||||
profileBackfillTimer: null,
|
||||
corpTypeOptions: [],
|
||||
corpNatureOptions: [],
|
||||
certTypeOptions: [],
|
||||
@@ -626,6 +666,10 @@ export default {
|
||||
clearInterval(this.pollingTimer);
|
||||
this.pollingTimer = null;
|
||||
}
|
||||
if (this.profileBackfillTimer) {
|
||||
clearInterval(this.profileBackfillTimer);
|
||||
this.profileBackfillTimer = null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadOptions() {
|
||||
@@ -709,6 +753,51 @@ export default {
|
||||
this.detailOpen = true;
|
||||
});
|
||||
},
|
||||
handleProfileRefresh() {
|
||||
if (!this.detailData.socialCreditCode) return;
|
||||
this.profileRefreshing = true;
|
||||
refreshEnterpriseProfile(this.detailData.socialCreditCode).then(() => {
|
||||
this.$modal.msgSuccess("工商信息已更新");
|
||||
return getEnterpriseBaseInfo(this.detailData.socialCreditCode);
|
||||
}).then(response => {
|
||||
this.detailData = response.data || {};
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.profileRefreshing = false;
|
||||
});
|
||||
},
|
||||
handleProfileBackfill() {
|
||||
this.$modal.confirm("确认启动实体库工商信息历史补全?").then(() => {
|
||||
this.profileBackfillLoading = true;
|
||||
return startEnterpriseProfileBackfill();
|
||||
}).then(response => {
|
||||
this.pollProfileBackfill(response.data);
|
||||
}).catch(() => {
|
||||
this.profileBackfillLoading = false;
|
||||
});
|
||||
},
|
||||
pollProfileBackfill(taskId) {
|
||||
const query = () => getEnterpriseProfileBackfillStatus(taskId).then(response => {
|
||||
const status = response.data || {};
|
||||
if (status.status === "COMPLETED") {
|
||||
clearInterval(this.profileBackfillTimer);
|
||||
this.profileBackfillTimer = null;
|
||||
this.profileBackfillLoading = false;
|
||||
this.$notify({ title: "工商历史补全完成", message: `成功 ${status.successCount || 0},跳过 ${status.skippedCount || 0},失败 ${status.failureCount || 0}`, type: status.failureCount ? "warning" : "success" });
|
||||
this.getList();
|
||||
}
|
||||
}).catch(() => {
|
||||
clearInterval(this.profileBackfillTimer);
|
||||
this.profileBackfillTimer = null;
|
||||
this.profileBackfillLoading = false;
|
||||
});
|
||||
query();
|
||||
this.profileBackfillTimer = setInterval(query, 2000);
|
||||
},
|
||||
formatCapital(amount, unit) {
|
||||
if (amount === null || amount === undefined || amount === "") return "-";
|
||||
return `${amount}${unit || ""}`;
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
this.isAdd = false;
|
||||
@@ -1009,4 +1098,12 @@ export default {
|
||||
.el-upload__tip {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.shareholder-title {
|
||||
margin: 18px 0 10px;
|
||||
color: #303133;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -172,6 +172,14 @@
|
||||
>
|
||||
导出流水
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
plain
|
||||
icon="el-icon-refresh"
|
||||
:loading="counterpartyBackfillLoading"
|
||||
@click="handleCounterpartyBackfill"
|
||||
v-hasPermi="['ccdi:project:counterpartyEnterprise:backfill']"
|
||||
>工商历史补全</el-button>
|
||||
</div>
|
||||
<el-alert
|
||||
v-if="resultMode === 'statement' && prefillTip"
|
||||
@@ -237,7 +245,13 @@
|
||||
<template slot-scope="scope">
|
||||
<div class="multi-line-cell">
|
||||
<div class="primary-text">
|
||||
{{ formatField(scope.row.customerAccountName) }}
|
||||
<el-button
|
||||
v-if="scope.row.customerAccountName"
|
||||
type="text"
|
||||
class="counterparty-link"
|
||||
@click="openCounterpartyDetail(scope.row.customerAccountName)"
|
||||
>{{ scope.row.customerAccountName }}</el-button>
|
||||
<span v-else>-</span>
|
||||
</div>
|
||||
<div class="secondary-text">
|
||||
{{ formatField(scope.row.customerAccountNo) }}
|
||||
@@ -496,6 +510,60 @@
|
||||
<el-button type="primary" @click="closeDetailDialog">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="对手方工商信息" :visible.sync="counterpartyVisible" width="920px" append-to-body>
|
||||
<div v-loading="counterpartyLoading">
|
||||
<el-alert
|
||||
v-if="counterpartyData.status === 'NOT_FOUND'"
|
||||
title="当前项目尚无该对手方工商数据"
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="counterparty-alert"
|
||||
/>
|
||||
<el-alert
|
||||
v-else-if="counterpartyData.status === 'EXPIRED'"
|
||||
title="工商缓存已过期,可重新查询"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="counterparty-alert"
|
||||
/>
|
||||
<el-descriptions :column="2" border size="small">
|
||||
<el-descriptions-item label="流水对手方">{{ formatField(counterpartyData.counterpartyName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="企业名称">{{ formatField(counterpartyData.enterpriseName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="统一社会信用代码">{{ formatField(counterpartyData.socialCreditCode) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="法定代表人">{{ formatField(counterpartyData.legalRepresentative) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册资本">{{ formatCapital(counterpartyData.registeredCapital, counterpartyData.registeredCapitalUnit) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册日期">{{ formatDateOnly(counterpartyData.registerDate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="成立日期">{{ formatDateOnly(counterpartyData.establishDate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="机构类型">{{ formatField(counterpartyData.organizationTypeName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属行业">{{ formatField(counterpartyData.industryName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="区域">{{ formatField(counterpartyData.regionName) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="从业人数">{{ counterpartyData.employeeCount == null ? '-' : counterpartyData.employeeCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="同步时间">{{ formatDate(counterpartyData.syncTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册地址" :span="2">{{ formatField(counterpartyData.registerAddress) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="counterparty-section-title">完整股东信息</div>
|
||||
<el-table :data="counterpartyData.shareholders || []" border size="small">
|
||||
<el-table-column label="序号" prop="sequenceNo" width="70" align="center" />
|
||||
<el-table-column label="股东名称" prop="shareholderName" min-width="220" />
|
||||
<el-table-column label="持股比例(%)" prop="stockPercent" width="130" align="right" />
|
||||
<el-table-column label="认缴金额" min-width="150" align="right"><template slot-scope="scope">{{ formatCapital(scope.row.subscribedCapital, scope.row.capitalUnit) }}</template></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<el-button
|
||||
v-if="counterpartyData.canRefresh"
|
||||
type="primary"
|
||||
icon="el-icon-refresh"
|
||||
:loading="counterpartyRefreshing"
|
||||
@click="refreshCounterparty"
|
||||
v-hasPermi="['ccdi:project:counterpartyEnterprise:refresh']"
|
||||
>重新查询</el-button>
|
||||
<el-button @click="counterpartyVisible=false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -508,6 +576,12 @@ import {
|
||||
getBankStatementDetail,
|
||||
} from "@/api/ccdiProjectBankStatement";
|
||||
import { buildFlowEvidenceFingerprint, buildFlowEvidenceSnapshot } from "@/utils/ccdiEvidence";
|
||||
import {
|
||||
getCounterpartyEnterpriseBackfillStatus,
|
||||
getCounterpartyEnterpriseDetail,
|
||||
refreshCounterpartyEnterprise,
|
||||
startCounterpartyEnterpriseBackfill,
|
||||
} from "@/api/ccdiProjectCounterpartyEnterprise";
|
||||
|
||||
const TAB_MAP = {
|
||||
all: "all",
|
||||
@@ -592,6 +666,8 @@ const createEmptyDetailData = () => ({
|
||||
hitTags: [],
|
||||
});
|
||||
|
||||
const createEmptyCounterpartyData = () => ({ status: "NOT_FOUND", canRefresh: false, shareholders: [] });
|
||||
|
||||
export default {
|
||||
name: "DetailQuery",
|
||||
props: {
|
||||
@@ -629,6 +705,12 @@ export default {
|
||||
listError: "",
|
||||
prefillTip: "",
|
||||
detailData: createEmptyDetailData(),
|
||||
counterpartyVisible: false,
|
||||
counterpartyLoading: false,
|
||||
counterpartyRefreshing: false,
|
||||
counterpartyBackfillLoading: false,
|
||||
counterpartyBackfillTimer: null,
|
||||
counterpartyData: createEmptyCounterpartyData(),
|
||||
queryParams: createDefaultQueryParams(this.projectId),
|
||||
optionData: createEmptyOptionData(),
|
||||
};
|
||||
@@ -642,6 +724,9 @@ export default {
|
||||
return this.resultMode === "counterparty" ? this.counterpartyTotal : this.total;
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.counterpartyBackfillTimer) clearInterval(this.counterpartyBackfillTimer);
|
||||
},
|
||||
watch: {
|
||||
dateRange(value) {
|
||||
this.queryParams.transactionStartTime = value && value[0] ? value[0] : "";
|
||||
@@ -838,6 +923,53 @@ export default {
|
||||
this.detailLoading = false;
|
||||
this.detailData = createEmptyDetailData();
|
||||
},
|
||||
async openCounterpartyDetail(counterpartyName) {
|
||||
if (!this.projectId || !counterpartyName) return;
|
||||
this.counterpartyVisible = true;
|
||||
this.counterpartyLoading = true;
|
||||
try {
|
||||
const response = await getCounterpartyEnterpriseDetail(this.projectId, counterpartyName);
|
||||
this.counterpartyData = { ...createEmptyCounterpartyData(), ...(response.data || {}) };
|
||||
} catch (error) {
|
||||
this.counterpartyVisible = false;
|
||||
this.$message.error("加载对手方工商信息失败");
|
||||
} finally {
|
||||
this.counterpartyLoading = false;
|
||||
}
|
||||
},
|
||||
async refreshCounterparty() {
|
||||
this.counterpartyRefreshing = true;
|
||||
try {
|
||||
const response = await refreshCounterpartyEnterprise({ projectId: this.projectId, counterpartyName: this.counterpartyData.counterpartyName });
|
||||
this.counterpartyData = { ...createEmptyCounterpartyData(), ...(response.data || {}) };
|
||||
this.$message.success("对手方工商信息已更新");
|
||||
} finally {
|
||||
this.counterpartyRefreshing = false;
|
||||
}
|
||||
},
|
||||
handleCounterpartyBackfill() {
|
||||
this.$confirm("确认启动全部项目对手方工商信息历史补全?", "提示", { type: "warning" }).then(() => {
|
||||
this.counterpartyBackfillLoading = true;
|
||||
return startCounterpartyEnterpriseBackfill();
|
||||
}).then(response => this.pollCounterpartyBackfill(response.data)).catch(() => { this.counterpartyBackfillLoading = false; });
|
||||
},
|
||||
pollCounterpartyBackfill(taskId) {
|
||||
const query = () => getCounterpartyEnterpriseBackfillStatus(taskId).then(response => {
|
||||
const status = response.data || {};
|
||||
if (status.status === "COMPLETED") {
|
||||
clearInterval(this.counterpartyBackfillTimer);
|
||||
this.counterpartyBackfillTimer = null;
|
||||
this.counterpartyBackfillLoading = false;
|
||||
this.$notify({ title: "对手方工商补全完成", message: `成功 ${status.successCount || 0},失败 ${status.failureCount || 0}`, type: status.failureCount ? "warning" : "success" });
|
||||
}
|
||||
}).catch(() => {
|
||||
clearInterval(this.counterpartyBackfillTimer);
|
||||
this.counterpartyBackfillTimer = null;
|
||||
this.counterpartyBackfillLoading = false;
|
||||
});
|
||||
query();
|
||||
this.counterpartyBackfillTimer = setInterval(query, 2000);
|
||||
},
|
||||
handleAddEvidence() {
|
||||
const detail = this.detailData || {};
|
||||
const sourceRecordId = buildFlowEvidenceFingerprint(detail);
|
||||
@@ -881,6 +1013,13 @@ export default {
|
||||
formatDate(value) {
|
||||
return value ? parseTime(value, "{y}-{m}-{d} {h}:{i}:{s}") : "-";
|
||||
},
|
||||
formatDateOnly(value) {
|
||||
return value ? parseTime(value, "{y}-{m}-{d}") : "-";
|
||||
},
|
||||
formatCapital(amount, unit) {
|
||||
if (amount === null || amount === undefined || amount === "") return "-";
|
||||
return `${amount}${unit || ""}`;
|
||||
},
|
||||
formatAmount(value) {
|
||||
if (value === null || value === undefined || value === "") {
|
||||
return "-";
|
||||
@@ -1010,6 +1149,26 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.counterparty-link {
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.counterparty-alert {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.counterparty-section-title {
|
||||
margin: 18px 0 10px;
|
||||
color: #303133;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.shell-sidebar,
|
||||
.shell-main {
|
||||
border: 1px solid #ebeef5;
|
||||
|
||||
Reference in New Issue
Block a user