改用axios请求进行封装
This commit is contained in:
@@ -0,0 +1,358 @@
|
||||
import axios, { AxiosRequestConfig, AxiosResponse, isAxiosError } from 'axios';
|
||||
import { mockData, type MockApiResponse } from './mock';
|
||||
|
||||
/**
|
||||
* API响应类型
|
||||
*/
|
||||
export type ApiResponse<T> = {
|
||||
data?: T;
|
||||
error?: string;
|
||||
status: number;
|
||||
headers?: Record<string, string>;
|
||||
};
|
||||
|
||||
export type QueryParams = Record<string, string | number | boolean | undefined>;
|
||||
|
||||
// 获取 API 基础 URL
|
||||
// const API_BASE_URL = 'http://172.18.0.100:3000';
|
||||
const API_BASE_URL = 'http://nas.7bm.co:3000';
|
||||
// const API_BASE_URL = 'http://172.16.0.119:9000/admin';
|
||||
// export const API_BASE_URL = 'http://nas.7bm.co:3000';
|
||||
|
||||
// 文档URL前缀
|
||||
export const DOCUMENT_URL = 'http://172.18.0.100:9000/docauditai/';
|
||||
|
||||
// 是否使用模拟数据(开发环境使用)
|
||||
const USE_MOCK_DATA = false; // 设置为true使用模拟数据,避免API连接问题
|
||||
|
||||
// 创建 axios 实例
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: 10000, // 10秒超时
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 将编码后的URL解码为可读格式
|
||||
* @param url 编码后的URL
|
||||
* @returns 解码后的可读URL
|
||||
*/
|
||||
function decodeUrlForDisplay(url: string): string {
|
||||
try {
|
||||
// 首先解码整个URL
|
||||
const decodedUrl = decodeURIComponent(url);
|
||||
|
||||
// 如果URL中包含@符号作为前缀,则移除它
|
||||
if (decodedUrl.startsWith('@')) {
|
||||
return decodedUrl.substring(1);
|
||||
}
|
||||
|
||||
return decodedUrl;
|
||||
} catch (error) {
|
||||
// 如果解码失败,返回原始URL
|
||||
console.error('URL解码失败:', error);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建完整的 API URL
|
||||
*/
|
||||
function buildUrl(endpoint: string, params?: QueryParams): string {
|
||||
let fullUrl;
|
||||
|
||||
// 检查endpoint是否已经是完整URL
|
||||
if (endpoint.startsWith('http')) {
|
||||
fullUrl = endpoint;
|
||||
} else {
|
||||
// 确保API_BASE_URL格式正确
|
||||
const baseUrl = API_BASE_URL.endsWith('/') ? API_BASE_URL.slice(0, -1) : API_BASE_URL;
|
||||
const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
fullUrl = `${baseUrl}${path}`;
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建URL对象
|
||||
const url = new URL(fullUrl);
|
||||
|
||||
// 添加查询参数
|
||||
if (params) {
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
if (value !== undefined) {
|
||||
url.searchParams.append(key, String(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
} catch (error) {
|
||||
console.error('URL构建错误:', fullUrl, error);
|
||||
throw new Error(`无法构建URL: ${fullUrl}, 错误: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模拟响应数据
|
||||
*/
|
||||
function getMockResponse<T>(endpoint: string): ApiResponse<T> {
|
||||
console.log(`[开发模式] 使用模拟数据: ${endpoint}`);
|
||||
|
||||
// 移除开头的斜杠以便于匹配
|
||||
const path = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
|
||||
|
||||
// 查找匹配的模拟数据
|
||||
for (const mockPath in mockData) {
|
||||
const normalizedMockPath = mockPath.startsWith('/') ? mockPath.substring(1) : mockPath;
|
||||
if (path === normalizedMockPath || path.startsWith(normalizedMockPath + '/')) {
|
||||
// 如果是详情查询 (如 /evaluation_points/1)
|
||||
if (path.includes('/') && path !== normalizedMockPath) {
|
||||
const id = parseInt(path.split('/')[1]);
|
||||
const mockDataItem = mockData[mockPath as keyof typeof mockData] as MockApiResponse<unknown>;
|
||||
|
||||
if (Array.isArray(mockDataItem.data)) {
|
||||
const item = mockDataItem.data.find((item: {id: number}) => item.id === id);
|
||||
|
||||
if (item) {
|
||||
return {
|
||||
data: {
|
||||
code: 0,
|
||||
msg: "成功",
|
||||
data: item
|
||||
} as unknown as T,
|
||||
status: 200
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { error: '未找到数据', status: 404 };
|
||||
}
|
||||
|
||||
// 返回列表数据
|
||||
return {
|
||||
data: mockData[mockPath as keyof typeof mockData] as unknown as T,
|
||||
status: 200
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { error: '没有匹配的模拟数据', status: 404 };
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩展AxiosRequestConfig类型,以支持body参数
|
||||
*/
|
||||
interface ExtendedAxiosRequestConfig extends AxiosRequestConfig {
|
||||
body?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用 API 请求函数
|
||||
*/
|
||||
export async function apiRequest<T>(
|
||||
endpoint: string,
|
||||
options: ExtendedAxiosRequestConfig = {},
|
||||
params?: QueryParams
|
||||
): Promise<ApiResponse<T>> {
|
||||
// 如果使用模拟数据,直接返回模拟响应
|
||||
if (USE_MOCK_DATA) {
|
||||
return getMockResponse<T>(endpoint);
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建 URL
|
||||
const url = buildUrl(endpoint, params);
|
||||
|
||||
// 设置默认请求头
|
||||
const headers = options.headers || {};
|
||||
if (!headers['Content-Type'] && options.method !== 'GET') {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
if (!headers['Accept']) {
|
||||
headers['Accept'] = 'application/json';
|
||||
}
|
||||
|
||||
// 针对 PostgREST 的额外处理
|
||||
if (endpoint.includes('evaluation_point_groups') && (options.method === 'POST' || options.method === 'PATCH')) {
|
||||
console.log('使用 PostgREST 特定配置处理请求');
|
||||
// 确保请求体是有效的 JSON 对象
|
||||
if (options.body && typeof options.body === 'string') {
|
||||
try {
|
||||
JSON.parse(options.body); // 验证 JSON 是否有效
|
||||
} catch (e) {
|
||||
console.error('请求体不是有效的 JSON:', options.body);
|
||||
throw new Error('请求体必须是有效的 JSON');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`📦 axios-client.ts->请求URL: ${decodeUrlForDisplay(url)}`);
|
||||
console.log(`axios-client.ts->发送 ${options.method || 'GET'} 请求到: ${decodeUrlForDisplay(url)}`);
|
||||
|
||||
// 处理body参数,转换为data
|
||||
if (options.body) {
|
||||
console.log(`axios-client.ts->请求体: \n${options.body}`);
|
||||
options.data = options.body;
|
||||
} else if (options.data) {
|
||||
console.log(`axios-client.ts->请求体: \n${typeof options.data === 'string' ? options.data : JSON.stringify(options.data)}`);
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
const config: AxiosRequestConfig = {
|
||||
...options,
|
||||
url,
|
||||
params,
|
||||
headers
|
||||
};
|
||||
|
||||
// 删除body属性,避免axios警告
|
||||
if ('body' in config) {
|
||||
delete (config as ExtendedAxiosRequestConfig).body;
|
||||
}
|
||||
|
||||
const response: AxiosResponse = await axiosInstance(config);
|
||||
|
||||
// 收集响应头信息
|
||||
const responseHeaders: Record<string, string> = {};
|
||||
Object.entries(response.headers).forEach(([key, value]) => {
|
||||
if (typeof value === 'string') {
|
||||
responseHeaders[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
// 打印响应信息
|
||||
// console.log(`响应状态: ${response.status}`);
|
||||
// console.log(`响应头:`, responseHeaders);
|
||||
// console.log(`响应体:`, response.data);
|
||||
|
||||
// 检查 PostgREST 特定错误
|
||||
if (response.status >= 400) {
|
||||
if (response.status === 400) {
|
||||
console.error('PostgREST 错误 - 无效请求:', response.data);
|
||||
return {
|
||||
error: response.data?.message || response.data?.msg || '无效的请求格式,请检查数据格式是否正确',
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
} else if (response.status === 401) {
|
||||
console.error('PostgREST 错误 - 未授权:', response.data);
|
||||
return {
|
||||
error: response.data?.message || response.data?.msg || '未授权,请检查认证信息',
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
} else if (response.status === 403) {
|
||||
console.error('PostgREST 错误 - 禁止访问:', response.data);
|
||||
return {
|
||||
error: response.data?.message || response.data?.msg || '没有权限执行此操作',
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
} else if (response.status === 404) {
|
||||
console.error('PostgREST 错误 - 资源不存在:', response.data);
|
||||
return {
|
||||
error: response.data?.message || response.data?.msg || '请求的资源不存在',
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
} else {
|
||||
console.error(`HTTP请求失败: ${response.status} - ${url}`, response.data);
|
||||
return {
|
||||
error: response.data?.message || response.data?.msg || `请求失败: ${response.status}`,
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 检查API返回的状态码
|
||||
const data = response.data;
|
||||
if (data && 'code' in data && data.code !== 0) {
|
||||
console.error(`API请求失败: ${data.message || data.msg || '未知错误'} - ${url}`);
|
||||
return {
|
||||
error: data.message || data.msg || '请求失败',
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
status: response.status,
|
||||
headers: responseHeaders
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
console.error('API请求失败:', error);
|
||||
|
||||
if (isAxiosError(error)) {
|
||||
const status = error.response?.status || 500;
|
||||
const errorData = error.response?.data;
|
||||
|
||||
// 如果超时或网络错误,使用模拟数据(仅开发环境)
|
||||
if (error.code === 'ECONNABORTED' && process.env.NODE_ENV !== 'production') {
|
||||
console.warn('自动使用模拟数据作为回退');
|
||||
return getMockResponse<T>(endpoint);
|
||||
}
|
||||
|
||||
return {
|
||||
error: errorData?.message || errorData?.msg || error.message || '未知错误',
|
||||
status
|
||||
};
|
||||
}
|
||||
|
||||
// 如果超时或网络错误,使用模拟数据(仅开发环境)
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.warn('自动使用模拟数据作为回退');
|
||||
return getMockResponse<T>(endpoint);
|
||||
}
|
||||
|
||||
return {
|
||||
error: error instanceof Error ? error.message : '未知错误',
|
||||
status: 500
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// GET请求简化方法
|
||||
export async function get<T>(endpoint: string, params?: QueryParams): Promise<ApiResponse<T>> {
|
||||
return apiRequest<T>(endpoint, { method: 'GET' }, params);
|
||||
}
|
||||
|
||||
// POST请求简化方法
|
||||
export async function post<T>(endpoint: string, data?: unknown, params?: QueryParams): Promise<ApiResponse<T>> {
|
||||
return apiRequest<T>(endpoint, { method: 'POST', data }, params);
|
||||
}
|
||||
|
||||
// PUT请求简化方法
|
||||
export async function put<T>(endpoint: string, data?: unknown, params?: QueryParams): Promise<ApiResponse<T>> {
|
||||
return apiRequest<T>(endpoint, { method: 'PUT', data }, params);
|
||||
}
|
||||
|
||||
// PATCH请求简化方法
|
||||
export async function patch<T>(endpoint: string, data?: unknown, params?: QueryParams): Promise<ApiResponse<T>> {
|
||||
return apiRequest<T>(endpoint, { method: 'PATCH', data }, params);
|
||||
}
|
||||
|
||||
// DELETE请求简化方法
|
||||
export async function del<T>(endpoint: string, params?: QueryParams): Promise<ApiResponse<T>> {
|
||||
return apiRequest<T>(endpoint, { method: 'DELETE' }, params);
|
||||
}
|
||||
|
||||
// 下载文件的方法
|
||||
export async function downloadFile(path: string): Promise<Blob> {
|
||||
const downloadUrl = `${DOCUMENT_URL}${path}`;
|
||||
|
||||
try {
|
||||
console.log(`📦 axios-client.ts->下载文件: ${decodeUrlForDisplay(downloadUrl)}`);
|
||||
const response = await axios.get(downloadUrl, {
|
||||
responseType: 'blob'
|
||||
});
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('下载文件失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ export async function getHomeData(): Promise<HomeStatistics> {
|
||||
select: 'count',
|
||||
filter: {
|
||||
and: `(audit_status.neq.0,audit_status.neq.2)`,
|
||||
created_at: `gte.${startOfThisMonth}`,
|
||||
updated_at: `gte.${startOfThisMonth}`,
|
||||
is_test_document: `eq.false`
|
||||
}
|
||||
};
|
||||
@@ -156,7 +156,7 @@ export async function getHomeData(): Promise<HomeStatistics> {
|
||||
select: 'count',
|
||||
filter: {
|
||||
or: `(audit_status.eq.1,audit_status.eq.-1)`,
|
||||
and: `(created_at.gte.${startOfLastMonth},created_at.lte.${endOfLastMonth})`,
|
||||
and: `(updated_at.gte.${startOfLastMonth},updated_at.lte.${endOfLastMonth})`,
|
||||
is_test_document: `eq.false`
|
||||
}
|
||||
};
|
||||
@@ -171,7 +171,8 @@ export async function getHomeData(): Promise<HomeStatistics> {
|
||||
// 计算同比增长
|
||||
let reviewGrowthValue = 0;
|
||||
let reviewGrowthIsUp = true;
|
||||
|
||||
// console.log('lastMonthReviewed-------', lastMonthReviewed);
|
||||
// console.log('monthlyReviewedFiles-------', monthlyReviewedFiles);
|
||||
if (lastMonthReviewed > 0) {
|
||||
const growthRate = ((monthlyReviewedFiles - lastMonthReviewed) / lastMonthReviewed) * 100;
|
||||
reviewGrowthValue = Math.abs(parseFloat(growthRate.toFixed(1)));
|
||||
@@ -205,7 +206,7 @@ export async function getHomeData(): Promise<HomeStatistics> {
|
||||
select: 'count',
|
||||
filter: {
|
||||
audit_status: `eq.1`,
|
||||
and: `(created_at.gte.${startOfLastMonth},created_at.lte.${endOfLastMonth})`,
|
||||
and: `(updated_at.gte.${startOfLastMonth},updated_at.lte.${endOfLastMonth})`,
|
||||
is_test_document: `eq.false`
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// app/api/postgrest-client.ts
|
||||
import { apiRequest, type QueryParams } from './client';
|
||||
import { apiRequest, type QueryParams } from './axios-client';
|
||||
import { handleApiError } from './error-handler';
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,9 +80,9 @@ export function FileInfo({ fileInfo, onConfirmResults }: FileInfoProps) {
|
||||
navigate(returnTo);
|
||||
};
|
||||
|
||||
const handleExportReport = () => {
|
||||
alert('导出评查报告功能');
|
||||
};
|
||||
// const handleExportReport = () => {
|
||||
// alert('导出评查报告功能');
|
||||
// };
|
||||
|
||||
return (
|
||||
<div className="mb-4 file-info-header">
|
||||
|
||||
@@ -71,7 +71,8 @@ interface FilePreviewProps {
|
||||
targetPage?: number; // 新增目标页码参数
|
||||
}
|
||||
|
||||
export function FilePreview({ fileContent, reviewPoints, activeReviewPointResultId, targetPage }: FilePreviewProps) {
|
||||
// export function FilePreview({ fileContent, reviewPoints, activeReviewPointResultId, targetPage }: FilePreviewProps) {
|
||||
export function FilePreview({ fileContent, activeReviewPointResultId, targetPage }: FilePreviewProps) {
|
||||
const [zoomLevel, setZoomLevel] = useState(100);
|
||||
// const [highlightsVisible, setHighlightsVisible] = useState(true);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -86,7 +86,7 @@ export function ReviewPointsList({
|
||||
const [searchText, setSearchText] = useState(''); // 搜索文本
|
||||
const [statusFilter, setStatusFilter] = useState<string | null>(null); // 状态过滤
|
||||
|
||||
const [suggestionTexts, setSuggestionTexts] = useState<Record<string, string>>({}); // 存储每个评查点的建议文本
|
||||
// const [suggestionTexts, setSuggestionTexts] = useState<Record<string, string>>({}); // 存储每个评查点的建议文本
|
||||
|
||||
// 添加重新审核意见的状态/ 用户输入的修改内容 / 用户提前写好的修改内容
|
||||
const [manualReviewNotes, setManualReviewNotes] = useState<Record<string, string>>({});
|
||||
@@ -99,7 +99,7 @@ export function ReviewPointsList({
|
||||
reviewPoints.forEach(point => {
|
||||
suggestions[point.id] = point.suggestion || '';
|
||||
});
|
||||
setSuggestionTexts(suggestions);
|
||||
// setSuggestionTexts(suggestions);
|
||||
|
||||
// 使用函数式更新,不再需要外部 manualReviewNotes 变量
|
||||
setManualReviewNotes(prev => {
|
||||
@@ -112,12 +112,12 @@ export function ReviewPointsList({
|
||||
}, [reviewPoints]);
|
||||
|
||||
// 处理建议文本变更
|
||||
const handleSuggestionChange = (reviewPointId: string, text: string) => {
|
||||
setSuggestionTexts(prev => ({
|
||||
...prev,
|
||||
[reviewPointId]: text
|
||||
}));
|
||||
};
|
||||
// const handleSuggestionChange = (reviewPointId: string, text: string) => {
|
||||
// setSuggestionTexts(prev => ({
|
||||
// ...prev,
|
||||
// [reviewPointId]: text
|
||||
// }));
|
||||
// };
|
||||
|
||||
/**
|
||||
* 处理评查点审核操作
|
||||
|
||||
@@ -22,14 +22,14 @@ export function ReviewTabs({ activeTab, onTabChange, children }: ReviewTabsProps
|
||||
>
|
||||
<i className="ri-file-text-line"></i> 评查结果
|
||||
</button>
|
||||
<button
|
||||
{/* <button
|
||||
className={`tab-nav-item ${activeTab === 'analysis' ? 'active' : ''}`}
|
||||
onClick={() => onTabChange('analysis')}
|
||||
type="button"
|
||||
aria-pressed={activeTab === 'analysis'}
|
||||
>
|
||||
<i className="ri-lightbulb-line"></i> AI智能分析
|
||||
</button>
|
||||
</button> */}
|
||||
<button
|
||||
className={`tab-nav-item ${activeTab === 'fileinfo' ? 'active' : ''}`}
|
||||
onClick={() => onTabChange('fileinfo')}
|
||||
|
||||
@@ -34,12 +34,12 @@ export const meta: MetaFunction = () => {
|
||||
};
|
||||
|
||||
// API 响应的类型定义
|
||||
interface StatsData {
|
||||
totalFiles: number;
|
||||
reviewedFiles: number;
|
||||
pendingFiles: number;
|
||||
passRate: number;
|
||||
}
|
||||
// interface StatsData {
|
||||
// totalFiles: number;
|
||||
// reviewedFiles: number;
|
||||
// pendingFiles: number;
|
||||
// passRate: number;
|
||||
// }
|
||||
|
||||
// 模拟数据,实际项目中应该从API获取
|
||||
export async function loader() {
|
||||
|
||||
+39
-5
@@ -629,7 +629,17 @@ function getMockReviewData(): ReviewData {
|
||||
groupName: "付款条款清晰性",
|
||||
// location: "交货与付款条款",
|
||||
status: "error",
|
||||
content: "乙方应在收到货物之日起5个工作日内支付合同款项,甲方应在收到乙方全部付款后开具增值税专用发票,乙方应在收到发票后支付剩余款项。",
|
||||
editAuditStatus: 0,
|
||||
content: {
|
||||
'anjia':{
|
||||
page: 1,
|
||||
value: { text: "乙方应在收到货物之日起5个工作日内支付合同款项,甲方应在收到乙方全部付款后开具增值税专用发票,乙方应在收到发票后支付剩余款项。" }
|
||||
},
|
||||
'yijia':{
|
||||
page: 1,
|
||||
value: { text: "乙方应在收到货物之日起5个工作日内支付合同款项,甲方应在收到乙方全部付款后开具增值税专用发票,乙方应在收到发票后支付剩余款项。" }
|
||||
}
|
||||
},
|
||||
suggestion: "乙方应在收到货物验收合格之日起5个工作日内支付合同总额的70%,甲方收到该部分款项后3个工作日内向乙方开具等额增值税专用发票;乙方应在收到发票之日起5个工作日内支付剩余30%款项。",
|
||||
position: { section: "交货与付款", index: 2 },
|
||||
result: false
|
||||
@@ -640,7 +650,13 @@ function getMockReviewData(): ReviewData {
|
||||
title: "违约责任条款缺失",
|
||||
groupName: "合同权利义务对等性",
|
||||
status: "warning",
|
||||
content: "如合同发生纠纷,双方应协商解决。",
|
||||
editAuditStatus: 0,
|
||||
content: {
|
||||
'clause': {
|
||||
page: 1,
|
||||
value: { text: "如合同发生纠纷,双方应协商解决。" }
|
||||
}
|
||||
},
|
||||
suggestion: "如合同发生纠纷,双方应友好协商解决;协商不成的,任何一方均有权向甲方所在地人民法院提起诉讼。任何一方未能履行本合同约定义务,应向守约方支付合同总金额的10%作为违约金;给对方造成损失的,还应赔偿由此产生的全部损失。",
|
||||
position: { section: "争议解决", index: 0 },
|
||||
result: false
|
||||
@@ -651,7 +667,13 @@ function getMockReviewData(): ReviewData {
|
||||
title: "签章不完整",
|
||||
groupName: "合同签署规范性",
|
||||
status: "warning",
|
||||
content: "乙方(盖章):YY贸易有限公司\n代表人签字:李YY\n日期:2023年10月20日",
|
||||
editAuditStatus: 0,
|
||||
content: {
|
||||
'signature': {
|
||||
page: 5,
|
||||
value: { text: "乙方(盖章):YY贸易有限公司\n代表人签字:李YY\n日期:2023年10月20日" }
|
||||
}
|
||||
},
|
||||
suggestion: "需要联系甲方补充公章",
|
||||
needsHumanReview: true,
|
||||
humanReviewNote: "需要联系甲方补充公章",
|
||||
@@ -664,7 +686,13 @@ function getMockReviewData(): ReviewData {
|
||||
title: "交货方式描述模糊",
|
||||
groupName: "履行条款明确性",
|
||||
status: "success",
|
||||
content: "3.4 运输方式:陆运,运费由甲方承担。",
|
||||
editAuditStatus: 0,
|
||||
content: {
|
||||
'delivery': {
|
||||
page: 3,
|
||||
value: { text: "3.4 运输方式:陆运,运费由甲方承担。" }
|
||||
}
|
||||
},
|
||||
suggestion: "建议补充具体的运输方式和时间",
|
||||
needsHumanReview: true,
|
||||
humanReviewNote: "经核实,该交货方式虽然描述不够详细,但符合行业惯例且双方已经多次合作,不会造成实际履行障碍。",
|
||||
@@ -679,7 +707,13 @@ function getMockReviewData(): ReviewData {
|
||||
title: "法律适用条款缺失",
|
||||
groupName: "争议解决条款完整性",
|
||||
status: "error",
|
||||
content: "",
|
||||
editAuditStatus: 0,
|
||||
content: {
|
||||
'missing': {
|
||||
page: 0,
|
||||
value: { text: "" }
|
||||
}
|
||||
},
|
||||
suggestion: "第十三条 法律适用\n本合同的订立、效力、解释、履行及争议的解决均适用中华人民共和国法律。因本合同引起的或与本合同有关的任何争议,双方应友好协商解决。协商不成的,提交甲方所在地人民法院诉讼解决。",
|
||||
position: { section: "缺失", index: 0 },
|
||||
result: false
|
||||
|
||||
@@ -17,7 +17,8 @@ import {
|
||||
} from "~/api/evaluation_points/rules-files";
|
||||
import { getDocumentTypes } from "~/api/document-types/document-types";
|
||||
import { toastService } from "~/components/ui/Toast";
|
||||
import { DOCUMENT_URL } from "~/api/client";
|
||||
// 导入axios下载文件方法
|
||||
import { downloadFile } from "~/api/axios-client";
|
||||
|
||||
export const links = () => [
|
||||
{ rel: "stylesheet", href: rulesFilesStyles }
|
||||
@@ -241,16 +242,8 @@ export default function RulesFiles() {
|
||||
// 下载文件
|
||||
const handleDownload = async (path: string) => {
|
||||
try {
|
||||
const downloadUrl = `${DOCUMENT_URL}${path}`;
|
||||
|
||||
// 使用fetch获取文件内容
|
||||
const response = await fetch(downloadUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`下载失败: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
// 将响应转换为Blob
|
||||
const blob = await response.blob();
|
||||
// 使用axios封装的下载方法
|
||||
const blob = await downloadFile(path);
|
||||
|
||||
// 创建Blob URL
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
|
||||
Reference in New Issue
Block a user