feat(api): 添加百色中学和诊所相关API接口

- 新增百色中学报名记录相关接口和数据模型
- 新增百色中学分部、班级、年代、年级管理接口
- 新增百色中学捐款记录和排行相关接口
- 新增诊所挂号和医生入驻申请接口
- 添加相应的数据传输对象和搜索参数模型
- 实现分页查询、增删改查等基础操作接口
- 集成请求处理和错误处理机制
This commit is contained in:
2026-01-07 14:44:06 +08:00
parent 424e5641bb
commit d32fd4f711
459 changed files with 79443 additions and 1460 deletions

View File

@@ -0,0 +1,659 @@
<!-- 编辑弹窗 -->
<template>
<a-drawer
width="80%"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="data?.name"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
>
<a-descriptions
:column="descriptionColumns"
size="small"
bordered
class="credit-company-descriptions"
>
<a-descriptions-item label="企业名称">
{{ formatValue(form.matchName) }}
</a-descriptions-item>
<a-descriptions-item label="法定代表人">
{{ formatValue(form.legalPerson) }}
</a-descriptions-item>
<a-descriptions-item label="统一社会信用代码">
{{ formatValue(form.code) }}
</a-descriptions-item>
<a-descriptions-item label="企业地址">
{{ formatValue(form.address) }}
</a-descriptions-item>
<a-descriptions-item label="电话">
{{ formatValue(form.tel) }}
</a-descriptions-item>
<a-descriptions-item label="更多电话">
{{ formatValue(form.moreTel) }}
</a-descriptions-item>
</a-descriptions>
<a-divider style="margin: 16px 0" />
<a-tabs
v-model:activeKey="activeTab"
type="card"
class="credit-company-tabs"
>
<a-tab-pane v-for="tab in tabList" :key="tab.key" :tab="tab.label">
<a-space style="margin-bottom: 12px">
<a-button
type="primary"
:disabled="!form.id"
@click="openRelatedImport(tab.key)"
>
导入
</a-button>
<a-button
:loading="tabState[tab.key].loading"
@click="reloadTab(tab.key)"
>
刷新
</a-button>
</a-space>
<a-table
v-if="tabState[tab.key].columns.length"
size="small"
:columns="tabState[tab.key].columns"
:data-source="tabState[tab.key].data"
:loading="tabState[tab.key].loading"
:row-key="getRowKey"
:scroll="{ x: 'max-content' }"
:pagination="false"
/>
<a-empty
v-else-if="!tabState[tab.key].loading"
description="暂无数据"
/>
</a-tab-pane>
</a-tabs>
<!-- 企业详情子表导入 -->
<CreditCompanyRelatedImport
v-model:visible="showRelatedImport"
:title="relatedImportTitle"
:templatePath="relatedImportTemplatePath"
:companyId="form.id"
:importFn="relatedImportFn"
@done="handleRelatedImportDone"
/>
</a-drawer>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import { CreditCompany } from '@/api/credit/creditCompany/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import CreditCompanyRelatedImport from './credit-company-related-import.vue';
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';
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: CreditCompany | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 是否显示最大化切换按钮
const maxable = ref(true);
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const descriptionColumns = computed(() => (styleResponsive.value ? 3 : 2));
const tabList = [
{ key: '招投标', label: '招投标' },
{ key: '对外投资', label: '对外投资' },
{ key: '风险关系', label: '风险关系' },
{ key: '竞争对手', label: '竞争对手' },
{ key: '供应商', label: '供应商' },
{ key: '客户', label: '客户' },
{ key: '立案信息', label: '立案信息' },
{ key: '诉前调解', label: '诉前调解' },
{ key: '开庭公告', label: '开庭公告' },
{ key: '法院公告', label: '法院公告' },
{ key: '送达公告', label: '送达公告' },
{ key: '裁判文书', label: '裁判文书' },
{ key: '被执行人', label: '被执行人' },
{ key: '失信被执行人', label: '失信被执行人' },
{ key: '终本案件', label: '终本案件' },
{ key: '限制高消费', label: '限制高消费' },
{ key: '股权冻结', label: '股权冻结' },
{ key: '司法案件', label: '司法案件' }
];
type TabApiConfig = {
page: (params: any) => Promise<{ list: Record<string, any>[] } | undefined>;
importFn: (file: File, companyId?: number) => Promise<string>;
templatePath: string;
};
const tabApiMap: Record<string, TabApiConfig> = {
招投标: {
page: pageCreditUser as any,
importFn: importCreditUsers as any,
templatePath: '/credit/credit-user/import/template'
},
对外投资: {
page: pageCreditExternal as any,
importFn: importCreditExternal as any,
templatePath: '/credit/credit-external/import/template'
},
风险关系: {
page: pageCreditRiskRelation as any,
importFn: importCreditRiskRelation as any,
templatePath: '/credit/credit-risk-relation/import/template'
},
竞争对手: {
page: pageCreditCompetitor as any,
importFn: importCreditCompetitor as any,
templatePath: '/credit/credit-competitor/import/template'
},
供应商: {
page: pageCreditSupplier as any,
importFn: importCreditSupplier as any,
templatePath: '/credit/credit-supplier/import/template'
},
客户: {
page: pageCreditCustomer as any,
importFn: importCreditCustomer as any,
templatePath: '/credit/credit-customer/import/template'
},
立案信息: {
page: pageCreditCaseFiling as any,
importFn: importCreditCaseFiling as any,
templatePath: '/credit/credit-case-filing/import/template'
},
诉前调解: {
page: pageCreditMediation as any,
importFn: importCreditMediation as any,
templatePath: '/credit/credit-mediation/import/template'
},
开庭公告: {
page: pageCreditCourtSession as any,
importFn: importCreditCourtSession as any,
templatePath: '/credit/credit-court-session/import/template'
},
法院公告: {
page: pageCreditCourtAnnouncement as any,
importFn: importCreditCourtAnnouncement as any,
templatePath: '/credit/credit-court-announcement/import/template'
},
送达公告: {
page: pageCreditDeliveryNotice as any,
importFn: importCreditDeliveryNotice as any,
templatePath: '/credit/credit-delivery-notice/import/template'
},
裁判文书: {
page: pageCreditJudicialDocument as any,
importFn: importCreditJudicialDocument as any,
templatePath: '/credit/credit-judicial-document/import/template'
},
被执行人: {
page: pageCreditJudgmentDebtor as any,
importFn: importCreditJudgmentDebtor as any,
templatePath: '/credit/credit-judgment-debtor/import/template'
},
失信被执行人: {
page: pageCreditBreachOfTrust as any,
importFn: importCreditBreachOfTrust as any,
templatePath: '/credit/credit-breach-of-trust/import/template'
},
终本案件: {
page: pageCreditFinalVersion as any,
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'
},
股权冻结: {
page: pageCreditGqdj as any,
importFn: importCreditGqdj as any,
templatePath: '/credit/credit-gqdj/import/template'
},
司法案件: {
page: pageCreditJudiciary as any,
importFn: importCreditJudiciaries as any,
templatePath: '/credit/credit-judiciary/import/template'
}
};
type TableColumn = {
title: string;
dataIndex: string;
key: string;
ellipsis?: boolean;
};
type TabColumnConfig = {
order?: string[];
hidden?: string[];
titleMap?: Record<string, string>;
};
const commonHiddenColumnKeys = new Set<string>([
'deleted',
'tenantId',
'userId',
'name1',
'sortNumber',
'recommend',
'url',
'status',
'comments',
'companyId',
'updateTime'
]);
const commonTitleMap: Record<string, string> = {
id: 'ID',
name: '被执行人名称',
name1: '被执行人',
code: '税号',
url: '链接地址',
caseNumber: '案号',
courtName: '法院',
occurrenceTime: '发生时间',
amount: '执行标的',
status: '状态',
dataStatus: '数据状态',
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>[];
columns: TableColumn[];
loadedIdentity?: string;
};
const tabState = reactive<Record<string, TabState>>({});
tabList.forEach((tab) => {
tabState[tab.key] = {
loading: false,
data: [],
columns: [],
loadedIdentity: undefined
};
});
const activeTab = ref(tabList[0].key);
// 子表导入弹窗
const showRelatedImport = ref(false);
const relatedImportTabKey = ref(tabList[0].key);
const relatedImportConfig = computed(
() => tabApiMap[relatedImportTabKey.value]
);
const relatedImportTitle = computed(() => {
const tab = tabList.find((t) => t.key === relatedImportTabKey.value);
return `${tab?.label ?? relatedImportTabKey.value}批量导入`;
});
const relatedImportTemplatePath = computed(
() => relatedImportConfig.value?.templatePath ?? ''
);
const relatedImportFn = (file: File, companyId?: number) => {
const fn = relatedImportConfig.value?.importFn;
if (!fn) {
return Promise.reject(new Error('未配置导入接口'));
}
return fn(file, companyId);
};
const openRelatedImport = (key: string) => {
if (!form.id) {
message.error('缺少企业ID无法导入');
return;
}
if (!tabApiMap[key]) {
message.error('未配置该Tab的导入功能');
return;
}
relatedImportTabKey.value = key;
showRelatedImport.value = true;
};
const handleRelatedImportDone = () => {
reloadTab(activeTab.value);
};
const defaultForm: CreditCompany = {
id: undefined,
name: undefined,
matchName: undefined,
code: undefined,
type: undefined,
parentId: undefined,
registrationStatus: undefined,
legalPerson: undefined,
registeredCapital: undefined,
paidinCapital: undefined,
establishDate: undefined,
address: undefined,
tel: undefined,
moreTel: undefined,
email: undefined,
moreEmail: undefined,
country: undefined,
province: undefined,
city: undefined,
region: undefined,
institutionType: undefined,
taxpayerCode: undefined,
registrationNumber: undefined,
organizationalCode: undefined,
numberOfInsuredPersons: undefined,
annualReport: undefined,
businessTerm: undefined,
nationalStandardIndustryCategories: undefined,
nationalStandardIndustryCategories2: undefined,
nationalStandardIndustryCategories3: undefined,
nationalStandardIndustryCategories4: undefined,
nationalStandardIndustryCategories5: undefined,
nationalStandardIndustryCategories6: undefined,
nationalStandardIndustryCategories7: undefined,
nationalStandardIndustryCategories8: undefined,
companySize: undefined,
formerName: undefined,
englishName: undefined,
domain: undefined,
mailingAddress: undefined,
companyProfile: undefined,
natureOfBusiness: undefined,
registrationAuthority: undefined,
taxpayerQualification: undefined,
latestAnnualReportYear: undefined,
latestAnnualReportOnOperatingRevenue: undefined,
enterpriseScoreCheck: undefined,
creditRating: undefined,
cechnologyScore: undefined,
cechnologyLevel: undefined,
smallEnterprise: undefined,
recommend: undefined,
deleted: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
status: 0,
comments: ''
};
// 用户信息
const form = reactive<CreditCompany>({ ...defaultForm });
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const formatValue = (value: unknown) => {
if (value === undefined || value === null || value === '') {
return '-';
}
return value;
};
// const formatStatus = (status?: number) => {
// if (status === 0) {
// return '显示';
// }
// if (status === 1) {
// return '隐藏';
// }
// return '-';
// };
const getRowKey = (record: Record<string, any>, index: number) => {
return record.id ?? record.code ?? record.key ?? index;
};
const buildColumns = (
tabKey: string,
rows: Record<string, any>[]
): TableColumn[] => {
if (!rows.length) {
return [];
}
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
}));
};
const resetForm = () => {
Object.assign(form, defaultForm);
};
const clearTabData = () => {
tabList.forEach((tab) => {
tabState[tab.key].data = [];
tabState[tab.key].columns = [];
tabState[tab.key].loading = false;
tabState[tab.key].loadedIdentity = undefined;
});
};
const loadTabData = async (key: string, force = false) => {
const taxpayerCode = form.code ?? props.data?.code;
const companyId = form.id ?? props.data?.id;
const identity = taxpayerCode
? `tax:${taxpayerCode}`
: companyId
? `id:${companyId}`
: undefined;
const state = tabState[key];
const api = tabApiMap[key]?.page;
if (!api) {
state.data = [];
state.columns = [];
state.loadedIdentity = undefined;
return;
}
if (!identity) {
state.data = [];
state.columns = [];
state.loadedIdentity = undefined;
return;
}
if (!force && state.loadedIdentity === identity) {
return;
}
state.loading = true;
try {
const res = await api({
taxpayerCode,
companyId,
page: 1,
limit: 500
});
state.data = res?.list || [];
state.columns = buildColumns(key, state.data);
state.loadedIdentity = identity;
} catch (e: any) {
state.data = [];
state.columns = [];
state.loadedIdentity = undefined;
message.error(e?.message ?? '查询失败');
} finally {
state.loading = false;
}
};
const reloadTab = (key: string) => {
loadTabData(key, true);
};
watch(
() => activeTab.value,
(key) => {
loadTabData(key);
}
);
watch(
() => props.visible,
(visible) => {
if (visible) {
showRelatedImport.value = false;
resetForm();
clearTabData();
if (props.data) {
assignObject(form, props.data);
}
activeTab.value = tabList[0].key;
loadTabData(activeTab.value, true);
} else {
showRelatedImport.value = false;
resetForm();
clearTabData();
}
},
{ immediate: true }
);
watch(
() => props.data,
(data) => {
if (!props.visible || !data) {
return;
}
showRelatedImport.value = false;
resetForm();
clearTabData();
assignObject(form, data);
loadTabData(activeTab.value, true);
}
);
</script>