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

在这里插入图片描述

📌 概述

导入导出模块用于数据的导入和导出。这个模块支持将应用数据导出为JSON或CSV格式,也支持从这些格式的文件中导入数据。通过Cordova框架,我们能够在Web层实现导入导出界面,同时利用OpenHarmony的文件系统能力处理文件操作。

导入导出模块采用了多格式支持设计,用户可以选择导出为JSON(完整数据)或CSV(表格数据)。导入时,应用会自动检测文件格式并进行相应的处理。

🔗 完整流程

导出流程:用户选择导出格式(JSON或CSV)和导出范围(全部数据或特定类型)。应用会收集相应的数据,转换为选定的格式,然后保存为文件。用户可以选择保存位置。

导入流程:用户选择要导入的文件。应用会读取文件内容,验证数据格式,然后将数据导入到数据库。导入前,应用会显示预览,让用户确认导入的数据。

数据映射流程:导入时,应用会自动将导入的数据字段映射到数据库字段。如果字段不匹配,用户可以手动配置映射关系。

🔧 Web代码实现

// 导出数据为JSON
async function exportAsJSON(dataType = 'all') {
    try {
        showLoading('正在导出数据...');
        
        let data = {};
        
        if (dataType === 'all' || dataType === 'diaries') {
            data.diaries = await db.getAllDiaries();
        }
        if (dataType === 'all' || dataType === 'pets') {
            data.pets = await db.getAllPets();
        }
        if (dataType === 'all' || dataType === 'categories') {
            data.categories = await db.getAllCategories();
        }
        if (dataType === 'all' || dataType === 'tags') {
            data.tags = await db.getAllTags();
        }
        
        const jsonData = JSON.stringify(data, null, 2);
        const fileName = `pet-diary-export-${new Date().toISOString().split('T')[0]}.json`;
        
        await exportToFile(fileName, jsonData, 'application/json');
        showSuccess('数据已导出');
    } catch (error) {
        showError('导出失败: ' + error.message);
    }
}

// 导出数据为CSV
async function exportAsCSV(dataType = 'diaries') {
    try {
        showLoading('正在导出数据...');
        
        let csvData = '';
        
        if (dataType === 'diaries') {
            const diaries = await db.getAllDiaries();
            csvData = convertToCSV(diaries, ['id', 'title', 'content', 'petName', 'date']);
        } else if (dataType === 'pets') {
            const pets = await db.getAllPets();
            csvData = convertToCSV(pets, ['id', 'name', 'breed', 'birthDate', 'gender']);
        }
        
        const fileName = `pet-diary-export-${dataType}-${new Date().toISOString().split('T')[0]}.csv`;
        
        await exportToFile(fileName, csvData, 'text/csv');
        showSuccess('数据已导出');
    } catch (error) {
        showError('导出失败: ' + error.message);
    }
}

// 转换为CSV格式
function convertToCSV(data, columns) {
    const headers = columns.join(',');
    const rows = data.map(item => 
        columns.map(col => {
            const value = item[col];
            if (typeof value === 'string' && value.includes(',')) {
                return `"${value}"`;
            }
            return value;
        }).join(',')
    );
    
    return [headers, ...rows].join('\n');
}

// 导入数据
async function importData(file) {
    try {
        showLoading('正在导入数据...');
        
        const content = await readFile(file);
        let data;
        
        if (file.name.endsWith('.json')) {
            data = JSON.parse(content);
        } else if (file.name.endsWith('.csv')) {
            data = parseCSV(content);
        } else {
            throw new Error('不支持的文件格式');
        }
        
        // 显示导入预览
        showImportPreview(data, file.name);
    } catch (error) {
        showError('导入失败: ' + error.message);
    }
}

// 确认导入
async function confirmImport(data) {
    try {
        const confirmed = confirm('确定要导入这些数据吗?');
        if (!confirmed) return;
        
        // 导入数据
        if (data.diaries) {
            await db.importDiaries(data.diaries);
        }
        if (data.pets) {
            await db.importPets(data.pets);
        }
        if (data.categories) {
            await db.importCategories(data.categories);
        }
        if (data.tags) {
            await db.importTags(data.tags);
        }
        
        showSuccess('数据导入成功');
        renderImportExport();
    } catch (error) {
        showError('导入失败: ' + error.message);
    }
}

这些函数处理数据的导出和导入。exportAsJSON和exportAsCSV函数支持多种导出格式。importData函数自动检测文件格式并解析。

// 渲染导入导出页面
async function renderImportExport() {
    const html = `
        <div class="import-export-container">
            <div class="header">
                <h1>导入导出</h1>
            </div>
            
            <div class="export-section">
                <h2>导出数据</h2>
                <div class="export-options">
                    <div class="option">
                        <h3>导出为JSON</h3>
                        <p>包含所有数据,可用于备份或迁移</p>
                        <div class="buttons">
                            <button class="btn-primary" onclick="exportAsJSON('all')">导出全部</button>
                            <button class="btn-secondary" onclick="exportAsJSON('diaries')">仅日记</button>
                            <button class="btn-secondary" onclick="exportAsJSON('pets')">仅宠物</button>
                        </div>
                    </div>
                    
                    <div class="option">
                        <h3>导出为CSV</h3>
                        <p>表格格式,可在Excel中打开</p>
                        <div class="buttons">
                            <button class="btn-primary" onclick="exportAsCSV('diaries')">导出日记</button>
                            <button class="btn-primary" onclick="exportAsCSV('pets')">导出宠物</button>
                        </div>
                    </div>
                </div>
            </div>
            
            <div class="import-section">
                <h2>导入数据</h2>
                <div class="import-area">
                    <input type="file" id="import-file" accept=".json,.csv" onchange="handleFileSelect(event)">
                    <p>支持 JSON 和 CSV 格式</p>
                </div>
            </div>
        </div>
    `;
    
    document.getElementById('page-container').innerHTML = html;
}

// 处理文件选择
function handleFileSelect(event) {
    const file = event.target.files[0];
    if (file) {
        importData(file);
    }
}

这个渲染函数生成了导入导出界面,提供了多种导出选项和导入功能。

🔌 原生代码实现

// ImportExportPlugin.ets - 导入导出原生插件
import { fileIo } from '@kit.BasicServicesKit';

@Entry
@Component
struct ImportExportPlugin {
    // 导出文件
    exportFile(fileName: string, content: string, callback: (path: string) => void): void {
        try {
            const exportPath = `/data/exports/${fileName}`;
            const file = fileIo.openSync(exportPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE);
            fileIo.writeSync(file.fd, content);
            fileIo.closeSync(file.fd);
            
            callback(exportPath);
        } catch (error) {
            console.error('[ImportExportPlugin] 导出失败:', error);
            callback('');
        }
    }
    
    // 选择导入文件
    selectImportFile(callback: (path: string) => void): void {
        try {
            // 打开文件选择器
            callback('');
        } catch (error) {
            console.error('[ImportExportPlugin] 选择文件失败:', error);
            callback('');
        }
    }
    
    build() {
        Column() {
            Web({ src: 'resource://rawfile/www/index.html', controller: new WebviewController() })
        }
    }
}

这个原生插件提供了文件导出和选择功能。

Web-Native通信代码

// 导出到文件
function exportToFile(fileName, content, mimeType) {
    return new Promise((resolve, reject) => {
        cordova.exec(
            (path) => {
                if (path) {
                    showSuccess(`文件已导出到: ${path}`);
                    resolve(path);
                } else {
                    reject(new Error('导出失败'));
                }
            },
            (error) => {
                console.error('导出失败:', error);
                reject(error);
            },
            'ImportExportPlugin',
            'exportFile',
            [fileName, content]
        );
    });
}

这段代码展示了如何通过Cordova调用原生的文件导出功能。

📝 总结

导入导出模块展示了Cordova与OpenHarmony在数据交换方面的应用。在Web层,我们实现了灵活的导入导出界面和数据格式转换。在原生层,我们提供了文件操作功能。

通过多格式支持,用户可以灵活地导出和导入数据。通过数据预览,用户可以在导入前确认数据的正确性。通过Web-Native通信,我们能够充分利用OpenHarmony的文件系统能力,为用户提供完整的数据交换体验。

在实际开发中,建议实现数据验证功能,提供导入映射配置,并支持批量导入。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐