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

在这里插入图片描述

📌 概述

福报分类模块允许用户创建、编辑、删除自定义的福报分类。分类帮助用户组织和管理不同类型的福报行为,如慈善捐赠、帮助他人、志愿服务等。通过分类,用户可以更清晰地了解自己在不同领域的福报积累情况。

🔗 完整流程

第一部分:分类管理界面

用户进入分类管理页面,看到所有已创建的分类列表。每个分类显示分类名称、颜色、使用次数等信息。用户可以点击"新建分类"按钮创建新分类,或点击现有分类进行编辑或删除。

第二部分:分类创建与编辑

用户填写分类表单,包括分类名称、颜色、描述等。前端进行表单验证,原生层进行数据库操作。新建分类时,检查分类名称是否重复。编辑分类时,更新数据库中的分类信息,并更新所有使用该分类的福报记录。

第三部分:分类统计与应用

系统统计每个分类被使用的次数,显示在分类列表中。当用户创建福报记录时,可以选择分类。系统根据分类统计用户的福报分布情况。

🔧 Web 代码实现

分类管理 HTML 结构

<div class="categories-container">
  <div class="categories-header">
    <h1 class="categories-title">福报分类</h1>
    <button class="btn-add-category" onclick="openCategoryForm()">
      <span class="icon"></span>
      <span class="text">新建分类</span>
    </button>
  </div>

  <div class="categories-grid" id="categoriesList">
    <!-- 分类卡片将动态插入这里 -->
  </div>

  <div class="categories-stats">
    <div class="stat-box">
      <div class="stat-label">总分类数</div>
      <div class="stat-value" id="totalCategories">0</div>
    </div>
    <div class="stat-box">
      <div class="stat-label">最常用分类</div>
      <div class="stat-value" id="topCategory">--</div>
    </div>
  </div>
</div>

<!-- 分类表单模态框 -->
<div class="modal" id="categoryModal">
  <div class="modal-content">
    <div class="modal-header">
      <h2>新建分类</h2>
      <button class="modal-close" onclick="closeCategoryForm()"></button>
    </div>

    <form class="category-form" id="categoryForm">
      <div class="form-group">
        <label for="categoryName">分类名称</label>
        <input type="text" id="categoryName" class="form-control" placeholder="输入分类名称" required />
      </div>

      <div class="form-group">
        <label for="categoryColor">分类颜色</label>
        <div class="color-picker">
          <input type="color" id="categoryColor" class="form-control" value="#667eea" />
          <div class="color-preview" id="colorPreview" style="background: #667eea;"></div>
        </div>
      </div>

      <div class="form-group">
        <label for="categoryDesc">分类描述</label>
        <textarea id="categoryDesc" class="form-control" placeholder="输入分类描述" rows="3"></textarea>
      </div>

      <div class="form-actions">
        <button type="submit" class="btn btn-primary">保存分类</button>
        <button type="button" class="btn btn-secondary" onclick="closeCategoryForm()">取消</button>
      </div>
    </form>
  </div>
</div>

HTML 结构包含分类列表、统计信息和分类表单。使用网格布局展示分类卡片。

分类管理样式

.categories-container {
  padding: 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  min-height: 100vh;
}

.categories-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: white;
  margin-bottom: 30px;
}

.categories-title {
  font-size: 32px;
  font-weight: bold;
  margin: 0;
}

.btn-add-category {
  padding: 10px 20px;
  background: white;
  color: #667eea;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  font-weight: bold;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s ease;
}

.btn-add-category:hover {
  transform: scale(1.05);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.categories-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}

.category-card {
  background: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.category-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
}

.category-color {
  width: 100%;
  height: 60px;
  border-radius: 8px;
  margin-bottom: 15px;
}

.category-name {
  font-size: 18px;
  font-weight: bold;
  color: #333;
  margin-bottom: 8px;
}

.category-desc {
  font-size: 12px;
  color: #999;
  margin-bottom: 12px;
  min-height: 30px;
}

.category-count {
  font-size: 14px;
  color: #667eea;
  font-weight: bold;
  margin-bottom: 15px;
}

.category-actions {
  display: flex;
  gap: 8px;
}

.category-btn {
  flex: 1;
  padding: 8px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 12px;
  font-weight: bold;
  transition: all 0.3s ease;
}

.category-btn-edit {
  background: #409eff;
  color: white;
}

.category-btn-delete {
  background: #f56c6c;
  color: white;
}

.category-btn:hover {
  transform: scale(1.05);
}

.categories-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 15px;
}

.stat-box {
  background: white;
  padding: 20px;
  border-radius: 12px;
  text-align: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.stat-label {
  font-size: 12px;
  color: #999;
  margin-bottom: 8px;
}

.stat-value {
  font-size: 28px;
  font-weight: bold;
  color: #667eea;
}

.color-picker {
  display: flex;
  align-items: center;
  gap: 10px;
}

.color-preview {
  width: 40px;
  height: 40px;
  border-radius: 6px;
  border: 2px solid #ddd;
}

CSS 使用网格布局展示分类卡片。颜色预览显示分类颜色。响应式设计适配不同屏幕。

分类管理 JavaScript 逻辑

class CategoriesModule {
  constructor() {
    this.categories = [];
    this.init();
  }

  init() {
    this.setupEventListeners();
    this.loadCategories();
  }

  setupEventListeners() {
    document.getElementById('categoryForm').addEventListener('submit', (e) => {
      e.preventDefault();
      this.handleCategorySubmit();
    });

    document.getElementById('categoryColor').addEventListener('change', (e) => {
      document.getElementById('colorPreview').style.background = e.target.value;
    });
  }

  loadCategories() {
    cordova.exec(
      (result) => {
        this.categories = result.categories;
        this.renderCategories();
        this.updateStats(result.stats);
      },
      (error) => {
        console.error('加载分类失败:', error);
      },
      'CategoriesPlugin',
      'getCategories',
      []
    );
  }

  renderCategories() {
    const list = document.getElementById('categoriesList');
    list.innerHTML = '';

    this.categories.forEach(category => {
      const div = document.createElement('div');
      div.className = 'category-card';

      div.innerHTML = `
        <div class="category-color" style="background: ${category.color};"></div>
        <div class="category-name">${category.name}</div>
        <div class="category-desc">${category.description || '暂无描述'}</div>
        <div class="category-count">使用 ${category.count} 次</div>
        <div class="category-actions">
          <button class="category-btn category-btn-edit" onclick="editCategory(${category.id})">编辑</button>
          <button class="category-btn category-btn-delete" onclick="deleteCategory(${category.id})">删除</button>
        </div>
      `;

      list.appendChild(div);
    });
  }

  updateStats(stats) {
    document.getElementById('totalCategories').textContent = stats.total;
    document.getElementById('topCategory').textContent = stats.topCategory || '--';
  }

  handleCategorySubmit() {
    const formData = {
      name: document.getElementById('categoryName').value,
      color: document.getElementById('categoryColor').value,
      description: document.getElementById('categoryDesc').value
    };

    cordova.exec(
      (result) => {
        this.showSuccess('分类创建成功!');
        this.closeCategoryForm();
        this.loadCategories();
      },
      (error) => {
        this.showError('创建分类失败:' + error);
      },
      'CategoriesPlugin',
      'createCategory',
      [formData]
    );
  }

  showSuccess(message) {
    this.showToast(message, 'success');
  }

  showError(message) {
    this.showToast(message, 'error');
  }

  showToast(message, type) {
    const toast = document.createElement('div');
    toast.className = `toast toast-${type}`;
    toast.textContent = message;
    document.body.appendChild(toast);

    setTimeout(() => {
      toast.classList.add('show');
    }, 10);

    setTimeout(() => {
      toast.classList.remove('show');
      setTimeout(() => toast.remove(), 300);
    }, 3000);
  }
}

function openCategoryForm() {
  document.getElementById('categoryModal').classList.add('show');
}

function closeCategoryForm() {
  document.getElementById('categoryModal').classList.remove('show');
  document.getElementById('categoryForm').reset();
}

function editCategory(categoryId) {
  console.log('编辑分类:', categoryId);
}

function deleteCategory(categoryId) {
  if (confirm('确定要删除这个分类吗?')) {
    cordova.exec(
      () => {
        categoriesModule.loadCategories();
      },
      (error) => {
        console.error('删除分类失败:', error);
      },
      'CategoriesPlugin',
      'deleteCategory',
      [categoryId]
    );
  }
}

const categoriesModule = new CategoriesModule();

JavaScript 代码实现了分类的列表展示、创建、编辑、删除等功能。

🔌 原生代码实现

OpenHarmony 分类插件

// CategoriesPlugin.ets
export class CategoriesPlugin {
  private context: Context;

  constructor(context: Context) {
    this.context = context;
  }

  getCategories(callback: (data: any) => void): void {
    try {
      const db = this.getDatabase();
      const userId = this.getUserId();

      const categories = db.query(`
        SELECT id, name, color, description, 
               (SELECT COUNT(*) FROM blessings WHERE category_id = c.id) as count
        FROM categories c
        WHERE user_id = ?
        ORDER BY count DESC
      `, [userId]);

      const stats = {
        total: categories.length,
        topCategory: categories[0]?.name || null
      };

      callback({ categories, stats });
    } catch (error) {
      console.error('获取分类失败:', error);
      callback({ categories: [], stats: { total: 0, topCategory: null } });
    }
  }

  createCategory(categoryData: any, callback: (success: boolean, message: string) => void): void {
    try {
      const db = this.getDatabase();
      const userId = this.getUserId();

      // 检查分类名称是否重复
      const existing = db.query(
        'SELECT id FROM categories WHERE user_id = ? AND name = ?',
        [userId, categoryData.name]
      );

      if (existing.length > 0) {
        callback(false, '分类名称已存在');
        return;
      }

      const sql = `
        INSERT INTO categories (user_id, name, color, description, created_at)
        VALUES (?, ?, ?, ?, ?)
      `;

      db.insert('categories', [
        userId,
        categoryData.name,
        categoryData.color,
        categoryData.description || '',
        Date.now()
      ]);

      callback(true, '分类创建成功');
    } catch (error) {
      console.error('创建分类失败:', error);
      callback(false, error.message);
    }
  }

  deleteCategory(categoryId: number, callback: (success: boolean) => void): void {
    try {
      const db = this.getDatabase();
      db.execute('DELETE FROM categories WHERE id = ?', [categoryId]);
      callback(true);
    } catch (error) {
      console.error('删除分类失败:', error);
      callback(false);
    }
  }

  private getDatabase(): any {
    return null;
  }

  private getUserId(): string {
    return '';
  }
}

原生代码实现了分类的 CRUD 操作和统计功能。

📝 总结

福报分类模块提供了灵活的分类管理功能。通过 Cordova 与 OpenHarmony 的结合,实现了高效的分类系统。关键技术包括:分类创建与验证、使用次数统计、颜色管理等。这些技术的综合应用,为用户提供了一个清晰、易用的分类体验。

Logo

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

更多推荐