欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

在这里插入图片描述

📌 概述

宠物档案模块用于管理和展示宠物的详细信息。这个模块提供了完整的宠物信息编辑功能,包括基本信息、身体特征、行为习惯等。通过Cordova框架,我们能够在Web层实现复杂的表单处理和数据验证,同时利用OpenHarmony的媒体库能力管理宠物照片。

宠物档案模块采用了标签页设计,将宠物信息分为多个类别,用户可以逐个编辑和查看。同时提供了宠物信息的导出功能,用户可以生成宠物档案报告。

🔗 完整流程

档案加载流程:当用户进入宠物档案页面时,应用首先检查是否是编辑现有宠物还是创建新宠物。如果是编辑,应用从数据库中加载该宠物的所有信息。如果是创建新宠物,应用初始化一个空的表单。同时,应用会加载宠物的所有照片和医疗记录。

信息编辑流程:用户可以编辑宠物的各项信息,包括名称、品种、出生日期、性别、颜色、特殊标记等。编辑过程中,应用会进行实时验证,确保数据的有效性。用户点击保存后,应用将更新的信息保存到数据库。

照片管理流程:用户可以上传宠物的多张照片,应用会自动压缩和优化图片。用户可以设置其中一张照片为宠物头像。应用支持删除不需要的照片。

🔧 Web代码实现

// 加载宠物档案
async function loadPetProfile(petId) {
    try {
        if (!petId) {
            return {
                isNew: true,
                pet: {
                    name: '',
                    breed: '',
                    birthDate: '',
                    gender: '',
                    color: '',
                    microchipId: '',
                    specialMarks: ''
                },
                photos: []
            };
        }
        
        const pet = await db.getPet(petId);
        const photos = await db.getPetPhotos(petId);
        
        return {
            isNew: false,
            pet: pet,
            photos: photos
        };
    } catch (error) {
        console.error('加载宠物档案失败:', error);
        return null;
    }
}

// 保存宠物档案
async function savePetProfile(petData) {
    try {
        if (petData.id) {
            // 更新现有宠物
            await db.updatePet(petData.id, petData);
            showSuccess('宠物档案已更新');
        } else {
            // 创建新宠物
            const id = await db.addPet(petData);
            showSuccess('宠物档案已创建');
        }
        
        app.navigateTo('pet-list');
    } catch (error) {
        showError('保存宠物档案失败: ' + error.message);
    }
}

这两个函数处理宠物档案的加载和保存。加载函数检查是否是新建还是编辑,并加载相应的数据。保存函数根据是否存在ID来决定是更新还是创建。

// 渲染宠物档案页面
async function renderPetProfile() {
    const profileData = await loadPetProfile(currentPetId);
    
    if (!profileData) {
        showError('无法加载宠物档案');
        return;
    }
    
    const html = `
        <div class="pet-profile-container">
            <div class="profile-header">
                <h1>${profileData.isNew ? '新建宠物档案' : '编辑宠物档案'}</h1>
            </div>
            
            <form id="pet-profile-form" class="pet-form">
                <div class="form-section">
                    <h2>基本信息</h2>
                    <div class="form-group">
                        <label>宠物名称</label>
                        <input type="text" id="pet-name" value="${profileData.pet.name}" required>
                    </div>
                    <div class="form-group">
                        <label>品种</label>
                        <input type="text" id="pet-breed" value="${profileData.pet.breed}" required>
                    </div>
                    <div class="form-group">
                        <label>出生日期</label>
                        <input type="date" id="pet-birthdate" value="${profileData.pet.birthDate}">
                    </div>
                    <div class="form-group">
                        <label>性别</label>
                        <select id="pet-gender">
                            <option value="">-- 选择性别 --</option>
                            <option value="male" ${profileData.pet.gender === 'male' ? 'selected' : ''}>公</option>
                            <option value="female" ${profileData.pet.gender === 'female' ? 'selected' : ''}>母</option>
                        </select>
                    </div>
                </div>
                
                <div class="form-section">
                    <h2>身体特征</h2>
                    <div class="form-group">
                        <label>颜色</label>
                        <input type="text" id="pet-color" value="${profileData.pet.color}">
                    </div>
                    <div class="form-group">
                        <label>特殊标记</label>
                        <textarea id="pet-marks">${profileData.pet.specialMarks}</textarea>
                    </div>
                    <div class="form-group">
                        <label>芯片ID</label>
                        <input type="text" id="pet-microchip" value="${profileData.pet.microchipId}">
                    </div>
                </div>
                
                <div class="form-section">
                    <h2>宠物照片</h2>
                    <div class="photo-upload">
                        <button type="button" class="btn-small" onclick="uploadPetPhoto()">上传照片</button>
                    </div>
                    <div class="photo-gallery">
                        ${profileData.photos.map(photo => `
                            <div class="photo-item">
                                <img src="${photo.path}" alt="宠物照片">
                                <button type="button" class="btn-small btn-danger" onclick="deletePetPhoto(${photo.id})">删除</button>
                            </div>
                        `).join('')}
                    </div>
                </div>
                
                <div class="form-actions">
                    <button type="button" class="btn-secondary" onclick="app.navigateTo('pet-list')">取消</button>
                    <button type="submit" class="btn-primary">保存档案</button>
                </div>
            </form>
        </div>
    `;
    
    document.getElementById('page-container').innerHTML = html;
    attachPetProfileListeners();
}

这个渲染函数生成了宠物档案编辑表单。表单分为多个部分,包括基本信息、身体特征和照片管理。

// 上传宠物照片
async function uploadPetPhoto() {
    try {
        const imagePath = await selectNativeImage();
        if (imagePath) {
            const compressedPath = await compressImage(imagePath);
            await db.addPetPhoto(currentPetId, {
                path: compressedPath,
                uploadedAt: new Date()
            });
            showSuccess('照片已上传');
            renderPetProfile();
        }
    } catch (error) {
        showError('上传照片失败: ' + error.message);
    }
}

上传照片函数调用原生的图片选择功能,然后压缩图片并保存到数据库。

🔌 原生代码实现

// PetProfilePlugin.ets - 宠物档案原生插件
import { fileIo } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';

@Entry
@Component
struct PetProfilePlugin {
    // 压缩宠物照片
    compressImage(imagePath: string, callback: (compressedPath: string) => void): void {
        try {
            const sourceFile = fileIo.openSync(imagePath, fileIo.OpenMode.READ);
            const compressedPath = imagePath.replace('.jpg', '_compressed.jpg');
            
            // 图片压缩逻辑
            const imageSource = image.createImageSource(imagePath);
            const pixelMap = imageSource.createPixelMap();
            
            // 缩放到合适的大小
            const scaledPixelMap = pixelMap.scale(0.5, 0.5);
            
            // 保存压缩后的图片
            const imagePackerApi = image.createImagePacker();
            imagePackerApi.packing(scaledPixelMap, { format: 'image/jpeg', quality: 80 })
                .then((data) => {
                    const file = fileIo.openSync(compressedPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE);
                    fileIo.writeSync(file.fd, data);
                    fileIo.closeSync(file.fd);
                    callback(compressedPath);
                });
        } catch (error) {
            console.error('[PetProfilePlugin] 压缩图片失败:', error);
            callback('');
        }
    }
    
    // 生成宠物档案报告
    generatePetReport(petData: string, callback: (reportPath: string) => void): void {
        try {
            const pet = JSON.parse(petData);
            const reportContent = `
宠物档案报告
============
名称: ${pet.name}
品种: ${pet.breed}
出生日期: ${pet.birthDate}
性别: ${pet.gender}
颜色: ${pet.color}
特殊标记: ${pet.specialMarks}
芯片ID: ${pet.microchipId}
生成时间: ${new Date().toISOString()}
            `;
            
            const reportPath = `/data/reports/pet_${pet.id}_report.txt`;
            const file = fileIo.openSync(reportPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE);
            fileIo.writeSync(file.fd, reportContent);
            fileIo.closeSync(file.fd);
            
            callback(reportPath);
        } catch (error) {
            console.error('[PetProfilePlugin] 生成报告失败:', error);
            callback('');
        }
    }
    
    build() {
        Column() {
            Web({ src: 'resource://rawfile/www/index.html', controller: new WebviewController() })
        }
    }
}

这个原生插件提供了图片压缩和报告生成功能。通过image模块,我们能够压缩和优化宠物照片。通过文件操作,我们能够生成宠物档案报告。

Web-Native通信代码

// 压缩图片
function compressImage(imagePath) {
    return new Promise((resolve, reject) => {
        cordova.exec(
            (compressedPath) => {
                if (compressedPath) {
                    resolve(compressedPath);
                } else {
                    reject(new Error('压缩失败'));
                }
            },
            (error) => {
                console.error('压缩失败:', error);
                reject(error);
            },
            'PetProfilePlugin',
            'compressImage',
            [imagePath]
        );
    });
}

// 生成宠物档案报告
function generatePetReport(petData) {
    return new Promise((resolve, reject) => {
        cordova.exec(
            (reportPath) => {
                if (reportPath) {
                    showSuccess(`报告已生成: ${reportPath}`);
                    resolve(reportPath);
                } else {
                    reject(new Error('生成失败'));
                }
            },
            (error) => {
                console.error('生成失败:', error);
                reject(error);
            },
            'PetProfilePlugin',
            'generatePetReport',
            [JSON.stringify(petData)]
        );
    });
}

这段代码展示了如何通过Cordova调用原生的图片压缩和报告生成功能。通过Promise包装,我们能够以异步的方式处理这些操作。

📝 总结

宠物档案模块展示了Cordova与OpenHarmony在表单处理和媒体管理方面的深度集成。在Web层,我们实现了复杂的表单验证和数据管理。在原生层,我们提供了图片压缩和报告生成等功能。

通过标签页设计,宠物档案提供了清晰的信息组织。通过照片管理功能,用户可以为宠物保存多张照片。通过Web-Native通信,我们能够充分利用OpenHarmony的媒体处理能力,为用户提供完整的宠物档案管理体验。

在实际开发中,建议实现宠物信息的版本控制,提供宠物档案的分享功能,并支持多语言的档案生成。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐