File size: 6,885 Bytes
25fe4a1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | # Save Profile and Download Image Implementation Guide
## Overview
This implementation adds two new features to the results page:
1. **Save Profile Button** - Allows users to save their Bazi profile information for quick access later
2. **Download Image Button** - Enables users to download the analysis results as a PNG image using html2canvas
## Components Created
### 1. SaveProfileDialog.tsx (`/home/lifekline/components/SaveProfileDialog.tsx`)
A modal dialog component that prompts users to enter a profile name and displays the Bazi information before saving.
**Features:**
- Input field for profile name validation
- Display of four pillars (年柱, 月柱, 日柱, 时柱)
- Shows birth year
- Save/Cancel actions with loading states
- Error handling
**Props:**
```typescript
interface SaveProfileDialogProps {
onClose: () => void;
onSave: (profileName: string) => Promise<void>;
baziInfo: {
yearPillar: string;
monthPillar: string;
dayPillar: string;
hourPillar: string;
birthYear: string;
};
isOpen: boolean;
}
```
### 2. ResultActions.tsx (`/home/lifekline/components/ResultActions.tsx`)
A component that provides action buttons for the results page.
**Features:**
- **保存档案 (Save Profile)** - Opens SaveProfileDialog
- **下载图片 (Download Image)** - Uses html2canvas to capture and download results
- **分享 (Share)** - Triggers the share functionality
- Error handling for download failures
- Loading states during image generation
**Props:**
```typescript
interface ResultActionsProps {
baziInfo: {
yearPillar: string;
monthPillar: string;
dayPillar: string;
hourPillar: string;
birthYear: string;
};
userName?: string;
onSaveProfile?: (profileName: string) => Promise<void>;
onShare?: () => void;
resultElementId?: string;
}
```
## Integration with ProgressiveAnalysisResult.tsx
The `ResultActions` component has been integrated into `ProgressiveAnalysisResult.tsx`:
### Changes Made:
1. **Import Added:**
```typescript
import ResultActions from './ResultActions';
```
2. **Props Extended:**
```typescript
interface ProgressiveAnalysisResultProps {
// ... existing props
userName?: string;
onSaveProfile?: (profileName: string) => Promise<void>;
onShare?: () => void;
}
```
3. **Component Placement:**
The ResultActions component is placed after the Agent Status section and before the Bazi Pillars display. It only appears when the analysis is complete and Bazi data is available.
4. **Result Section Wrapper:**
Added a wrapper div with `id="result-chart-section"` around the entire results area to enable html2canvas to capture the content.
## Usage Example
Here's how to use the updated ProgressiveAnalysisResult component:
```typescript
import ProgressiveAnalysisResult from './components/ProgressiveAnalysisResult';
function MyAnalysisPage() {
// Save profile handler - integrates with existing profile management
const handleSaveProfile = async (profileName: string) => {
try {
// Get current user input from state
const profileData = {
name: profileName,
birthYear: currentInput.birthYear,
yearPillar: currentInput.yearPillar,
monthPillar: currentInput.monthPillar,
dayPillar: currentInput.dayPillar,
hourPillar: currentInput.hourPillar,
startAge: currentInput.startAge,
firstDaYun: currentInput.firstDaYun,
birthPlace: currentInput.birthPlace,
gender: currentInput.gender,
// ... other required fields
};
// Save to localStorage or API
const profiles = JSON.parse(localStorage.getItem('lifekline_profiles') || '[]');
const newProfile = {
...profileData,
id: Date.now().toString(),
isDefault: profiles.length === 0,
createdAt: new Date().toISOString(),
};
profiles.push(newProfile);
localStorage.setItem('lifekline_profiles', JSON.stringify(profiles));
// Show success message
alert('Profile saved successfully!');
} catch (error) {
console.error('Failed to save profile:', error);
throw new Error('Failed to save profile. Please try again.');
}
};
// Share handler
const handleShare = () => {
// Open share panel or trigger share functionality
setShowSharePanel(true);
};
return (
<ProgressiveAnalysisResult
requestData={requestData}
userName={userName}
onSaveProfile={handleSaveProfile}
onShare={handleShare}
onComplete={(result) => console.log('Analysis complete:', result)}
onError={(error) => console.error('Analysis error:', error)}
/>
);
}
```
## Download Image Functionality
The download image feature uses html2canvas with the following configuration:
```typescript
const canvas = await html2canvas(element, {
scale: 2, // High resolution (2x)
useCORS: true, // Handle cross-origin images
backgroundColor: '#ffffff',
logging: false,
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight,
});
```
The generated image is named: `人生K线_[UserName]_[Date].png`
## Save Profile Integration with Existing System
The save profile functionality integrates seamlessly with the existing profile management system:
1. Uses the same data structure as `CreateProfileModal`
2. Stores in localStorage under `lifekline_profiles` key
3. Compatible with `ProfileManager` component
4. Can be loaded back using the profile selector
## Styling and UX
- All buttons use consistent styling with the existing design system
- Loading states with spinners during async operations
- Error messages displayed inline with appropriate styling
- Modal dialogs use backdrop blur for better focus
- Responsive design works on mobile and desktop
## Testing Checklist
✓ Build successful with no TypeScript errors
- [ ] Save Profile Dialog opens and closes correctly
- [ ] Profile name validation works
- [ ] Bazi information displays correctly in dialog
- [ ] Profile saves to localStorage
- [ ] Saved profile can be loaded from ProfileManager
- [ ] Download Image generates PNG correctly
- [ ] Downloaded image includes all result sections
- [ ] Image filename includes username and date
- [ ] Error handling works for both features
- [ ] Responsive design on mobile devices
- [ ] Integration with share functionality
## Browser Compatibility
- html2canvas requires modern browsers
- Works with Chrome, Firefox, Safari, Edge
- May have limitations with very old browsers (IE11 not supported)
## Future Enhancements
Potential improvements for future versions:
1. Add image format options (PNG, JPEG)
2. Add image quality/resolution selector
3. Save to cloud storage instead of just localStorage
4. Batch profile management
5. Profile import/export functionality
6. Share profile as QR code
7. Print-optimized layout for PDF export
|