feat(credit): 企业详情页面增加子表数据导入功能

- 为18个信用相关API的导入方法添加companyId参数支持
- 在企业详情页面的各个子表tab中添加导入和刷新按钮
- 创建credit-company-related-import组件实现统一的导入弹窗
- 新增taxpayerCode字段到用户信息模型中
- 移除企业详情页面中冗余的描述项注释代码
- 实现基于企业ID或纳税人识别号的数据加载缓存机制
- 添加导入模板下载功能和文件类型验证
This commit is contained in:
2026-01-05 12:44:16 +08:00
parent 74b06dbc17
commit b494a7d951
3 changed files with 156 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
VITE_APP_NAME=后台管理(开发环境)
#VITE_API_URL=http://127.0.0.1:9200/api
VITE_API_URL=http://127.0.0.1:9200/api
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api

View File

@@ -107,9 +107,12 @@ export async function getCreditUser(id: number) {
/**
* 导入招投标
*/
export async function importCreditUsers(file: File) {
export async function importCreditUsers(file: File, companyId?: number) {
const formData = new FormData();
formData.append('file', file);
if (companyId != null) {
formData.append('companyId', String(companyId));
}
const res = await request.post<ApiResult<unknown>>(
'/credit/credit-user/import',
formData,

View File

@@ -93,24 +93,69 @@
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import CreditCompanyRelatedImport from './credit-company-related-import.vue';
import { pageCreditProject, importCreditProject } from '@/api/credit/creditProject';
import { pageCreditExternal, importCreditExternal } from '@/api/credit/creditExternal';
import { pageCreditRiskRelation, importCreditRiskRelation } from '@/api/credit/creditRiskRelation';
import { pageCreditCompetitor, importCreditCompetitor } from '@/api/credit/creditCompetitor';
import { pageCreditSupplier, importCreditSupplier } from '@/api/credit/creditSupplier';
import { pageCreditCustomer, importCreditCustomer } from '@/api/credit/creditCustomer';
import { pageCreditCaseFiling, importCreditCaseFiling } from '@/api/credit/creditCaseFiling';
import { pageCreditMediation, importCreditMediation } from '@/api/credit/creditMediation';
import { pageCreditCourtSession, importCreditCourtSession } from '@/api/credit/creditCourtSession';
import { pageCreditCourtAnnouncement, importCreditCourtAnnouncement } from '@/api/credit/creditCourtAnnouncement';
import { pageCreditDeliveryNotice, importCreditDeliveryNotice } from '@/api/credit/creditDeliveryNotice';
import { pageCreditJudicialDocument, importCreditJudicialDocument } from '@/api/credit/creditJudicialDocument';
import { pageCreditJudgmentDebtor, importCreditJudgmentDebtor } from '@/api/credit/creditJudgmentDebtor';
import { pageCreditBreachOfTrust, importCreditBreachOfTrust } from '@/api/credit/creditBreachOfTrust';
import { pageCreditFinalVersion, importCreditFinalVersion } from '@/api/credit/creditFinalVersion';
import { pageCreditUser, importCreditUsers } from '@/api/credit/creditUser';
import {
pageCreditExternal,
importCreditExternal
} from '@/api/credit/creditExternal';
import {
pageCreditRiskRelation,
importCreditRiskRelation
} from '@/api/credit/creditRiskRelation';
import {
pageCreditCompetitor,
importCreditCompetitor
} from '@/api/credit/creditCompetitor';
import {
pageCreditSupplier,
importCreditSupplier
} from '@/api/credit/creditSupplier';
import {
pageCreditCustomer,
importCreditCustomer
} from '@/api/credit/creditCustomer';
import {
pageCreditCaseFiling,
importCreditCaseFiling
} from '@/api/credit/creditCaseFiling';
import {
pageCreditMediation,
importCreditMediation
} from '@/api/credit/creditMediation';
import {
pageCreditCourtSession,
importCreditCourtSession
} from '@/api/credit/creditCourtSession';
import {
pageCreditCourtAnnouncement,
importCreditCourtAnnouncement
} from '@/api/credit/creditCourtAnnouncement';
import {
pageCreditDeliveryNotice,
importCreditDeliveryNotice
} from '@/api/credit/creditDeliveryNotice';
import {
pageCreditJudicialDocument,
importCreditJudicialDocument
} from '@/api/credit/creditJudicialDocument';
import {
pageCreditJudgmentDebtor,
importCreditJudgmentDebtor
} from '@/api/credit/creditJudgmentDebtor';
import {
pageCreditBreachOfTrust,
importCreditBreachOfTrust
} from '@/api/credit/creditBreachOfTrust';
import {
pageCreditFinalVersion,
importCreditFinalVersion
} from '@/api/credit/creditFinalVersion';
import { pageCreditXgxf, importCreditXgxf } from '@/api/credit/creditXgxf';
import { pageCreditGqdj, importCreditGqdj } from '@/api/credit/creditGqdj';
import { pageCreditJudiciary, importCreditJudiciaries } from '@/api/credit/creditJudiciary';
import {
pageCreditJudiciary,
importCreditJudiciaries
} from '@/api/credit/creditJudiciary';
const props = defineProps<{
// 弹窗是否打开
@@ -161,9 +206,9 @@
const tabApiMap: Record<string, TabApiConfig> = {
招投标: {
page: pageCreditProject as any,
importFn: importCreditProject as any,
templatePath: '/credit/credit-project/import/template'
page: pageCreditUser as any,
importFn: importCreditUsers as any,
templatePath: '/credit/credit-user/import/template'
},
对外投资: {
page: pageCreditExternal as any,
@@ -235,7 +280,7 @@
importFn: importCreditFinalVersion as any,
templatePath: '/credit/credit-final-version/import/template'
},
'限制高消费': {
限制高消费: {
page: pageCreditXgxf as any,
importFn: importCreditXgxf as any,
templatePath: '/credit/credit-xgxf/import/template'
@@ -259,6 +304,69 @@
ellipsis?: boolean;
};
type TabColumnConfig = {
order?: string[];
hidden?: string[];
titleMap?: Record<string, string>;
};
const commonHiddenColumnKeys = new Set<string>([
'deleted',
'tenantId',
'userId',
'companyId'
]);
const commonTitleMap: Record<string, string> = {
id: 'ID',
name: '被执行人名称',
name1: '被执行人',
code: '税号',
url: '链接地址',
status: '状态',
comments: '备注',
createTime: '创建时间',
updateTime: '修改时间'
};
// 每个tab的“字段顺序/隐藏字段/中文表头”在这里配置
const tabColumnConfigMap: Record<string, TabColumnConfig> = {
招投标: {
order: [
'name',
'role',
'caseNumber',
'procurementName',
'winningName',
'winningPrice',
'releaseDate',
'url',
'createTime',
'updateTime'
],
hidden: [
'type',
'parentId',
'sortNumber',
'recommend',
'expirationTime',
'updateTime'
],
titleMap: {
name: '项目名称',
role: '企业角色',
caseNumber: '案号',
procurementName: '招采单位名称',
winningName: '中标单位名称',
winningPrice: '中标金额',
releaseDate: '发布日期',
url: '链接地址',
createTime: '创建时间',
updateTime: '修改时间'
}
}
};
type TabState = {
loading: boolean;
data: Record<string, any>[];
@@ -280,7 +388,9 @@
// 子表导入弹窗
const showRelatedImport = ref(false);
const relatedImportTabKey = ref(tabList[0].key);
const relatedImportConfig = computed(() => tabApiMap[relatedImportTabKey.value]);
const relatedImportConfig = computed(
() => tabApiMap[relatedImportTabKey.value]
);
const relatedImportTitle = computed(() => {
const tab = tabList.find((t) => t.key === relatedImportTabKey.value);
return `${tab?.label ?? relatedImportTabKey.value}批量导入`;
@@ -405,12 +515,26 @@
return record.id ?? record.code ?? record.key ?? index;
};
const buildColumns = (rows: Record<string, any>[]): TableColumn[] => {
const buildColumns = (
tabKey: string,
rows: Record<string, any>[]
): TableColumn[] => {
if (!rows.length) {
return [];
}
return Object.keys(rows[0]).map((key) => ({
title: key,
const config = tabColumnConfigMap[tabKey];
const hidden = new Set<string>([
...commonHiddenColumnKeys,
...(config?.hidden ?? [])
]);
const titleMap = { ...commonTitleMap, ...(config?.titleMap ?? {}) };
const keysFromData = Object.keys(rows[0]);
const keys = config?.order?.length ? config.order : keysFromData;
const finalKeys = keys.filter((k) => !hidden.has(k));
return finalKeys.map((key) => ({
title: titleMap[key] ?? key,
dataIndex: key,
key,
ellipsis: true
@@ -464,7 +588,7 @@
limit: 500
});
state.data = res?.list || [];
state.columns = buildColumns(state.data);
state.columns = buildColumns(key, state.data);
state.loadedIdentity = identity;
} catch (e: any) {
state.data = [];