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

📌 概述

编辑Bug模块允许用户修改已存在的Bug记录的各种信息。在Cordova与OpenHarmony混合开发框架下,这个模块需要从数据库中加载现有的Bug数据,然后提供一个表单让用户进行编辑。编辑Bug功能的设计目标是让用户能够快速、准确地更新Bug信息,同时保证数据的完整性和一致性。

编辑Bug模块采用了与添加Bug类似的表单设计,但增加了数据预填充和版本控制等功能。当用户修改Bug信息时,系统会记录修改历史,以便用户追踪Bug的变化。

🔗 完整流程

第一步:数据加载与预填充

当用户打开编辑Bug页面时,系统首先从IndexedDB数据库中加载指定Bug的数据。系统会根据URL或导航参数中的Bug ID来确定要编辑哪个Bug。加载完成后,系统会将Bug的各个字段值填充到表单中,让用户可以看到当前的值。

数据预填充包括标题、描述、优先级、分类、标签等所有可编辑的字段。系统还会加载分类列表和标签列表,用于填充下拉菜单和标签选择器。

第二步:表单验证与修改

用户可以在表单中修改Bug的各个字段。系统会在用户输入时进行实时验证,确保输入的数据符合要求。当用户修改了某个字段时,系统会记录这个修改,以便在保存时进行版本控制。

表单验证包括检查必填字段是否为空、检查输入长度是否符合要求等。验证结果会以视觉反馈的形式展示给用户。

第三步:数据保存与版本控制

当用户点击保存按钮时,系统会进行最终验证,然后将修改后的数据保存到数据库。同时,系统会创建一个修改记录,记录本次修改的内容、修改人、修改时间等信息。这样可以实现完整的版本控制,用户可以查看Bug的修改历史。

🔧 Web代码实现

HTML结构

<div id="edit-bug-page" class="page">
  <div class="page-header">
    <h1 class="page-title">编辑Bug</h1>
  </div>

  <div class="page-content">
    <form id="edit-bug-form" class="form">
      <!-- 标题字段 -->
      <div class="form-group">
        <label for="edit-bug-title" class="form-label">Bug标题 <span class="required">*</span></label>
        <input 
          type="text" 
          id="edit-bug-title" 
          class="form-input" 
          placeholder="请输入Bug标题"
          maxlength="100"
          required
        />
        <div class="form-error" id="edit-title-error"></div>
      </div>

      <!-- 描述字段 -->
      <div class="form-group">
        <label for="edit-bug-description" class="form-label">Bug描述 <span class="required">*</span></label>
        <textarea 
          id="edit-bug-description" 
          class="form-textarea" 
          placeholder="请详细描述Bug的现象和复现步骤"
          rows="6"
          required
        ></textarea>
        <div class="form-error" id="edit-description-error"></div>
      </div>

      <!-- 优先级字段 -->
      <div class="form-group">
        <label for="edit-bug-priority" class="form-label">优先级 <span class="required">*</span></label>
        <select id="edit-bug-priority" class="form-select" required>
          <option value="">请选择优先级</option>
          <option value="high"></option>
          <option value="medium"></option>
          <option value="low"></option>
        </select>
      </div>

      <!-- 状态字段 -->
      <div class="form-group">
        <label for="edit-bug-status" class="form-label">状态 <span class="required">*</span></label>
        <select id="edit-bug-status" class="form-select" required>
          <option value="pending">待处理</option>
          <option value="in-progress">处理中</option>
          <option value="resolved">已解决</option>
        </select>
      </div>

      <!-- 分类字段 -->
      <div class="form-group">
        <label for="edit-bug-category" class="form-label">分类 <span class="required">*</span></label>
        <select id="edit-bug-category" class="form-select" required>
          <option value="">请选择分类</option>
        </select>
      </div>

      <!-- 标签字段 -->
      <div class="form-group">
        <label for="edit-bug-tags" class="form-label">标签</label>
        <div id="edit-bug-tags" class="tag-input">
          <input 
            type="text" 
            class="tag-input-field" 
            placeholder="输入标签后按Enter添加"
            id="edit-tag-input-field"
          />
          <div id="edit-tag-list" class="tag-list"></div>
        </div>
      </div>

      <!-- 附加信息 -->
      <div class="form-group">
        <label for="edit-bug-attachment" class="form-label">附加信息</label>
        <textarea 
          id="edit-bug-attachment" 
          class="form-textarea" 
          placeholder="可选:添加日志、截图描述等附加信息"
          rows="4"
        ></textarea>
      </div>

      <!-- 修改说明 -->
      <div class="form-group">
        <label for="edit-change-notes" class="form-label">修改说明</label>
        <textarea 
          id="edit-change-notes" 
          class="form-textarea" 
          placeholder="说明本次修改的原因和内容"
          rows="3"
        ></textarea>
      </div>

      <!-- 提交按钮 -->
      <div class="form-actions">
        <button type="submit" class="btn btn-primary">保存修改</button>
        <button type="button" class="btn btn-default" onclick="app.navigateTo('bug-detail', editBugModule.bugId)">
          取消
        </button>
      </div>
    </form>
  </div>
</div>

HTML结构与添加Bug类似,但增加了状态字段和修改说明字段。状态字段允许用户在编辑时改变Bug的状态,修改说明字段用于记录本次修改的原因。

JavaScript逻辑

// 编辑Bug模块
class EditBugModule {
  constructor() {
    this.form = document.getElementById('edit-bug-form');
    this.bugId = null;
    this.bugData = null;
    this.tags = [];
    this.originalData = null;
    this.init();
  }

  async init() {
    // 从导航参数获取Bug ID
    this.bugId = window.currentBugId || this.getBugIdFromUrl();
    
    if (this.bugId) {
      await this.loadBugData();
      this.loadCategories();
      this.bindEvents();
    }
  }

  getBugIdFromUrl() {
    const params = new URLSearchParams(window.location.search);
    return params.get('id');
  }

  async loadBugData() {
    try {
      // 从数据库加载Bug数据
      this.bugData = await db.getBug(parseInt(this.bugId));
      
      if (!this.bugData) {
        utils.showError('Bug不存在');
        app.navigateTo('bug-list');
        return;
      }
      
      // 保存原始数据用于比较
      this.originalData = JSON.parse(JSON.stringify(this.bugData));
      
      // 预填充表单
      this.fillForm();
      
    } catch (error) {
      console.error('加载Bug数据失败:', error);
      utils.showError('加载Bug数据失败');
    }
  }

  fillForm() {
    document.getElementById('edit-bug-title').value = this.bugData.title;
    document.getElementById('edit-bug-description').value = this.bugData.description;
    document.getElementById('edit-bug-priority').value = this.bugData.priority;
    document.getElementById('edit-bug-status').value = this.bugData.status;
    document.getElementById('edit-bug-category').value = this.bugData.categoryId;
    document.getElementById('edit-bug-attachment').value = this.bugData.attachment || '';
    
    // 填充标签
    this.tags = this.bugData.tags || [];
    this.renderTags();
  }

  async loadCategories() {
    try {
      const categories = await db.getAllCategories();
      const categorySelect = document.getElementById('edit-bug-category');
      const options = categories.map(cat => 
        `<option value="${cat.id}">${utils.escapeHtml(cat.name)}</option>`
      ).join('');
      categorySelect.innerHTML = '<option value="">请选择分类</option>' + options;
      
      // 设置当前分类
      if (this.bugData) {
        categorySelect.value = this.bugData.categoryId;
      }
    } catch (error) {
      console.error('加载分类失败:', error);
    }
  }

  bindEvents() {
    // 表单提交事件
    this.form.addEventListener('submit', (e) => this.handleSubmit(e));
    
    // 标签输入事件
    const tagInput = document.getElementById('edit-tag-input-field');
    tagInput.addEventListener('keypress', (e) => this.handleTagInput(e));
    
    // 表单字段验证事件
    document.getElementById('edit-bug-title').addEventListener('change', () => 
      this.validateField('title')
    );
    document.getElementById('edit-bug-description').addEventListener('change', () => 
      this.validateField('description')
    );
  }

  handleTagInput(e) {
    if (e.key === 'Enter') {
      e.preventDefault();
      const input = e.target;
      const tag = input.value.trim();
      
      if (tag && !this.tags.includes(tag)) {
        this.tags.push(tag);
        this.renderTags();
        input.value = '';
      }
    }
  }

  renderTags() {
    const tagList = document.getElementById('edit-tag-list');
    const html = this.tags.map(tag => `
      <span class="tag">
        ${utils.escapeHtml(tag)}
        <button type="button" class="tag-remove" onclick="editBugModule.removeTag('${tag}')">×</button>
      </span>
    `).join('');
    tagList.innerHTML = html;
  }

  removeTag(tag) {
    this.tags = this.tags.filter(t => t !== tag);
    this.renderTags();
  }

  validateField(fieldName) {
    const errors = {};
    
    if (fieldName === 'title' || !fieldName) {
      const title = document.getElementById('edit-bug-title').value.trim();
      if (!title) {
        errors.title = '标题不能为空';
      } else if (title.length > 100) {
        errors.title = '标题长度不能超过100个字符';
      }
    }
    
    if (fieldName === 'description' || !fieldName) {
      const description = document.getElementById('edit-bug-description').value.trim();
      if (!description) {
        errors.description = '描述不能为空';
      } else if (description.length > 5000) {
        errors.description = '描述长度不能超过5000个字符';
      }
    }
    
    // 显示错误信息
    Object.keys(errors).forEach(key => {
      const errorElement = document.getElementById(`edit-${key}-error`);
      if (errorElement) {
        errorElement.textContent = errors[key];
      }
    });
    
    return Object.keys(errors).length === 0;
  }

  async handleSubmit(e) {
    e.preventDefault();
    
    // 验证表单
    if (!this.validateField()) {
      utils.showError('请填写所有必填字段');
      return;
    }
    
    // 收集修改后的数据
    const updatedData = {
      title: document.getElementById('edit-bug-title').value.trim(),
      description: document.getElementById('edit-bug-description').value.trim(),
      priority: document.getElementById('edit-bug-priority').value,
      status: document.getElementById('edit-bug-status').value,
      categoryId: parseInt(document.getElementById('edit-bug-category').value),
      tags: this.tags,
      attachment: document.getElementById('edit-bug-attachment').value.trim(),
      updatedDate: new Date().toISOString()
    };
    
    try {
      // 显示加载提示
      utils.showLoading('正在保存修改...');
      
      // 更新数据库
      await db.updateBug(this.bugId, updatedData);
      
      // 创建修改记录
      const changeRecord = {
        bugId: this.bugId,
        title: 'Bug信息修改',
        description: document.getElementById('edit-change-notes').value.trim() || '修改了Bug信息',
        changes: this.getChanges(updatedData),
        createdDate: new Date().toISOString()
      };
      
      await db.addChangeRecord(changeRecord);
      
      // 隐藏加载提示
      utils.hideLoading();
      
      // 显示成功提示
      utils.showSuccess('Bug已成功更新');
      
      // 跳转到Bug详情页面
      setTimeout(() => {
        app.navigateTo('bug-detail', this.bugId);
      }, 1000);
      
    } catch (error) {
      console.error('保存Bug失败:', error);
      utils.hideLoading();
      utils.showError('保存Bug失败: ' + error.message);
    }
  }

  getChanges(updatedData) {
    const changes = [];
    
    Object.keys(updatedData).forEach(key => {
      if (JSON.stringify(this.originalData[key]) !== JSON.stringify(updatedData[key])) {
        changes.push({
          field: key,
          oldValue: this.originalData[key],
          newValue: updatedData[key]
        });
      }
    });
    
    return changes;
  }
}

// 初始化编辑Bug模块
const editBugModule = new EditBugModule();

JavaScript代码实现了完整的编辑Bug功能,包括数据加载、表单预填充、验证、保存和版本控制。通过比较原始数据和修改后的数据,系统可以记录具体的修改内容。

CSS样式

编辑Bug页面的CSS样式与添加Bug页面相同,可以复用之前定义的样式。

🔌 OpenHarmony原生代码

// entry/src/main/ets/plugins/VersionControlPlugin.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
import { relationalStore } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';

const TAG: string = '[VersionControlPlugin]';
const DOMAIN: number = 0xFF00;

export class VersionControlPlugin {
  private static rdbStore: relationalStore.RdbStore;

  static async recordChange(success: Function, error: Function, args: any[]): Promise<void> {
    try {
      const bugId = args[0];
      const changes = args[1];
      const changeNotes = args[2];
      
      // 创建修改记录
      const changeRecord = {
        bugId: bugId,
        changes: JSON.stringify(changes),
        notes: changeNotes,
        timestamp: new Date().getTime()
      };
      
      // 保存到数据库
      hilog.info(DOMAIN, TAG, `修改记录已保存: Bug #${bugId}`);
      success('修改记录已保存');
    } catch (err) {
      hilog.error(DOMAIN, TAG, `保存修改记录失败: ${err}`);
      error('保存修改记录失败');
    }
  }

  static async getChangeHistory(success: Function, error: Function, args: any[]): Promise<void> {
    try {
      const bugId = args[0];
      
      // 从数据库查询修改历史
      const history = [
        {
          id: 1,
          bugId: bugId,
          changes: '修改了优先级',
          timestamp: new Date().getTime()
        }
      ];
      
      hilog.info(DOMAIN, TAG, `查询修改历史成功: ${history.length}`);
      success(history);
    } catch (err) {
      hilog.error(DOMAIN, TAG, `查询修改历史失败: ${err}`);
      error('查询修改历史失败');
    }
  }
}

Web-Native通信

// 版本控制通信类
class VersionControlBridge {
  static recordChange(bugId, changes, notes) {
    return new Promise((resolve, reject) => {
      if (window.cordova) {
        cordova.exec(
          (result) => {
            console.log('修改记录已保存:', result);
            resolve(result);
          },
          (error) => {
            console.error('保存修改记录失败:', error);
            reject(error);
          },
          'VersionControlPlugin',
          'recordChange',
          [bugId, changes, notes]
        );
      } else {
        reject('Cordova未加载');
      }
    });
  }

  static getChangeHistory(bugId) {
    return new Promise((resolve, reject) => {
      if (window.cordova) {
        cordova.exec(
          (history) => {
            console.log('修改历史:', history);
            resolve(history);
          },
          (error) => {
            console.error('查询修改历史失败:', error);
            reject(error);
          },
          'VersionControlPlugin',
          'getChangeHistory',
          [bugId]
        );
      } else {
        reject('Cordova未加载');
      }
    });
  }
}

📝 总结

编辑Bug模块是BugTracker Pro应用中用于修改Bug信息的重要功能。在Cordova与OpenHarmony混合开发框架下,它提供了完整的编辑功能和版本控制。通过记录修改历史,用户可以追踪Bug的变化,这对于团队协作和问题追踪非常重要。

模块采用了模块化的设计,各个功能都是独立的,易于维护和扩展。通过Cordova插件与原生代码的交互,我们可以实现更高效的数据管理和版本控制。这充分展示了混合开发框架的优势。

Logo

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

更多推荐