feat: 1. 添加企查查的按钮。新增相关组件和对接接口进行显示。

2. 为51707端口添加只存在交叉评查入口的项目启动配置。入口页添加相关的区分。
3. 完善文档列表的权限功能控制。
4. 隐藏系统概览中高风险用户的统计模块。
fix: 1. 修复合同起草无权访问却生成了新的模板文件的问题。
2. 修复文档类型无法编辑入口模块的问题。
This commit is contained in:
2025-12-13 02:59:34 +08:00
parent 5c47b20e1d
commit daa53289af
23 changed files with 3370 additions and 183 deletions
+138 -2
View File
@@ -21,6 +21,9 @@ import { useState, useEffect, useRef } from 'react';
import { toastService } from '../ui/Toast';
import { createPortal } from 'react-dom'; // 导入React Portal API,用于将组件渲染到DOM树的不同位置
import { Tooltip } from '../ui/Tooltip';
import { CorporateInfoModal } from '../corporate-information';
import type { BusinessInfoResult, DishonestyResult } from '../corporate-information';
import { queryCompanyInfo } from '~/api/corporate-information/qichacha';
// import '../../styles/components/TooltipStyles.css';
/**
@@ -423,6 +426,15 @@ export function ReviewPointsList({
// 存放评查点ID与有效页码的映射
const [effectivePages, setEffectivePages] = useState<Record<string, number>>({});
// 企业信息模态框状态
const [corporateModalVisible, setCorporateModalVisible] = useState(false);
const [corporateCompanyName, setCorporateCompanyName] = useState('');
const [corporateBusinessInfo, setCorporateBusinessInfo] = useState<BusinessInfoResult | null>(null);
const [corporateDishonestyInfo, setCorporateDishonestyInfo] = useState<DishonestyResult | null>(null);
const [corporateLoading, setCorporateLoading] = useState(false);
const [corporateError, setCorporateError] = useState<string | null>(null);
const [corporateUpdatedAt, setCorporateUpdatedAt] = useState<string | null>(null);
// 初始化建议文本
useEffect(() => {
// 使用函数式更新,不再需要外部 manualReviewNotes 变量
@@ -483,6 +495,71 @@ export function ReviewPointsList({
setEditingReviewPoint(null);
};
/**
* 处理企业信息按钮点击
* @param companyName 企业名称(乙方名称)
* @param forceRefresh 是否强制刷新(对接企查查重新查询)
*/
const handleCorporateInfoClick = async (companyName: string, forceRefresh = false) => {
if (!companyName) {
toastService.warning('企业名称为空,无法查询');
return;
}
// 打开模态框并设置加载状态
setCorporateModalVisible(true);
setCorporateCompanyName(companyName);
setCorporateLoading(true);
setCorporateError(null);
setCorporateBusinessInfo(null);
setCorporateDishonestyInfo(null);
setCorporateUpdatedAt(null);
try {
const response = await queryCompanyInfo({ keyword: companyName, force_refresh: forceRefresh });
if (response.success && response.data) {
setCorporateBusinessInfo(response.data.enterprise);
setCorporateUpdatedAt(response.data.updated_at);
// 转换失信数据格式
if (response.data.dishonesty) {
setCorporateDishonestyInfo({
VerifyResult: response.data.dishonesty.VerifyResult,
Data: response.data.dishonesty.Data || [],
});
}
} else {
setCorporateError(response.message || '查询失败');
}
} catch (error) {
console.error('查询企业信息失败:', error);
setCorporateError(error instanceof Error ? error.message : '查询失败');
} finally {
setCorporateLoading(false);
}
};
/**
* 处理强制刷新(对接企查查重新查询)
*/
const handleCorporateForceRefresh = async () => {
if (corporateCompanyName) {
await handleCorporateInfoClick(corporateCompanyName, true);
}
};
/**
* 关闭企业信息模态框
*/
const handleCloseCorporateModal = () => {
setCorporateModalVisible(false);
setCorporateCompanyName('');
setCorporateBusinessInfo(null);
setCorporateDishonestyInfo(null);
setCorporateError(null);
setCorporateUpdatedAt(null);
};
/**
* 过滤评查点
* 根据搜索文本和状态过滤条件筛选评查点
@@ -2406,7 +2483,7 @@ export function ReviewPointsList({
tabIndex={0}
style={{ userSelect: 'text' }}
onClick={() => {
// console.log('reviewPoint', reviewPoint);
console.log('reviewPoint', reviewPoint);
handleReviewPointClick(reviewPoint.id);
}}
onKeyDown={(e) => {
@@ -2419,7 +2496,51 @@ export function ReviewPointsList({
{/* 评查点名称 pointName*/}
<div className="flex justify-between items-center mb-2">
{/* <div className='flex flex-col'> */}
<div className="review-point-title text-left text-blue-500 max-w-[75%] break-all">{reviewPoint.pointName}</div>
<div className="flex items-center gap-2 max-w-[75%]">
<div className="review-point-title text-left text-blue-500 break-all">{reviewPoint.pointName}</div>
{ reviewPoint.pointName === '签署乙方详细信息校验' && (
<button
className="enterprise-info-btn"
style={{
padding: '2px 8px',
fontSize: '12px',
borderRadius: '4px',
display: 'flex',
alignItems: 'center',
gap: '4px',
flexShrink: 0,
transition: 'all 0.2s',
border: 'none',
cursor: reviewPoint.content?.['合同主体信息-乙方-名称']?.value ? 'pointer' : 'not-allowed',
backgroundColor: reviewPoint.content?.['合同主体信息-乙方-名称']?.value ? '#00684a' : '#e5e7eb',
color: reviewPoint.content?.['合同主体信息-乙方-名称']?.value ? '#ffffff' : '#9ca3af',
}}
disabled={!reviewPoint.content?.['合同主体信息-乙方-名称']?.value}
onClick={(e) => {
e.stopPropagation();
const companyNameValue = reviewPoint.content?.['合同主体信息-乙方-名称']?.value;
const companyName = typeof companyNameValue === 'string' ? companyNameValue : String(companyNameValue || '');
if (companyName) {
handleCorporateInfoClick(companyName);
}
}}
onMouseEnter={(e) => {
if (reviewPoint.content?.['合同主体信息-乙方-名称']?.value) {
e.currentTarget.style.backgroundColor = '#005a3f';
}
}}
onMouseLeave={(e) => {
if (reviewPoint.content?.['合同主体信息-乙方-名称']?.value) {
e.currentTarget.style.backgroundColor = '#00684a';
}
}}
>
<i className="ri-eye-line"></i>
</button>
)}
</div>
{/* <div className="review-point-header flex justify-between items-start">
<div className="flex-1 text-left min-w-[25%] font-medium text-[13px]">{reviewPoint.title}</div>
//评查点分组显示
@@ -2450,6 +2571,21 @@ export function ReviewPointsList({
renderEmptyState()
)}
</div>
{/* 企业信息模态框 */}
<CorporateInfoModal
visible={corporateModalVisible}
onClose={handleCloseCorporateModal}
companyName={corporateCompanyName}
businessInfo={corporateBusinessInfo}
dishonestyInfo={corporateDishonestyInfo}
businessLoading={corporateLoading}
dishonestyLoading={corporateLoading}
businessError={corporateError}
dishonestyError={corporateError}
updatedAt={corporateUpdatedAt}
onForceRefresh={handleCorporateForceRefresh}
/>
</div>
);
}