Дерево страниц

Сравнение версий

Ключ

  • Эта строка добавлена.
  • Эта строка удалена.
  • Изменено форматирование.
Комментарий: Написан текст статьи

...

Скачать архив с кодом проекта: pb-hello-world.rar

Шаг 1.

Добавьте подписку на события onAction() от диалогового сервиса. Это позволит переходить с экрана на экран с помощью голосовых команд. Сделать это нужно на следующих экранах:

  • VideoStream
  • AcquaintanceForm
  • MainMenu
  • Chat


Добавьте следующий текст в mounted() в defineComponent компонента VideoStream.

Блок кода
languagejs
this.$robot.dialogService.onAction(actions => {
  if (actions.find(action => action.toLowerCase() === 'next') && !this.disabled) {
    this.moveNext() // Имитирование нажатия кнопки Продолжить
  }
})


Добавьте следующий текст в mounted() в defineComponent компонента AcquaintanceForm.

Блок кода
languagejs
this.$robot.dialogService.onAction(actions => {
  if (actions.find(action => action.toLowerCase() === 'save_and_continue') && this.isNotEmptyName) {
    this.saveUser() // Имитирование нажатия кнопки Продолжить
  }
})


Добавьте следующий текст в mounted() в defineComponent компонента MainMenu.

Блок кода
languagejs
this.$robot.dialogService.onAction(actions => {
  if (actions.find(action => action.toLowerCase() === 'about-hotel')) {
    this.aboutHotel() // Имитирование нажатия кнопки Об отеле
  }

  if (actions.find(action => action.toLowerCase() === 'to-chat')) {
    this.toChat() // Имитирование нажатия кнопки Поболтать
  }

  if (actions.find(action => action.toLowerCase() === 'to-data')) {
    this.toData() // Имитирование нажатия кнопки Персональные данные
  }
})


Добавьте следующий текст в mounted() в defineComponent компонента Header.

Блок кода
languagejs
this.$robot.dialogService.onAction(actions => {
  if (actions.find(action => action.toLowerCase() === 'back')) {
    this.$router.back() // Имитирование нажатия кнопки Назад на экране Поболтать
  }
})

Шаг 2.

Добавьте компонент-обертку. Создайте файл VoiceInput.vue в папке components.

Шаг 3.

Добавьте div с pb-input в VoiceInput.vue. Укажите ссылку ref, она понадобится позже. Добавьте input-options и mask-options, а также двустороннее связывание через modelValue. Добавьте кнопку Микрофон, которая позволит включать голосовой способ ввода для поля (компонент pb-icon-button с SVG-картинкой). Для этого замените содержимое файла VoiceInput.vue на следующий текст.

Блок кода
languagejs
<template>
  <div class="voice-input">
    <pb-input
      ref="input-wrap"
      :input-options="inputOptions"
      :mask-options="maskOptions"
      @accept="$emit('update:modelValue', $event.target.value)"
      :modelValue="modelValue"
    />

    <pb-icon-button>
      <svg width="14" height="20" viewBox="0 0 14 20" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M3.33337 3.5C3.33337 1.567 4.90038 0 6.83337 0V0C8.76637 0 10.3334 1.567 10.3334 3.5V9.5C10.3334 11.433 8.76637 13 6.83337 13V13C4.90038 13 3.33337 11.433 3.33337 9.5V3.5Z" fill="#2D68FF"/>
        <path d="M0.833374 9V9.5C0.833374 12.8137 3.51967 15.5 6.83337 15.5V15.5C10.1471 15.5 12.8334 12.8137 12.8334 9.5V9" stroke="#2D68FF"/>
        <path d="M6.83337 15.5V20" stroke="#2D68FF"/>
        <path d="M4.33337 19.5H9.33337" stroke="#2D68FF"/>
      </svg>
    </pb-icon-button>
  </div>

</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'

export default defineComponent({
  name: 'VoiceInput',
})
</script>

<style lang="scss" scoped>

</style>

Шаг 4.

Задайте кнопке Микрофон (pb-icon-button) необходимые классы: статичный класс от voice-input и динамический класс, который будет отвечать за анимацию прослушивания. Добавьте реакцию на клик — метод toggleListen, логику которого мы реализуем позднее. Для этого замените тег <pb-icon-button> файла VoiceInput.vue на следующий текст.

Блок кода
languagejs
<pb-icon-button
  :class="['voice-input__icon _transparent', { '_animated': isListening }]"
  @click="toggleListen"
>

Шаг 5.

Заполните props. Укажите modelValue, inputOptions, maskOptions. Для этого добавьте следующий текст в defineComponent компонента VoiceInput.

Блок кода
languagejs
props: {
  modelValue: [String, Number],
  inputOptions: {
    type: Object as PropType<InputTextareaOptions>,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    default: () => {}
  },
  maskOptions: {
    type: Object as PropType<MaskOptions>,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    default: () => {}
  }
}

Шаг 6.

Добавьте импорт для inputOptions и maskOptions. Для этого добавьте следующий текст в <script> </script> файла VoiceInput.vue.

Блок кода
languagejs
import { InputTextareaOptions, MaskOptions } from '@pb/ui-kit/src/components/input/inputTextareaMixin'

Шаг 7.

Заполните data(), которая будет возвращать inputElement и isListening. inputElement потребуется для фокусирования и вставки текста непосредственно в компонент. Для этого добавьте следующий текст в defineComponent компонента VoiceInput.

Блок кода
languagejs
data (): { inputElement: null | HTMLInputElement, isListening: boolean } {
  return {
    inputElement: null,
    isListening: false
  }
}

Шаг 8.

Реализуйте метод toggleListen(), который позволит включать голосовой ввод для поля (обработчик кнопки Микрофон). Первым делом в теле метода происходит проверка, включен или выключен бесшумный режим. Если включен, то вызывается метод muteOff(), иначе — muteOn(). Это нужно для того, чтобы во время вставки текста в input'ы, не срабатывали userAction'ы. В конце метода isListening меняется на противоположное ему значение. Добавьте следующий текст в methods в defineComponent компонента VoiceInput.

Блок кода
languagejs
toggleListen (): void {
  this.$robot.dialogService.isMute
    ? this.$robot.dialogService.muteOff()
    : this.$robot.dialogService.muteOn()

  this.isListening = !this.isListening
}

Шаг 9.

Заполните mounted(). Для этого добавьте следующий текст в mounted в defineComponent компонента VoiceInput.

Блок кода
languagejs
this.inputElement = this.$el.querySelector('input')

this.$robot.dialogService.onUserReplic((text, isFinished) => {
  if (this.isListening && isFinished) {
    (this.inputElement as HTMLInputElement).focus();
    (this.inputElement as HTMLInputElement).value = text; // Текст из лингвобазы
    (this.inputElement as HTMLInputElement).blur()

    // Если тихий режим выключать сразу, то сработают userAction'ы, поэтому используем таймаут.
    setTimeout(() => {
      this.toggleListen()
    }, TIMEOUT_FOR_MUTE_OFF) 
  }
})

Шаг 10.

Задайте значение константы TIMEOUT_FOR_MUTE_OFF. Для этого добавьте следующий текст в <script> </script> файла VoiceInput.vue.

Блок кода
languagejs
const TIMEOUT_FOR_MUTE_OFF = 500

Шаг 11.

Добавьте watch. Для этого добавьте следующий текст в defineComponent компонента VoiceInput.

Блок кода
languagejs
watch: {
  isListening (newValue) {
    if (newValue) {
      (this.inputElement as HTMLInputElement).focus()
    }
  }
}

Шаг 12.

Добавьте стили для voice-input. Для этого добавьте следующий текст в <style lang="scss" scoped> </style> файла VoiceInput.vue.

Блок кода
languagejs
.voice-input {
  position: relative;

  &__icon {
    position: absolute;
    right: 0;

    &._animated {
      animation: pulse 1.5s linear infinite;

      border-radius: 50%;
      box-shadow: 0 0 0 0 #2D68FF;
      filter: invert(30%) sepia(100%) saturate(1265%) hue-rotate(209deg) brightness(101%) contrast(109%);
    }
  }
}

Шаг 13.

Добавьте стили для анимации кнопки Микрофон через @keyframes. Для этого добавьте следующий текст в <style lang="scss" scoped> </style> файла VoiceInput.vue.

Блок кода
languagejs
@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 #2D68FF;
  }
  70% {
    box-shadow: 0 0 0 3px rgba(45, 104, 255, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(45, 104, 255, 0);
  }
}

Шаг 14.

Добавьте VoiceInput в список компонентов — components в defineComponent компонента DataEntry в файле DataEntry.vue. Сверьтесь со списком ниже.

Блок кода
languagejs
collapsetrue
components: {
  Header,
  Modal,
  VoiceInput
}

Шаг 15.

Замените pb-input на VoiceInput в div в файле DataEntry.vue. Сверьтесь с текстом ниже.

Блок кода
languagejs
collapsetrue
<div class="data-entry__input-wrapper">
  <VoiceInput
    v-model="name"
    :input-options="{
      label: 'Фамилия'
    }"
    :mask-options="{
      type: 'text'
    }"
  />
  <VoiceInput
    v-model="name"
    :input-options="{
      label: 'Имя'
    }"
    :mask-options="{
      type: 'text'
    }"
  />
  <VoiceInput
    v-model="patronymic"
    :input-options="{
      label: 'Отчество'
    }"
    :mask-options="{
      type: 'text'
    }"
  />
</div>

Шаг 16.

Добавьте голосовое управление кнопкой Продолжить и ссылкой на модальное окно Персональные данные в файле DataEntry.vue. Для этого добавьте следующий текст в mounted в defineComponent компонента DataEntry.

Блок кода
languagejs
this.$robot.dialogService.onAction(actions => {
  if (actions.find(action => action.toLowerCase() === 'confirm') && this.isNotEmptyFields) {
    this.confirm()
  }

  if (actions.find(action => action.toLowerCase() === 'open-modal') && !this.isShowModal) {
    this.isShowModal = true
  }

  if (actions.find(action => action.toLowerCase() === 'close-modal') && this.isShowModal) {
    this.isShowModal = false
  }
})

Шаг 17.

Добавьте голосовое управление кнопкой На главную в файле SuccessScreen.vue. Для этого добавьте следующий текст в mounted() в defineComponent компонента SuccessScreen.

Блок кода
languagejs
this.$robot.dialogService.onAction(actions => {
  if (actions.find(action => action.toLowerCase() === 'to-main')) {
    this.$router.push('/')
  }
})