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

在这里插入图片描述

📌 模块概述

仪表板是MovieTracker应用的首页,作为用户的信息中心,展示观影统计、最近观看的影片、热门分类等关键信息。该模块采用Cordova框架与OpenHarmony原生能力相结合的混合开发方式,通过Web层展示丰富的UI界面,同时利用原生能力提供更好的性能和系统集成。

仪表板模块的核心功能包括:统计卡片展示(总影片数、已看影片数、想看影片数)、最近观看列表、分类分布图表、快速操作按钮等。用户打开应用时首先看到的就是这个仪表板,因此其性能和用户体验至关重要。

该模块展示了如何在Cordova框架下,通过IndexedDB数据库获取数据,使用原生JavaScript进行数据处理和DOM操作,同时通过OpenHarmony原生插件提供额外的功能支持。

🔗 完整流程

第一步:初始化与数据加载

当用户打开应用或导航到仪表板页面时,首先需要初始化模块并从IndexedDB数据库中加载数据。这个过程包括获取所有影片记录、计算统计数据、准备UI所需的数据结构。

在Cordova框架中,数据加载是异步的,需要通过Promise或async/await来处理。我们首先检查数据库是否已初始化,然后查询所有影片、分类和标签数据,最后进行数据聚合和统计计算。这个过程需要考虑性能因素,避免阻塞UI线程。

第二步:数据统计与计算

仪表板需要展示多种统计数据,包括影片总数、已看影片数、想看影片数、各分类的影片数量等。这些统计数据需要从原始数据中计算得出。我们需要遍历所有影片记录,根据其状态(已看、想看、未分类)进行分类统计。

同时,我们还需要计算每个分类的影片数量、评分分布等信息。这些计算可能涉及复杂的数据聚合操作,需要优化算法以提高性能。在处理大量数据时,可以考虑使用缓存机制,避免重复计算。

第三步:UI渲染与交互

完成数据计算后,需要将数据绑定到UI组件中进行渲染。这包括更新统计卡片的数值、渲染最近观看列表、绘制分类分布图表等。在Cordova框架中,可以使用原生JavaScript或Vue.js等框架来实现动态UI更新。

同时需要为各个交互元素绑定事件监听器,如点击统计卡片跳转到对应的列表页面、点击快速操作按钮执行相应的操作等。这些交互需要考虑用户体验,提供及时的反馈和流畅的动画效果。

🔧 Web代码实现

仪表板HTML结构

<div id="dashboard-page" class="page">
    <div class="dashboard-container">
        <div class="stats-grid">
            <div class="stat-card" onclick="app.navigateTo('all-movies')">
                <div class="stat-icon">📽️</div>
                <div class="stat-content">
                    <div class="stat-label">总影片数</div>
                    <div class="stat-value" id="total-movies">0</div>
                </div>
            </div>
            <div class="stat-card" onclick="app.navigateTo('watched-movies')">
                <div class="stat-icon"></div>
                <div class="stat-content">
                    <div class="stat-label">已看影片</div>
                    <div class="stat-value" id="watched-count">0</div>
                </div>
            </div>
            <div class="stat-card" onclick="app.navigateTo('watchlist')">
                <div class="stat-icon"></div>
                <div class="stat-content">
                    <div class="stat-label">想看清单</div>
                    <div class="stat-value" id="watchlist-count">0</div>
                </div>
            </div>
        </div>
        <div class="recent-movies">
            <h3>最近观看</h3>
            <div id="recent-list" class="movie-list"></div>
        </div>
    </div>
</div>

这个HTML结构定义了仪表板的基本布局。统计卡片使用网格布局排列,每个卡片包含图标、标签和数值。最近观看列表是一个动态容器,将通过JavaScript填充电影数据。onclick事件处理器直接调用app.navigateTo()方法进行页面导航。

仪表板数据加载

async function renderDashboard() {
    try {
        const allMovies = await db.getAllMovies();
        const watched = allMovies.filter(m => m.status === 'watched');
        const watchlist = allMovies.filter(m => m.status === 'watchlist');
        
        document.getElementById('total-movies').textContent = allMovies.length;
        document.getElementById('watched-count').textContent = watched.length;
        document.getElementById('watchlist-count').textContent = watchlist.length;
        
        const recentMovies = allMovies
            .sort((a, b) => new Date(b.lastUpdated) - new Date(a.lastUpdated))
            .slice(0, 5);
        
        renderRecentMoviesList(recentMovies);
    } catch (error) {
        console.error('仪表板加载失败:', error);
        showError('加载仪表板数据失败');
    }
}

这个函数是仪表板的核心数据加载逻辑。首先从数据库获取所有影片,然后根据状态进行过滤统计。使用filter()方法分别获取已看和想看的影片,计算各自的数量。然后对所有影片按最后更新时间排序,取前5条作为最近观看列表。

最近观看列表渲染

function renderRecentMoviesList(movies) {
    const listContainer = document.getElementById('recent-list');
    listContainer.innerHTML = '';
    
    movies.forEach(movie => {
        const movieItem = document.createElement('div');
        movieItem.className = 'movie-item';
        movieItem.innerHTML = `
            <img src="${movie.poster}" alt="${movie.title}" class="movie-poster">
            <div class="movie-info">
                <h4>${movie.title}</h4>
                <p class="movie-year">${movie.year}</p>
                <p class="movie-rating">⭐ ${movie.rating || '未评分'}</p>
            </div>
        `;
        movieItem.onclick = () => app.navigateTo('movie-detail', movie.id);
        listContainer.appendChild(movieItem);
    });
}

这个函数将最近观看的影片列表渲染到DOM中。对每个影片创建一个movie-item元素,包含海报图片、标题、年份和评分信息。为每个影片项添加点击事件监听器,点击时导航到影片详情页面。使用innerHTML设置内容时需要注意XSS防护,确保数据来自可信源。

🔌 OpenHarmony原生代码

仪表板插件初始化

// DashboardPlugin.ets
import { webview } from '@kit.ArkWeb';
import { common } from '@kit.AbilityKit';

export class DashboardPlugin {
    private context: common.UIAbilityContext;
    
    constructor(context: common.UIAbilityContext) {
        this.context = context;
    }
    
    public registerDashboard(controller: webview.WebviewController): void {
        controller.registerJavaScriptProxy({
            object: new DashboardBridge(),
            name: 'dashboardNative',
            methodList: ['getSystemInfo', 'getDeviceStats', 'requestPermission']
        });
    }
}

这个OpenHarmony原生插件负责初始化仪表板的原生功能。通过registerJavaScriptProxy方法将原生对象暴露给Web层,使得JavaScript代码可以调用原生方法。DashboardBridge类包含了所有可供Web层调用的原生方法。

系统信息获取

export class DashboardBridge {
    public getSystemInfo(): string {
        const info = {
            platform: 'OpenHarmony',
            version: '4.0',
            device: 'HarmonyOS Device',
            timestamp: Date.now()
        };
        return JSON.stringify(info);
    }
    
    public getDeviceStats(): string {
        const stats = {
            memoryUsage: this.getMemoryUsage(),
            batteryLevel: this.getBatteryLevel(),
            networkStatus: this.getNetworkStatus()
        };
        return JSON.stringify(stats);
    }
    
    private getMemoryUsage(): number {
        // 获取设备内存使用情况
        return Math.random() * 100;
    }
    
    private getBatteryLevel(): number {
        // 获取电池电量
        return Math.random() * 100;
    }
    
    private getNetworkStatus(): string {
        // 获取网络状态
        return 'connected';
    }
}

这个类实现了仪表板所需的原生功能。getSystemInfo()方法返回系统信息,包括平台、版本等。getDeviceStats()方法获取设备统计信息,如内存使用、电池电量、网络状态等。这些信息可以在仪表板上显示,帮助用户了解设备状态。

Web-Native通信

JavaScript调用原生方法

async function loadSystemInfo() {
    try {
        if (window.dashboardNative) {
            const infoStr = window.dashboardNative.getSystemInfo();
            const info = JSON.parse(infoStr);
            console.log('系统信息:', info);
            
            const statsStr = window.dashboardNative.getDeviceStats();
            const stats = JSON.parse(statsStr);
            console.log('设备统计:', stats);
            
            updateDashboardWithSystemInfo(info, stats);
        }
    } catch (error) {
        console.error('获取系统信息失败:', error);
    }
}

这个函数展示了如何从JavaScript调用OpenHarmony原生方法。首先检查window.dashboardNative对象是否存在,然后调用getSystemInfo()和getDeviceStats()方法。由于原生方法返回JSON字符串,需要使用JSON.parse()进行解析。最后将获取的信息更新到仪表板UI中。

原生方法在仪表板中的应用

function updateDashboardWithSystemInfo(info, stats) {
    const systemInfoDiv = document.getElementById('system-info');
    if (systemInfoDiv) {
        systemInfoDiv.innerHTML = `
            <div class="system-card">
                <h4>系统信息</h4>
                <p>平台: ${info.platform}</p>
                <p>版本: ${info.version}</p>
                <p>设备: ${info.device}</p>
            </div>
            <div class="device-stats">
                <h4>设备统计</h4>
                <p>内存使用: ${stats.memoryUsage.toFixed(2)}%</p>
                <p>电池电量: ${stats.batteryLevel.toFixed(2)}%</p>
                <p>网络状态: ${stats.networkStatus}</p>
            </div>
        `;
    }
}

这个函数将原生获取的系统信息和设备统计数据展示在仪表板上。创建了两个卡片分别显示系统信息和设备统计。这样用户可以在仪表板上一目了然地看到系统状态,增强了应用的信息展示能力。

📝 总结

仪表板模块展示了Cordova与OpenHarmony混合开发的完整流程。通过Web层提供丰富的UI界面和交互体验,同时利用OpenHarmony原生能力获取系统信息和设备统计数据。这种混合开发方式既保证了跨平台兼容性,又能充分利用原生平台的优势。

在实现仪表板时,需要注意数据加载的异步处理、UI更新的性能优化、以及Web-Native通信的可靠性。通过合理的架构设计和代码组织,可以构建出高效、易维护的混合应用。

Logo

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

更多推荐