forked from wangziqi/gongxue-base
feat: add ai recommendation exports
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { Button, Input, Picker, Text, Textarea, View } from '@tarojs/components';
|
||||
import {
|
||||
exportSchoolRecommendationReport,
|
||||
generateSchoolRecommendation,
|
||||
loadSchoolRecommendationReports,
|
||||
type SchoolRecommendationReport,
|
||||
@@ -22,6 +24,24 @@ function recommendationRows(report: SchoolRecommendationReport | null) {
|
||||
return report?.resultPayload?.recommendedSchools || [];
|
||||
}
|
||||
|
||||
function saveExportFile(fileName: string, content: string, mimeType: string) {
|
||||
if (process.env.TARO_ENV === 'h5' && typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
const blob = new Blob([content], { type: mimeType });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = fileName;
|
||||
link.rel = 'noopener noreferrer';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
return;
|
||||
}
|
||||
Taro.setClipboardData({ data: content });
|
||||
Taro.showToast({ title: '报告内容已复制', icon: 'none' });
|
||||
}
|
||||
|
||||
export default function StudentAiSchoolPage() {
|
||||
const [profile, setProfile] = useState<StudentProfile | null>(null);
|
||||
const [reports, setReports] = useState<SchoolRecommendationReport[]>([]);
|
||||
@@ -30,6 +50,7 @@ export default function StudentAiSchoolPage() {
|
||||
const [constraints, setConstraints] = useState('');
|
||||
const [riskIndex, setRiskIndex] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [exporting, setExporting] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
@@ -65,6 +86,22 @@ export default function StudentAiSchoolPage() {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleExport(format: 'markdown' | 'html') {
|
||||
if (!current?.id) return;
|
||||
setExporting(format);
|
||||
setError('');
|
||||
try {
|
||||
const payload = await exportSchoolRecommendationReport(current.id, format);
|
||||
if (!payload.item?.contentText) throw new Error('后端未返回报告内容');
|
||||
saveExportFile(payload.item.fileName, payload.item.contentText, payload.item.mimeType);
|
||||
if (process.env.TARO_ENV === 'h5') Taro.showToast({ title: '报告已导出', icon: 'success' });
|
||||
} catch (nextError) {
|
||||
setError(nextError instanceof Error ? nextError.message : '导出失败');
|
||||
} finally {
|
||||
setExporting('');
|
||||
}
|
||||
}
|
||||
|
||||
const rows = recommendationRows(current);
|
||||
|
||||
return (
|
||||
@@ -123,6 +160,10 @@ export default function StudentAiSchoolPage() {
|
||||
<Text className='hero-title'>{riskLabel(current.resultPayload.riskLevel)}方案</Text>
|
||||
<Text className='hero-copy'>{current.resultPayload.summary}</Text>
|
||||
</View>
|
||||
<View className='toolbar wrap compact-toolbar'>
|
||||
<Button className='secondary-button' loading={exporting === 'markdown'} onClick={() => handleExport('markdown')}>导出MD</Button>
|
||||
<Button className='secondary-button' loading={exporting === 'html'} onClick={() => handleExport('html')}>导出HTML</Button>
|
||||
</View>
|
||||
<View className='list-stack'>
|
||||
{rows.map(item => (
|
||||
<View className='list-row' key={`${item.schoolId || item.schoolName}:${item.majorId || item.majorName || ''}`}>
|
||||
|
||||
@@ -63,6 +63,17 @@ export interface SchoolRecommendationReport {
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SchoolRecommendationExport {
|
||||
reportId: string;
|
||||
format: 'markdown' | 'html';
|
||||
fileName: string;
|
||||
mimeType: string;
|
||||
contentBase64: string;
|
||||
contentText?: string;
|
||||
sha256: string;
|
||||
sizeBytes: number;
|
||||
}
|
||||
|
||||
export async function generateSchoolRecommendation(input: GenerateSchoolRecommendationInput) {
|
||||
return apiRequest<{ item?: SchoolRecommendationReport }>('/api/ai/school-recommendations/generate', {
|
||||
method: 'POST',
|
||||
@@ -81,3 +92,9 @@ export async function loadSchoolRecommendationReport(reportId: string) {
|
||||
query: { reportId },
|
||||
});
|
||||
}
|
||||
|
||||
export async function exportSchoolRecommendationReport(reportId: string, format: 'markdown' | 'html' = 'markdown') {
|
||||
return apiRequest<{ item?: SchoolRecommendationExport }>('/api/ai/school-recommendations/export', {
|
||||
query: { reportId, format },
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user