This commit is contained in:
wkc
2026-04-17 16:01:41 +08:00
parent e0629f22e5
commit c278d11390
37 changed files with 3722 additions and 4 deletions

View File

@@ -0,0 +1,78 @@
import request from '@/utils/request'
// 查询实体库列表
export function listEnterpriseBaseInfo(query) {
return request({
url: '/ccdi/enterpriseBaseInfo/list',
method: 'get',
params: query
})
}
// 查询实体库详细
export function getEnterpriseBaseInfo(socialCreditCode) {
return request({
url: '/ccdi/enterpriseBaseInfo/' + socialCreditCode,
method: 'get'
})
}
// 新增实体库
export function addEnterpriseBaseInfo(data) {
return request({
url: '/ccdi/enterpriseBaseInfo',
method: 'post',
data: data
})
}
// 修改实体库
export function updateEnterpriseBaseInfo(data) {
return request({
url: '/ccdi/enterpriseBaseInfo',
method: 'put',
data: data
})
}
// 删除实体库
export function delEnterpriseBaseInfo(socialCreditCodes) {
return request({
url: '/ccdi/enterpriseBaseInfo/' + socialCreditCodes,
method: 'delete'
})
}
// 下载导入模板
export function importTemplate() {
return request({
url: '/ccdi/enterpriseBaseInfo/importTemplate',
method: 'post'
})
}
// 导入实体库
export function importData(data) {
return request({
url: '/ccdi/enterpriseBaseInfo/importData',
method: 'post',
data: data
})
}
// 查询导入状态
export function getImportStatus(taskId) {
return request({
url: '/ccdi/enterpriseBaseInfo/importStatus/' + taskId,
method: 'get'
})
}
// 查询导入失败记录
export function getImportFailures(taskId, pageNum, pageSize) {
return request({
url: '/ccdi/enterpriseBaseInfo/importFailures/' + taskId,
method: 'get',
params: { pageNum, pageSize }
})
}

View File

@@ -89,3 +89,23 @@ export function getDataSourceOptions() {
method: 'get'
})
}
/**
* 查询实体风险等级选项
*/
export function getEnterpriseRiskLevelOptions() {
return request({
url: '/ccdi/enum/enterpriseRiskLevel',
method: 'get'
})
}
/**
* 查询企业来源选项
*/
export function getEnterpriseSourceOptions() {
return request({
url: '/ccdi/enum/enterpriseSource',
method: 'get'
})
}

View File

@@ -0,0 +1,977 @@
<template>
<div class="app-container">
<el-form ref="queryForm" :model="queryParams" size="small" :inline="true" v-show="showSearch" label-width="110px">
<el-form-item label="企业名称" prop="enterpriseName">
<el-input
v-model="queryParams.enterpriseName"
placeholder="请输入企业名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="统一社会信用代码" prop="socialCreditCode">
<el-input
v-model="queryParams.socialCreditCode"
placeholder="请输入统一社会信用代码"
clearable
maxlength="18"
style="width: 240px"
@input="queryParams.socialCreditCode = normalizeUpperCode(queryParams.socialCreditCode)"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="企业类型" prop="enterpriseType">
<el-select v-model="queryParams.enterpriseType" placeholder="请选择企业类型" clearable style="width: 240px">
<el-option
v-for="item in corpTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="企业性质" prop="enterpriseNature">
<el-select v-model="queryParams.enterpriseNature" placeholder="请选择企业性质" clearable style="width: 240px">
<el-option
v-for="item in corpNatureOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="行业分类" prop="industryClass">
<el-input
v-model="queryParams.industryClass"
placeholder="请输入行业分类"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="经营状态" prop="status">
<el-input
v-model="queryParams.status"
placeholder="请输入经营状态"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="风险等级" prop="riskLevel">
<el-select v-model="queryParams.riskLevel" placeholder="请选择风险等级" clearable style="width: 240px">
<el-option
v-for="item in riskLevelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="企业来源" prop="entSource">
<el-select v-model="queryParams.entSource" placeholder="请选择企业来源" clearable style="width: 240px">
<el-option
v-for="item in enterpriseSourceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['ccdi:enterpriseBaseInfo:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['ccdi:enterpriseBaseInfo:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-upload2"
size="mini"
@click="handleImport"
v-hasPermi="['ccdi:enterpriseBaseInfo:import']"
>导入</el-button>
</el-col>
<el-col :span="1.5" v-if="showFailureButton">
<el-tooltip :content="getLastImportTooltip()" placement="top">
<el-button
type="warning"
plain
icon="el-icon-warning"
size="mini"
@click="viewImportFailures"
>查看导入失败记录</el-button>
</el-tooltip>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="enterpriseBaseInfoList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="企业名称" align="center" prop="enterpriseName" min-width="180" show-overflow-tooltip />
<el-table-column label="统一社会信用代码" align="center" prop="socialCreditCode" width="180" show-overflow-tooltip />
<el-table-column label="企业类型" align="center" prop="enterpriseType" min-width="120" show-overflow-tooltip />
<el-table-column label="企业性质" align="center" prop="enterpriseNature" min-width="120" show-overflow-tooltip />
<el-table-column label="行业分类" align="center" prop="industryClass" min-width="120" show-overflow-tooltip />
<el-table-column label="所属行业" align="center" prop="industryName" min-width="120" show-overflow-tooltip />
<el-table-column label="法定代表人" align="center" prop="legalRepresentative" width="120" show-overflow-tooltip />
<el-table-column label="经营状态" align="center" prop="status" width="120">
<template slot-scope="scope">
<span>{{ formatStatus(scope.row.status) }}</span>
</template>
</el-table-column>
<el-table-column label="风险等级" align="center" prop="riskLevel" width="100">
<template slot-scope="scope">
<span>{{ formatRiskLevel(scope.row.riskLevel) }}</span>
</template>
</el-table-column>
<el-table-column label="企业来源" align="center" prop="entSource" width="120">
<template slot-scope="scope">
<span>{{ formatEnterpriseSource(scope.row.entSource) }}</span>
</template>
</el-table-column>
<el-table-column label="数据来源" align="center" prop="dataSource" width="120">
<template slot-scope="scope">
<span>{{ formatDataSource(scope.row.dataSource) }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
v-hasPermi="['ccdi:enterpriseBaseInfo:query']"
>详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['ccdi:enterpriseBaseInfo:edit']"
>编辑</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['ccdi:enterpriseBaseInfo:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<el-dialog :title="title" :visible.sync="open" width="1100px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="统一社会信用代码" prop="socialCreditCode">
<el-input
v-model="form.socialCreditCode"
placeholder="请输入统一社会信用代码"
maxlength="18"
:disabled="!isAdd"
@input="form.socialCreditCode = normalizeUpperCode(form.socialCreditCode)"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="企业名称" prop="enterpriseName">
<el-input v-model="form.enterpriseName" placeholder="请输入企业名称" maxlength="200" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="企业类型" prop="enterpriseType">
<el-select v-model="form.enterpriseType" placeholder="请选择企业类型" clearable style="width: 100%">
<el-option
v-for="item in corpTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="企业性质" prop="enterpriseNature">
<el-select v-model="form.enterpriseNature" placeholder="请选择企业性质" clearable style="width: 100%">
<el-option
v-for="item in corpNatureOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="行业分类" prop="industryClass">
<el-input v-model="form.industryClass" placeholder="请输入行业分类" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属行业" prop="industryName">
<el-input v-model="form.industryName" placeholder="请输入所属行业" maxlength="100" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="成立日期" prop="establishDate">
<el-date-picker
v-model="form.establishDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择成立日期"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注册地址" prop="registerAddress">
<el-input v-model="form.registerAddress" placeholder="请输入注册地址" maxlength="500" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="法定代表人" prop="legalRepresentative">
<el-input v-model="form.legalRepresentative" placeholder="请输入法定代表人" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="法定代表人证件类型" prop="legalCertType">
<el-select v-model="form.legalCertType" placeholder="请选择证件类型" clearable style="width: 100%">
<el-option
v-for="item in certTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="法定代表人证件号码" prop="legalCertNo">
<el-input v-model="form.legalCertNo" placeholder="请输入法定代表人证件号码" maxlength="50" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="经营状态" prop="status">
<el-input v-model="form.status" placeholder="请输入经营状态" maxlength="50" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="风险等级" prop="riskLevel">
<el-select v-model="form.riskLevel" placeholder="请选择风险等级" style="width: 100%">
<el-option
v-for="item in riskLevelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="企业来源" prop="entSource">
<el-select v-model="form.entSource" placeholder="请选择企业来源" style="width: 100%">
<el-option
v-for="item in enterpriseSourceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="数据来源" prop="dataSource">
<el-select v-model="form.dataSource" placeholder="请选择数据来源" style="width: 100%">
<el-option
v-for="item in dataSourceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="股东1" prop="shareholder1">
<el-input v-model="form.shareholder1" placeholder="请输入股东1" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="股东2" prop="shareholder2">
<el-input v-model="form.shareholder2" placeholder="请输入股东2" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="股东3" prop="shareholder3">
<el-input v-model="form.shareholder3" placeholder="请输入股东3" maxlength="100" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="股东4" prop="shareholder4">
<el-input v-model="form.shareholder4" placeholder="请输入股东4" maxlength="100" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="股东5" prop="shareholder5">
<el-input v-model="form.shareholder5" placeholder="请输入股东5" maxlength="100" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-dialog title="实体库详情" :visible.sync="detailOpen" width="1000px" append-to-body>
<el-descriptions :column="2" border>
<el-descriptions-item label="统一社会信用代码">{{ detailData.socialCreditCode || '-' }}</el-descriptions-item>
<el-descriptions-item label="企业名称">{{ detailData.enterpriseName || '-' }}</el-descriptions-item>
<el-descriptions-item label="企业类型">{{ detailData.enterpriseType || '-' }}</el-descriptions-item>
<el-descriptions-item label="企业性质">{{ detailData.enterpriseNature || '-' }}</el-descriptions-item>
<el-descriptions-item label="行业分类">{{ detailData.industryClass || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属行业">{{ detailData.industryName || '-' }}</el-descriptions-item>
<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="法定代表人证件类型">{{ detailData.legalCertType || '-' }}</el-descriptions-item>
<el-descriptions-item label="法定代表人证件号码">{{ detailData.legalCertNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="经营状态">{{ formatStatus(detailData.status) }}</el-descriptions-item>
<el-descriptions-item label="风险等级">{{ formatRiskLevel(detailData.riskLevel) }}</el-descriptions-item>
<el-descriptions-item label="企业来源">{{ formatEnterpriseSource(detailData.entSource) }}</el-descriptions-item>
<el-descriptions-item label="数据来源">{{ formatDataSource(detailData.dataSource) }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ parseTime(detailData.createTime) || '-' }}</el-descriptions-item>
<el-descriptions-item label="股东1">{{ detailData.shareholder1 || '-' }}</el-descriptions-item>
<el-descriptions-item label="股东2">{{ detailData.shareholder2 || '-' }}</el-descriptions-item>
<el-descriptions-item label="股东3">{{ detailData.shareholder3 || '-' }}</el-descriptions-item>
<el-descriptions-item label="股东4">{{ detailData.shareholder4 || '-' }}</el-descriptions-item>
<el-descriptions-item label="股东5">{{ detailData.shareholder5 || '-' }}</el-descriptions-item>
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button @click="detailOpen = false"> </el-button>
</div>
</el-dialog>
<el-dialog
:title="upload.title"
:visible.sync="upload.open"
width="400px"
append-to-body
@close="handleImportDialogClose"
v-loading="upload.isUploading"
element-loading-text="正在导入数据,请稍候..."
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.7)"
>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline;" @click="downloadImportTemplate">下载模板</el-link>
</div>
<div class="el-upload__tip" slot="tip">
<span>仅允许导入"xls""xlsx"格式文件</span>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm" :loading="upload.isUploading"> </el-button>
<el-button @click="upload.open = false" :disabled="upload.isUploading"> </el-button>
</div>
</el-dialog>
<el-dialog title="实体库导入失败记录" :visible.sync="failureDialogVisible" width="1200px" append-to-body>
<el-alert
v-if="lastImportInfo"
:title="lastImportInfo"
type="info"
:closable="false"
style="margin-bottom: 15px"
/>
<el-table :data="failureList" v-loading="failureLoading">
<el-table-column label="企业名称" prop="enterpriseName" align="center" min-width="180" />
<el-table-column label="统一社会信用代码" prop="socialCreditCode" align="center" min-width="180" />
<el-table-column label="企业类型" prop="enterpriseType" align="center" min-width="120" />
<el-table-column label="企业性质" prop="enterpriseNature" align="center" min-width="120" />
<el-table-column label="风险等级" prop="riskLevel" align="center" min-width="100" />
<el-table-column label="企业来源" prop="entSource" align="center" min-width="120" />
<el-table-column
label="失败原因"
prop="errorMessage"
align="center"
min-width="220"
:show-overflow-tooltip="true"
/>
</el-table>
<pagination
v-show="failureTotal > 0"
:total="failureTotal"
:page.sync="failureQueryParams.pageNum"
:limit.sync="failureQueryParams.pageSize"
@pagination="getFailureList"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="failureDialogVisible = false"> </el-button>
<el-button type="danger" plain @click="clearImportHistory">清除历史记录</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
addEnterpriseBaseInfo,
delEnterpriseBaseInfo,
getEnterpriseBaseInfo,
getImportFailures,
getImportStatus,
listEnterpriseBaseInfo,
updateEnterpriseBaseInfo
} from "@/api/ccdiEnterpriseBaseInfo";
import {
getCertTypeOptions,
getCorpNatureOptions,
getCorpTypeOptions,
getDataSourceOptions,
getEnterpriseRiskLevelOptions,
getEnterpriseSourceOptions
} from "@/api/ccdiEnum";
import { getToken } from "@/utils/auth";
const socialCreditCodePattern = /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/;
export default {
name: "EnterpriseBaseInfo",
data() {
return {
loading: true,
ids: [],
single: true,
multiple: true,
showSearch: true,
total: 0,
enterpriseBaseInfoList: [],
title: "",
open: false,
detailOpen: false,
isAdd: true,
detailData: {},
corpTypeOptions: [],
corpNatureOptions: [],
certTypeOptions: [],
riskLevelOptions: [],
enterpriseSourceOptions: [],
dataSourceOptions: [],
queryParams: {
pageNum: 1,
pageSize: 10,
enterpriseName: null,
socialCreditCode: null,
enterpriseType: null,
enterpriseNature: null,
industryClass: null,
status: null,
riskLevel: null,
entSource: null
},
form: {},
rules: {
socialCreditCode: [
{ required: true, message: "统一社会信用代码不能为空", trigger: "blur" },
{ pattern: socialCreditCodePattern, message: "请输入正确的18位统一社会信用代码", trigger: "blur" }
],
enterpriseName: [
{ required: true, message: "企业名称不能为空", trigger: "blur" },
{ max: 200, message: "企业名称长度不能超过200个字符", trigger: "blur" }
],
status: [
{ required: true, message: "经营状态不能为空", trigger: "blur" }
],
riskLevel: [
{ required: true, message: "请选择风险等级", trigger: "change" }
],
entSource: [
{ required: true, message: "请选择企业来源", trigger: "change" }
],
dataSource: [
{ required: true, message: "请选择数据来源", trigger: "change" }
]
},
upload: {
open: false,
title: "",
isUploading: false,
headers: { Authorization: "Bearer " + getToken() },
url: process.env.VUE_APP_BASE_API + "/ccdi/enterpriseBaseInfo/importData"
},
pollingTimer: null,
showFailureButton: false,
currentTaskId: null,
failureDialogVisible: false,
failureList: [],
failureLoading: false,
failureTotal: 0,
failureQueryParams: {
pageNum: 1,
pageSize: 10
}
};
},
computed: {
lastImportInfo() {
var savedTask = this.getImportTaskFromStorage();
if (savedTask && savedTask.totalCount) {
return "导入时间: " + this.parseTime(savedTask.saveTime) +
" | 总数: " + savedTask.totalCount + "条" +
" | 成功: " + savedTask.successCount + "条" +
" | 失败: " + savedTask.failureCount + "条";
}
return "";
}
},
created() {
this.getList();
this.loadOptions();
this.restoreImportState();
},
beforeDestroy() {
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
}
},
methods: {
loadOptions() {
Promise.all([
getCorpTypeOptions(),
getCorpNatureOptions(),
getCertTypeOptions(),
getEnterpriseRiskLevelOptions(),
getEnterpriseSourceOptions(),
getDataSourceOptions()
]).then(([corpTypeRes, corpNatureRes, certTypeRes, riskLevelRes, enterpriseSourceRes, dataSourceRes]) => {
this.corpTypeOptions = corpTypeRes.data || [];
this.corpNatureOptions = corpNatureRes.data || [];
this.certTypeOptions = certTypeRes.data || [];
this.riskLevelOptions = riskLevelRes.data || [];
this.enterpriseSourceOptions = enterpriseSourceRes.data || [];
this.dataSourceOptions = dataSourceRes.data || [];
});
},
getList() {
this.loading = true;
listEnterpriseBaseInfo(this.queryParams).then(response => {
this.enterpriseBaseInfoList = response.rows;
this.total = response.total;
this.loading = false;
}).catch(() => {
this.loading = false;
});
},
reset() {
this.form = {
socialCreditCode: null,
enterpriseName: null,
enterpriseType: null,
enterpriseNature: null,
industryClass: null,
industryName: null,
establishDate: null,
registerAddress: null,
legalRepresentative: null,
legalCertType: null,
legalCertNo: null,
shareholder1: null,
shareholder2: null,
shareholder3: null,
shareholder4: null,
shareholder5: null,
status: null,
riskLevel: null,
entSource: null,
dataSource: null
};
this.resetForm("form");
},
cancel() {
this.open = false;
this.reset();
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.socialCreditCode);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
handleAdd() {
this.reset();
this.isAdd = true;
this.open = true;
this.title = "新增实体库";
},
handleDetail(row) {
getEnterpriseBaseInfo(row.socialCreditCode).then(response => {
this.detailData = response.data || {};
this.detailOpen = true;
});
},
handleUpdate(row) {
this.reset();
this.isAdd = false;
var socialCreditCode = row.socialCreditCode || this.ids[0];
getEnterpriseBaseInfo(socialCreditCode).then(response => {
this.form = response.data || {};
this.open = true;
this.title = "编辑实体库";
});
},
submitForm() {
this.$refs["form"].validate(valid => {
if (!valid) {
return;
}
var payload = this.normalizePayload(this.form);
if (this.isAdd) {
addEnterpriseBaseInfo(payload).then(() => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
} else {
updateEnterpriseBaseInfo(payload).then(() => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
}
});
},
handleDelete(row) {
var socialCreditCodes = row && row.socialCreditCode ? row.socialCreditCode : this.ids;
this.$modal.confirm('是否确认删除统一社会信用代码为"' + socialCreditCodes + '"的数据项?').then(function() {
return delEnterpriseBaseInfo(socialCreditCodes);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
handleImport() {
this.upload.title = "实体库数据导入";
this.upload.open = true;
},
handleImportDialogClose() {
this.$nextTick(() => {
if (this.$refs.upload) {
this.$refs.upload.clearFiles();
}
});
},
downloadImportTemplate() {
this.download('ccdi/enterpriseBaseInfo/importTemplate', {}, '实体库管理模板_' + new Date().getTime() + '.xlsx');
},
handleFileUploadProgress() {
this.upload.isUploading = true;
},
handleFileSuccess(response) {
this.upload.isUploading = false;
this.upload.open = false;
if (response.code !== 200) {
this.$modal.msgError(response.msg || "导入失败");
return;
}
if (!response.data || !response.data.taskId) {
this.$modal.msgError("导入任务创建失败:缺少任务ID");
return;
}
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
}
this.clearImportTaskFromStorage();
this.currentTaskId = response.data.taskId;
this.showFailureButton = false;
this.saveImportTaskToStorage({
taskId: response.data.taskId,
status: 'PROCESSING',
hasFailures: false
});
this.$notify({
title: '导入任务已提交',
message: '正在后台处理中,处理完成后将通知您',
type: 'info',
duration: 3000
});
this.startImportStatusPolling(response.data.taskId);
},
startImportStatusPolling(taskId) {
var pollCount = 0;
var maxPolls = 150;
this.pollingTimer = setInterval(async () => {
try {
pollCount++;
if (pollCount > maxPolls) {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
this.$modal.msgWarning('导入任务处理超时,请联系管理员');
return;
}
var response = await getImportStatus(taskId);
if (response.data && response.data.status !== 'PROCESSING') {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
this.handleImportComplete(response.data);
}
} catch (error) {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
this.$modal.msgError('查询导入状态失败: ' + error.message);
}
}, 2000);
},
handleImportComplete(statusResult) {
this.saveImportTaskToStorage({
taskId: statusResult.taskId,
status: statusResult.status,
hasFailures: statusResult.failureCount > 0,
totalCount: statusResult.totalCount,
successCount: statusResult.successCount,
failureCount: statusResult.failureCount
});
this.getList();
if (statusResult.status === 'SUCCESS') {
this.showFailureButton = false;
this.$notify({
title: '导入完成',
message: '全部成功!共导入' + statusResult.totalCount + '条数据',
type: 'success',
duration: 5000
});
} else if (statusResult.failureCount > 0) {
this.showFailureButton = true;
this.currentTaskId = statusResult.taskId;
this.$notify({
title: '导入完成',
message: '成功' + statusResult.successCount + '条,失败' + statusResult.failureCount + '条',
type: 'warning',
duration: 5000
});
}
},
viewImportFailures() {
this.failureDialogVisible = true;
this.failureQueryParams.pageNum = 1;
this.getFailureList();
},
getFailureList() {
if (!this.currentTaskId) {
this.failureList = [];
this.failureTotal = 0;
return;
}
this.failureLoading = true;
getImportFailures(this.currentTaskId, this.failureQueryParams.pageNum, this.failureQueryParams.pageSize).then(response => {
this.failureList = response.rows;
this.failureTotal = response.total;
this.failureLoading = false;
}).catch(error => {
this.failureLoading = false;
this.$modal.msgError('查询失败记录失败: ' + error.message);
});
},
submitFileForm() {
this.$refs.upload.submit();
},
saveImportTaskToStorage(taskData) {
try {
localStorage.setItem('enterprise_base_info_import_last_task', JSON.stringify({
saveTime: Date.now(),
...taskData
}));
} catch (error) {
console.error('保存导入任务状态失败:', error);
}
},
getImportTaskFromStorage() {
try {
var data = localStorage.getItem('enterprise_base_info_import_last_task');
if (!data) {
return null;
}
var task = JSON.parse(data);
if (!task || !task.taskId) {
this.clearImportTaskFromStorage();
return null;
}
var sevenDays = 7 * 24 * 60 * 60 * 1000;
if (task.saveTime && Date.now() - task.saveTime > sevenDays) {
this.clearImportTaskFromStorage();
return null;
}
return task;
} catch (error) {
this.clearImportTaskFromStorage();
return null;
}
},
clearImportTaskFromStorage() {
try {
localStorage.removeItem('enterprise_base_info_import_last_task');
} catch (error) {
console.error('清除导入任务状态失败:', error);
}
},
restoreImportState() {
var savedTask = this.getImportTaskFromStorage();
if (!savedTask) {
this.showFailureButton = false;
this.currentTaskId = null;
return;
}
this.currentTaskId = savedTask.taskId;
this.showFailureButton = !!savedTask.hasFailures;
},
clearImportHistory() {
this.$confirm('确认清除上次导入记录?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.clearImportTaskFromStorage();
this.showFailureButton = false;
this.currentTaskId = null;
this.failureDialogVisible = false;
this.$message.success('已清除');
}).catch(() => {});
},
getLastImportTooltip() {
var savedTask = this.getImportTaskFromStorage();
if (savedTask && savedTask.saveTime) {
return '上次导入: ' + this.parseTime(savedTask.saveTime, '{y}-{m}-{d} {h}:{i}');
}
return '';
},
normalizeUpperCode(value) {
if (!value) {
return value;
}
return String(value).replace(/\s+/g, '').toUpperCase();
},
normalizePayload(form) {
var payload = {};
Object.keys(form).forEach(key => {
var value = form[key];
if (value === "") {
payload[key] = null;
} else if (key === "socialCreditCode") {
payload[key] = this.normalizeUpperCode(value);
} else {
payload[key] = value;
}
});
return payload;
},
getOptionLabel(options, value) {
if (!value) {
return "-";
}
var matched = (options || []).find(item => item.value === value);
return matched ? matched.label : value;
},
formatRiskLevel(value) {
return this.getOptionLabel(this.riskLevelOptions, value);
},
formatEnterpriseSource(value) {
return this.getOptionLabel(this.enterpriseSourceOptions, value);
},
formatDataSource(value) {
return this.getOptionLabel(this.dataSourceOptions, value);
},
formatStatus(value) {
return value || "-";
}
}
};
</script>
<style scoped>
.el-upload__tip {
line-height: 1.6;
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<el-dialog :title="title" :visible.sync="dialogVisible" width="680px" append-to-body @close="handleClose">
<el-form ref="formRef" :model="localForm" :rules="rules" label-width="140px">
<el-form-item label="所属中介">
<el-input :value="ownerName" disabled />
</el-form-item>
<el-form-item label="统一社会信用代码" prop="socialCreditCode">
<el-input v-model="localForm.socialCreditCode" placeholder="请输入统一社会信用代码" maxlength="18" clearable />
</el-form-item>
<el-form-item label="关联角色/职务">
<el-input v-model="localForm.relationPersonPost" placeholder="请输入关联角色/职务" maxlength="100" clearable />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="localForm.remark" type="textarea" :rows="3" maxlength="500" show-word-limit />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSubmit"> </el-button>
<el-button @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: "EnterpriseRelationEditDialog",
props: {
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: ""
},
form: {
type: Object,
default: () => ({})
},
ownerName: {
type: String,
default: ""
}
},
data() {
return {
dialogVisible: false,
localForm: {},
rules: {
socialCreditCode: [{ required: true, message: "统一社会信用代码不能为空", trigger: "blur" }]
}
};
},
watch: {
visible: {
immediate: true,
handler(val) {
this.dialogVisible = val;
}
},
dialogVisible(val) {
this.$emit("update:visible", val);
},
form: {
immediate: true,
deep: true,
handler(val) {
this.localForm = { ...val };
}
}
},
methods: {
handleSubmit() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$emit("submit", { ...this.localForm });
}
});
},
handleClose() {
this.dialogVisible = false;
this.$emit("close");
}
}
};
</script>

View File

@@ -0,0 +1,192 @@
<template>
<el-dialog :title="title" :visible.sync="dialogVisible" width="820px" append-to-body @close="handleClose">
<el-form ref="formRef" :model="localForm" :rules="rules" label-width="120px">
<el-row>
<el-col :span="12">
<el-form-item label="所属中介">
<el-input :value="ownerName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="亲属关系" prop="personSubType">
<el-select v-model="localForm.personSubType" placeholder="请选择亲属关系" clearable style="width: 100%">
<el-option
v-for="item in filteredRelationOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input v-model="localForm.name" placeholder="请输入姓名" maxlength="100" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="证件号" prop="personId">
<el-input v-model="localForm.personId" placeholder="请输入证件号码" maxlength="50" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="人员类型">
<el-select v-model="localForm.personType" placeholder="请选择人员类型" clearable style="width: 100%">
<el-option
v-for="item in indivTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="证件类型">
<el-select v-model="localForm.idType" placeholder="请选择证件类型" clearable style="width: 100%">
<el-option
v-for="item in certTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="性别">
<el-select v-model="localForm.gender" placeholder="请选择性别" clearable style="width: 100%">
<el-option
v-for="item in genderOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码">
<el-input v-model="localForm.mobile" placeholder="请输入手机号码" maxlength="20" clearable />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="联系地址">
<el-input v-model="localForm.contactAddress" placeholder="请输入联系地址" maxlength="200" clearable />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="所在公司">
<el-input v-model="localForm.company" placeholder="请输入所在公司" maxlength="200" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="职位">
<el-input v-model="localForm.position" placeholder="请输入职位" maxlength="100" clearable />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注">
<el-input v-model="localForm.remark" type="textarea" :rows="3" maxlength="500" show-word-limit />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSubmit"> </el-button>
<el-button @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: "RelativeEditDialog",
props: {
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: ""
},
form: {
type: Object,
default: () => ({})
},
ownerName: {
type: String,
default: ""
},
relationTypeOptions: {
type: Array,
default: () => []
},
indivTypeOptions: {
type: Array,
default: () => []
},
genderOptions: {
type: Array,
default: () => []
},
certTypeOptions: {
type: Array,
default: () => []
}
},
data() {
return {
dialogVisible: false,
localForm: {},
rules: {
name: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
personId: [{ required: true, message: "证件号不能为空", trigger: "blur" }],
personSubType: [{ required: true, message: "亲属关系不能为空", trigger: "change" }]
}
};
},
computed: {
filteredRelationOptions() {
return this.relationTypeOptions.filter(item => item.value !== "本人");
}
},
watch: {
visible: {
immediate: true,
handler(val) {
this.dialogVisible = val;
}
},
dialogVisible(val) {
this.$emit("update:visible", val);
},
form: {
immediate: true,
deep: true,
handler(val) {
this.localForm = { ...val };
}
}
},
methods: {
handleSubmit() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$emit("submit", { ...this.localForm });
}
});
},
handleClose() {
this.dialogVisible = false;
this.$emit("close");
}
}
};
</script>