仿金山打字效果

^Mao^發表於2024-04-10

背景

需要校驗使用者輸入的內容和我們要求的內容保持一致,比如:籤合同的時候需要使用者根據我們的內容進行手抄

效果圖

實現程式碼

<template>
  <div class="app">
    <h1>
      功能1:根據輸入的內容去匹配正文,輸入的內容顯示在"輸入內容"中,如果匹配正確的話則使用綠色標識,錯誤的的話使用紅色標識
    </h1>
    <h3>《荷塘月色》</h3>
    <p>{{ original_content }}</p>
    <hr />
    輸入內容:
    <p v-html="content"></p>
    <hr />
    <el-input
      :autosize="{ minRows: 2 }"
      type="textarea"
      :rows="2"
      placeholder="請輸入內容"
      v-model="input_content"
      @input="handleInputContent"
    >
    </el-input>

    <h1>
      功能2:根據輸入的內容去匹配正文,如果匹配正確的話則直接在正文中使用綠色標識,錯誤的的話直接在正文中使用紅色標識
    </h1>
    <h3>《荷塘月色》</h3>
    <p v-html="content_2" ref="p_ref"></p>
    <hr />
    <el-input
      :autosize="{ minRows: 2 }"
      type="textarea"
      :rows="2"
      placeholder="請輸入內容"
      v-model="input_content_2"
      @input="handleInputContent_2"
    >
    </el-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      original_content:
        '路上只我一個人,揹著手踱著。這一片天地好像是我的;我也像超出了平常旳自己,到了另一世界裡。我愛熱鬧,也愛冷靜;愛群居,也愛獨處。像今晚上,一個人在這蒼茫旳月下,什麼都可以想,什麼都可以不想,便覺是個自由的人。白天裡一定要做的事,一定要說的話,現在都可不理。這是獨處的妙處,我且受用這無邊的荷香月色好了。',

      content: '',
      input_content: '',

      original_content_2:
        '路上只我一個人,揹著手踱著。這一片天地好像是我的;我也像超出了平常旳自己,到了另一世界裡。我愛熱鬧,也愛冷靜;愛群居,也愛獨處。像今晚上,一個人在這蒼茫旳月下,什麼都可以想,什麼都可以不想,便覺是個自由的人。白天裡一定要做的事,一定要說的話,現在都可不理。這是獨處的妙處,我且受用這無邊的荷香月色好了。',
      content_2:
        '路上只我一個人,揹著手踱著。這一片天地好像是我的;我也像超出了平常旳自己,到了另一世界裡。我愛熱鬧,也愛冷靜;愛群居,也愛獨處。像今晚上,一個人在這蒼茫旳月下,什麼都可以想,什麼都可以不想,便覺是個自由的人。白天裡一定要做的事,一定要說的話,現在都可不理。這是獨處的妙處,我且受用這無邊的荷香月色好了。',
      input_content_2: '',
    }
  },
  methods: {
    handleInputContent(value) {
      // 解決輸入特殊字元後出現問題,要手動轉義
      value = value
        .replaceAll('.', '\\.')
        .replaceAll('^', '\\^')
        .replaceAll('$', '\\$')
        .replaceAll('*', '\\\\*')
        .replaceAll('+', '\\+')
        .replaceAll('?', '\\\\?')
        .replaceAll('\\', '\\\\')
        .replaceAll('|', '\\|')
        .replaceAll('[', '\\[')
        .replaceAll(']', '\\]')
        .replaceAll('{', '\\{')
        .replaceAll('}', '\\}')
        .replaceAll(';', '\\\\;')

      const reg = new RegExp(value)
      const match_result = reg.test(this.original_content)
      const str_length = value.length

      if (match_result) {
        this.content =
          "<span class='right'>" +
          this.original_content.substring(0, str_length) +
          '</span>'
        this.original_content.slice(str_length - 1)
      } else {
        // 記錄此次需要匹配的原始內容
        let original_content_search_str = this.original_content.substring(
          0,
          str_length
        )
        let match_index = 0
        for (let i = 1; i <= value.length; i++) {
          const search_str = value.slice(0, i)
          if (original_content_search_str.includes(search_str)) {
            match_index = i
          } else {
            match_index = i - 1
            break
          }
        }

        this.content =
          "<span class='right'>" +
          value.substring(0, match_index) +
          "</span><span class='error'>" +
          value.substring(match_index) +
          '</span>'
      }
    },
    handleInputContent_2(value) {
      // 解決輸入特殊字元後出現問題,要手動轉義
      value = value
        .replaceAll('.', '\\.')
        .replaceAll('^', '\\^')
        .replaceAll('$', '\\$')
        .replaceAll('*', '\\\\*')
        .replaceAll('+', '\\+')
        .replaceAll('?', '\\\\?')
        .replaceAll('\\', '\\\\')
        .replaceAll('|', '\\|')
        .replaceAll('[', '\\[')
        .replaceAll(']', '\\]')
        .replaceAll('{', '\\{')
        .replaceAll('}', '\\}')
        .replaceAll(';', '\\\\;')

      const reg = new RegExp(value)
      const match_result = reg.test(this.original_content_2)
      const str_length = value.length

      if (match_result) {
        this.content_2 =
          "<span class='right'>" +
          this.original_content_2.substring(0, str_length) +
          '</span>' +
          this.original_content_2.substring(str_length)
      } else {
        const right_el = this.$refs.p_ref.querySelector('.right')
        if (right_el) {
          const right_length = right_el.textContent.length
          this.content_2 =
            "<span class='right'>" +
            this.original_content_2.substring(0, right_length) +
            '</span>' +
            "<span class='error'>" +
            this.original_content_2.substring(right_length, str_length) +
            '</span>' +
            this.original_content_2.substring(str_length)
        } else {
          this.content_2 =
            "<span class='error'>" +
            this.original_content_2.substring(
              0,
              this.original_content_2.length
            ) +
            '</span>'
        }
      }
    },
  },
}
</script>

<style lang="less" scoped>
// /deep/.error {
//   color: #f00 !important;
// }
/deep/.right {
  color: #2e8b57;
}
/deep/.error {
  color: #f00;
}
</style>

相關文章