Interfaz de Usuario para Comparación de Respuestas y Retroalimentación en HarmonyOS PC con Electron

En aplicaciones de reconocimiento manuscrito, la normalización de texto es esencial para evitar errores de comparación. El texto devuelto por servicios de OCR a menudo contiene espacios, mayúsculas inconsistentes o caracteres especiales. Comparar directamente estos resultados con la respuesta correcta puede generar falsos negativos, afectando la experiencia del usuario. La normalización elimina estos artefactos antes de la comparación.

Implementación del método de normalización

/**
 * Normaliza el texto para comparación uniforme
 * @param entrada Texto original del OCR o respuesta correcta
 * @returns Texto normalizado
 */
private normalizarTexto(entrada: string): string {
  let procesado = entrada.trim();          // Eliminar espacios al inicio y final
  procesado = procesado.toLowerCase();     // Convertir a minúsculas
  procesado = procesado.replace(/[^a-z\u4e00-\u9fa5]/g, ''); // Filtrar caracteres no válidos
  return procesado;
}

La función realiza tres pasos: eliminación de espacios, conversión a minúsculas y filtrado de caracteres. La expresión regular conserva solo letras minúsculas y caracteres chinos, asegurando una base común para la comparación.

  1. Lógica de Verificación de Respuestas

Tras el reconocimiento, el sistema evalúa la respuesta en tres estados posibles: correcto, incorrecto o vacío. Cada estado tiene una retroalimentación visual específica.

Estados de verificación

Estado Condición Color Visualización
Correcto Texto normalizado coincide Verde (#5B8A4A) Icono de check + texto reconocido
Incorrecto Texto normalizado no coincide Rojo (#B5533C) Icono de error + texto reconocido + respuesta correcta
Vacío Texto reconocido vacío Amarillo (#C9A14A) Mansaje de advertencia

Implementación completa

@State mensajeFeedback: string = '';
@State colorFeedback: string = '#6B7280';
@State mostrarRespuesta: boolean = false;
@State textoReconocido: string = '';

private verificarRespuesta(textoOCR: string): void {
  if (!this.palabraActual) return;
  this.textoReconocido = textoOCR;

  const entradaUsuario = this.normalizarTexto(textoOCR);
  const respuestaCorrecta = this.normalizarTexto(this.palabraActual.ingles);

  if (entradaUsuario.length === 0) {
    this.mensajeFeedback = '⚠ Contenido no reconocido';
    this.colorFeedback = '#C9A14A';
    this.mostrarRespuesta = false;
  } else if (entradaUsuario === respuestaCorrecta) {
    this.mensajeFeedback = `✓ ${textoOCR}`;
    this.colorFeedback = '#5B8A4A';
    this.mostrarRespuesta = false;
  } else {
    this.mensajeFeedback = `✗ ${textoOCR}`;
    this.colorFeedback = '#B5533C';
    this.mostrarRespuesta = true;
  }
}

Esta lógica se invoca tras la acción de reconocimiento OCR, proporcionando retroalimentación inmediata basada en la comparación normalizada.

  1. Diseño de la Interfaz de Retroalimentación

La interfaz de retroalimentación se superpone al área de dibujo para mostrar resultados sin interferir con la interacción del usuario. Utiliza una capa flotante en la esquina superior izquierda con estilo semi-transparente.

Implementación de la capa de retroalimentación

if (this.mensajeFeedback.length > 0) {
  Column({ space: 4 }) {
    Text(this.mensajeFeedback)
      .fontSize(28)
      .fontColor(this.colorFeedback)
      .fontWeight(FontWeight.Bold)
      .maxLines(2)

    if (this.mostrarRespuesta && this.palabraActual) {
      Text(`Respuesta: ${this.palabraActual.ingles}`)
        .fontSize(20)
        .fontColor('#8B9D6B')
    }
  }
  .padding({ left: 16, right: 16, top: 12, bottom: 12 })
  .backgroundColor('#FFFFFFEE')
  .borderRadius(8)
  .margin({ left: 12, top: 12 })
  .hitTestBehavior(HitTestMode.Transparent)
}

El uso de hitTestBehavior(HitTestMode.Transparent) permite que los eventos táctiles pasen a la capa inferior, manteniendo la funcionalidad de escritura. La opacidad del fondo (#FFFFFFEE) asegura visibilidad sin obstruir completamente el contenido.

  1. Barra de Herramientas

La barra de herramientas se posiciona en la esquina superior derecha, combinando propiedades de posicionamiento para alineación precisa.

Posicionameinto en esquina

.position({ x: '100%', y: 0 })
.markAnchor({ x: '100%', y: 0 })

Esta configuración alinea el borde derecho del componente con el borde derecho del contenedor padre y el borde superior con el tope del contenedor.

Componentes de la barra

Row({ space: 10 }) {
  Toggle({ type: ToggleType.Switch, isOn: this.marcaAgua })
    .selectedColor('#8B9D6B')
    .onChange((activo: boolean) => { this.marcaAgua = activo; })

  Button('Rehacer')
    .onClick(() => { this.reiniciarCanvas(); })

  if (this.procesandoOCR) {
    LoadingProgress()
    Text('Procesando')
  } else {
    Button('Reconocer')
      .onClick(() => { this.ejecutarReconocimiento(); })
  }
}
.position({ x: '100%', y: 0 })
.markAnchor({ x: '100%', y: 0 })
.hitTestBehavior(HitTestMode.Transparent)

El estado procesandoOCR previene múltiples solicitudes OCR simultáneas mediante un indicador de carga visual.

  1. Gestión de Estados y Reinicio

El método reiniciarCanvas restablece tanto el lienzo de dibujo como los estados de retroalimentación al cambiar de palabra o por acción del usuario.

private reiniciarCanvas(): void {
  this.contextoCanvas.clearRect(0, 0, this.anchoCanvas, this.altoCanvas);
  this.configurarPincel();
  this.mensajeFeedback = '';
  this.colorFeedback = '#6B7280';
  this.mostrarRespuesta = false;
  this.textoReconocido = '';
  this.trazos = [];
}

Este enfoque garantiza que la interfaz parta de un estado limpio, evitando residuos visuales o estados inconsistentes.

  1. Sistema de Colores Semánticos

La aplicación utiliza una paleta de colores definida por significado para mantener coherencia visual y facilitar el mantenimiento.

const ColoresSistema = {
  exito: '#5B8A4A',       // Retroalimentación positiva
  error: '#B5533C',       // Errores
  advertencia: '#C9A14A', // Alertas
  info: '#6B7280',        // Texto secundario
  principal: '#8B9D6B',   // Tema principal
} as const;

Este sistema permite actualizaciones centralizadas del esquema de colores y mejora la legibilidad del código al usar nombres semánticos en lugar de valores hexadecimales.

  1. Solución a Problemas Comunes

La capa de retroalimentación no aparece: Verificar que mensajeFeedback se actualiza correctamente y que el componente está en la capa superior dentro del Stack.

Eventos táctiles no pasan al lienzo: Asegurar que hitTestBehavior(HitTestMode.Transparent) está aplicado al contenedor raíz de la capa flotante.

Clics múltiples en reconocimiento: Usar un estado booleano para bloquear la interacción durante el procesamiento, en lugar de deshabilitar el botón.

Etiquetas: HarmonyOS Electron TypeScript OCR ArkUI

Publicado el 6-2 16:50