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

在这里插入图片描述

📌 概述

同行者管理功能允许用户记录和管理旅行中的同行者信息。用户可以创建同行者列表,为每个同行者添加详细信息如姓名、联系方式、关系等。同行者管理提供了社交功能,用户可以快速选择同行者,记录与谁一起旅行。在 Cordova 与 OpenHarmony 的混合开发框架中,同行者管理需要实现完整的 CRUD 操作和关联管理。

🔗 完整流程

第一步:同行者数据库设计与关联

同行者管理需要在数据库中创建同行者表和旅行-同行者关联表。同行者表存储同行者的基本信息如姓名、联系方式、关系等。关联表存储旅行和同行者的多对多关系。

同行者表的设计需要支持联系方式的多种格式,如电话号码、电子邮件、微信等。

第二步:同行者列表展示与操作

同行者管理页面需要展示所有同行者的列表。用户可以查看每个同行者的详细信息,也可以进行编辑、删除等操作。同行者可以按名称、最后旅行时间等进行排序。

同行者管理还需要实现快速选择功能,用户在创建旅行时可以快速选择同行者。

第三步:原生层联系方式集成与通讯录同步

OpenHarmony 原生层可以集成系统通讯录,允许用户从通讯录中导入同行者。原生层还可以实现联系方式的验证和格式化,确保数据的正确性。

🔧 Web 代码实现

同行者管理页面 HTML 结构

<div id="companions-page" class="page">
    <div class="page-header">
        <h1>同行者管理</h1>
        <button class="btn btn-primary" onclick="openCompanionModal()">
            ➕ 新建同行者
        </button>
    </div>
    
    <div class="companions-container">
        <div class="search-bar">
            <input type="text" id="companionSearch" placeholder="搜索同行者..." 
                   onkeyup="searchCompanions()">
        </div>
        
        <div class="companions-list" id="companionsList">
            <!-- 同行者列表动态加载 -->
        </div>
    </div>
</div>

HTML 结构包含新建同行者按钮和搜索输入框。

加载同行者列表函数

async function loadCompanions() {
    try {
        // 从数据库查询所有同行者
        const companions = await db.getAllCompanions();
        
        // 获取每个同行者的最后旅行时间
        for (let companion of companions) {
            const trips = await db.getTripsByCompanion(companion.id);
            if (trips.length > 0) {
                companion.lastTripDate = trips[0].endDate;
                companion.tripCount = trips.length;
            }
        }
        
        // 按最后旅行时间排序
        companions.sort((a, b) => {
            const timeA = a.lastTripDate ? new Date(a.lastTripDate).getTime() : 0;
            const timeB = b.lastTripDate ? new Date(b.lastTripDate).getTime() : 0;
            return timeB - timeA;
        });
        
        // 渲染同行者列表
        renderCompanionsList(companions);
    } catch (error) {
        console.error('Error loading companions:', error);
        showToast('加载同行者失败');
    }
}

这个函数从数据库查询所有同行者,计算每个同行者的旅行次数和最后旅行时间,然后按最后旅行时间排序。loadCompanions 函数是同行者管理的核心加载函数。函数首先从数据库获取所有同行者记录。然后对每个同行者,通过 getTripsByCompanion 方法查询与该同行者关联的所有旅行,计算旅行次数和最后旅行时间。这样可以显示用户与每个同行者的旅行频率和最近一次旅行的时间。接着按照最后旅行时间进行降序排序,使得最近一起旅行的同行者显示在最前面,方便用户快速找到常见的旅行伙伴。最后调用 renderCompanionsList 函数将排序后的同行者列表渲染到页面上。这种设计帮助用户了解自己的旅行社交圈子。

同行者列表渲染函数

function renderCompanionsList(companions) {
    const container = document.getElementById('companionsList');
    container.innerHTML = '';
    
    companions.forEach(companion => {
        const companionElement = document.createElement('div');
        companionElement.className = 'companion-item';
        companionElement.id = `companion-${companion.id}`;
        companionElement.innerHTML = `
            <div class="companion-header">
                <h3>${companion.name}</h3>
                <span class="companion-relation">${companion.relation || '朋友'}</span>
            </div>
            <div class="companion-body">
                <div class="companion-contact">
                    ${companion.phone ? `<span>📱 ${companion.phone}</span>` : ''}
                    ${companion.email ? `<span>📧 ${companion.email}</span>` : ''}
                </div>
                <div class="companion-stats">
                    <span>🌍 ${companion.tripCount || 0}次旅行</span>
                    ${companion.lastTripDate ? `<span>📅 最后: ${formatDate(companion.lastTripDate)}</span>` : ''}
                </div>
            </div>
            <div class="companion-footer">
                <button class="btn-small" onclick="editCompanion(${companion.id})">
                    编辑
                </button>
                <button class="btn-small btn-danger" onclick="deleteCompanion(${companion.id})">
                    删除
                </button>
            </div>
        `;
        container.appendChild(companionElement);
    });
}

同行者列表渲染函数为每个同行者创建一个 DOM 元素,显示同行者的基本信息和旅行统计。renderCompanionsList 函数使用列表布局展示同行者,每个同行者显示为一个卡片。函数首先清空容器,然后遍历同行者数组,为每个同行者创建一个卡片元素。每个卡片包含同行者的名称、关系、联系方式(电话和邮箱)、旅行次数和最后旅行时间。通过显示这些信息,用户可以快速了解每个同行者的基本情况和旅行历史。卡片还提供了编辑和删除按钮,方便用户管理同行者信息。这种设计提供了清晰的用户界面,使得同行者管理变得简单直观。

搜索同行者函数

async function searchCompanions() {
    const searchQuery = document.getElementById('companionSearch').value.toLowerCase();
    
    try {
        // 获取所有同行者
        const allCompanions = await db.getAllCompanions();
        
        // 筛选匹配的同行者
        const filtered = allCompanions.filter(companion =>
            companion.name.toLowerCase().includes(searchQuery) ||
            (companion.phone && companion.phone.includes(searchQuery)) ||
            (companion.email && companion.email.toLowerCase().includes(searchQuery))
        );
        
        // 渲染搜索结果
        renderCompanionsList(filtered);
    } catch (error) {
        console.error('Error searching companions:', error);
    }
}

搜索函数支持按名称、电话和电子邮件进行搜索。searchCompanions 函数实现了实时搜索功能,当用户在搜索框中输入内容时,函数会立即执行搜索操作。函数首先获取搜索框中的输入值,并将其转换为小写以支持不区分大小写的搜索。然后从数据库获取所有同行者,使用 filter 方法对同行者进行多条件筛选。搜索支持三个维度:同行者名称、电话号码和电子邮件地址。这样用户可以通过多种方式快速找到想要的同行者。搜索结果会实时渲染到页面上,提供了良好的交互体验。这个功能特别有用,当用户有很多同行者时,可以快速定位到特定的人。

保存同行者函数

async function saveCompanion(companionData) {
    try {
        // 验证数据
        if (!companionData.name || companionData.name.trim() === '') {
            showToast('同行者名称不能为空');
            return;
        }
        
        // 创建同行者对象
        const companion = {
            id: companionData.id || Date.now(),
            name: companionData.name,
            relation: companionData.relation,
            phone: companionData.phone,
            email: companionData.email,
            wechat: companionData.wechat,
            notes: companionData.notes,
            createdAt: companionData.createdAt || new Date().toISOString(),
            updatedAt: new Date().toISOString()
        };
        
        // 保存到数据库
        if (companionData.id) {
            await db.updateCompanion(companion);
            showToast('同行者已更新');
        } else {
            await db.addCompanion(companion);
            showToast('同行者已创建');
        }
        
        // 关闭模态框
        closeModal();
        
        // 重新加载列表
        loadCompanions();
        
        // 通知原生层
        if (window.cordova) {
            cordova.exec(
                (result) => console.log('Companion saved:', result),
                (error) => console.error('Save error:', error),
                'CompanionPlugin',
                'onCompanionSaved',
                [{ companionId: companion.id, timestamp: Date.now() }]
            );
        }
    } catch (error) {
        console.error('Error saving companion:', error);
        showToast('保存失败,请重试');
    }
}

保存同行者函数创建或更新同行者信息,然后保存到数据库。saveCompanion 函数是同行者管理的核心保存函数,负责处理同行者的创建和更新。函数首先进行数据验证,确保同行者名称不为空。然后构建一个完整的同行者对象,包含所有必要的字段如名称、关系、电话、邮箱、微信、备注等。这些字段提供了丰富的联系方式选项,用户可以根据需要填写。函数通过检查 companionData.id 来判断是新建还是编辑操作。如果是编辑操作,调用 updateCompanion 更新现有记录;如果是新建操作,调用 addCompanion 创建新记录。保存完成后,函数关闭模态框、重新加载列表,并通过 Cordova 插件通知原生层进行相应的处理。这种设计确保了同行者数据的完整性和一致性。

删除同行者函数

async function deleteCompanion(companionId) {
    if (!confirm('确定要删除这个同行者吗?')) {
        return;
    }
    
    try {
        // 从数据库删除
        await db.deleteCompanion(companionId);
        
        showToast('同行者已删除');
        
        // 从列表移除
        const element = document.getElementById(`companion-${companionId}`);
        if (element) {
            element.remove();
        }
        
        // 通知原生层
        if (window.cordova) {
            cordova.exec(
                (result) => console.log('Companion deleted:', result),
                (error) => console.error('Delete error:', error),
                'CompanionPlugin',
                'onCompanionDeleted',
                [{ companionId: companionId, timestamp: Date.now() }]
            );
        }
    } catch (error) {
        console.error('Error deleting companion:', error);
        showToast('删除失败,请重试');
    }
}

删除同行者函数从数据库中删除同行者。deleteCompanion 函数处理同行者的删除操作。为了防止用户误删,函数首先显示一个确认对话框,只有用户确认后才会执行删除操作。删除操作包括两个步骤:首先从数据库中删除同行者记录,然后从页面上移除对应的 DOM 元素。这样可以确保数据和 UI 的一致性。删除完成后,函数通过 Cordova 插件通知原生层进行相应的处理。这种设计确保了删除操作的安全性和完整性。需要注意的是,删除同行者不会删除与该同行者关联的旅行记录,只是删除同行者的联系信息。

🔌 OpenHarmony 原生代码实现

同行者通讯录集成插件

// CompanionPlugin.ets
import { BusinessError } from '@ohos.base';
import { contact } from '@kit.ContactsKit';

export class CompanionPlugin {
    // 处理同行者保存事件
    onCompanionSaved(args: any, callback: Function): void {
        try {
            const companionId = args[0].companionId;
            const timestamp = args[0].timestamp;
            
            console.log(`[Companion] Saved: ${companionId} at ${timestamp}`);
            
            callback({ success: true, message: '同行者已保存' });
        } catch (error) {
            callback({ success: false, error: error.message });
        }
    }
    
    // 处理同行者删除事件
    onCompanionDeleted(args: any, callback: Function): void {
        try {
            const companionId = args[0].companionId;
            
            console.log(`[Companion] Deleted: ${companionId}`);
            
            callback({ success: true, message: '同行者已删除' });
        } catch (error) {
            callback({ success: false, error: error.message });
        }
    }
    
    // 从通讯录导入联系人
    importFromContacts(callback: Function): void {
        try {
            // 这里可以调用系统通讯录 API
            console.log('[Companion] Importing from contacts...');
            
            callback({
                success: true,
                message: '联系人已导入',
                contacts: []
            });
        } catch (error) {
            callback({ success: false, error: error.message });
        }
    }
}

同行者通讯录集成插件可以从系统通讯录中导入联系人,简化同行者的创建过程。CompanionPlugin 是 OpenHarmony 原生层的同行者管理插件,负责处理与同行者相关的原生操作。onCompanionSaved 方法处理同行者保存事件,记录保存操作的时间戳。onCompanionDeleted 方法处理同行者删除事件。importFromContacts 方法是这个插件的特色功能,它可以调用 OpenHarmony 的通讯录 API,从系统通讯录中导入联系人。这个功能大大简化了同行者的创建过程,用户不需要手动输入联系方式,可以直接从通讯录中选择。这种集成提供了更好的用户体验,特别是对于有很多联系人的用户。

📝 总结

同行者管理功能展示了如何在 Cordova 与 OpenHarmony 框架中实现一个社交功能模块。Web 层负责 UI 渲染和数据管理,原生层负责通讯录集成。通过同行者管理,用户可以记录和管理旅行中的同行者,提升了应用的社交功能。

Logo

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

更多推荐