Vue.js & vuex 通过服务器端事件处理短信

Vue.js & vuex handling SMS by server-side-events

我有一个应用程序,它基本上是一个呼叫中心。您可以接听电话,打电话给某人,接收短信和发送短信等。我在屏幕上显示我的短信时遇到问题,当我从后端接收事件时,我在屏幕上使用 vuex 和 V-for 显示特定组件的数据.问题是当我从后端收到另一个不同号码的事件时,我想在第一条短信下显示它,但它会覆盖第一条短信并只显示那条新短信。我尝试了多种方法,但没有任何效果,所以我希望有人能够指出我的错误。

这是带有一条短信的屏幕照片(红色框是第二条短信应该带有自己的信息,例如号码...的地方)..

这是我接收事件的代码。

export default function setupStream(){
    let evtSource = new EventSource('/hzs/events.sse');
    evtSource.addEventListener('receive_sms', event => {
      let sms_data = JSON.parse(event.data);
      store.dispatch('receiveSMS', sms_data);
    }, false)
}

这是我的 vuex 代码

const state = {
    sms: [],
};

const getters = {
    getSMS: (state) => state.sms,
};

const actions = {
    receiveSMS({ commit }, sms_data) {
        commit('setSMS', sms_data);
    },
};

const mutations = {
    setSMS: (state, sms) => (state.sms = sms),
};

export default {
    state,
    getters,
    actions,
    mutations
}

这里是组件。

<template>
      <v-card>
        <v-card-title class="primary white--text">
          {{ $t("Communication") }}
        </v-card-title>
        <v-card d-flex flex-column height="100%" class="card-outter scroll">
          <v-col>
            <div v-for="sms in getSMS" :key="sms.id">
            <v-card-actions>
              <v-row>
                    <v-btn @click="openChat" icon class="mt-4"
                      ><v-img
                        max-width="30px"
                        max-height="30px"
                        class="mt-2"
                        src="@/assets/icons/icon-sms.svg"
                        alt="icon-sms"
                    /></v-btn>
                <v-col>
                  <span>{{sms.date_time}}</span> <br />
                  <h4>{{sms.sender}}</h4>
                  
                    <!-- Dialog for Adding new Note -->
                    <v-dialog
                      v-model="showEditor"
                      max-width="400px"
                      persistent
                      scrollable
                    >
                      <template v-slot:activator="{ on, attrs }">
                        <v-btn
                          @click="showEditor = true"
                          depressed
                          small
                          v-bind="attrs"
                          v-on="on"
                          >{{$t("Add Note")}}</v-btn
                        >
                      </template>
                      <AddNoteDialog v-on:close-card="showEditor = false"
                    /></v-dialog>
                  
                </v-col>
                <v-spacer></v-spacer>
                <v-btn class="mt-5" icon @click="deleteCommunication"
                  ><v-img
                    max-width="20px"
                    src="@/assets/icons/icon-delete.svg"
                    alt="icon-delete"
                /></v-btn>
              </v-row>
            </v-card-actions>
            <v-divider></v-divider>
            </div>
            <v-spacer></v-spacer>
            <v-divider></v-divider>
            <v-card-actions class="card-actions">
              <v-row>
                <v-text-field
                  class="ml-4"
                  color="primary white--text"
                  required
                  :label="$t('Mobile number')"
                  clearable
                ></v-text-field>
                <v-dialog
                      v-model="showEditor1"
                      max-width="450px"
                      persistent
                      scrollable
                    >
                      <template v-slot:activator="{ on, attrs }">
                        <v-btn
                          @click="showEditor1 = true"
                          class="mt-5 mr-4"
                          depressed
                          icon
                          v-bind="attrs"
                          v-on="on"
                          ><v-icon>mdi-plus-circle</v-icon></v-btn
                        >
                      </template>
                      <AddNummberDialog v-on:close-card="showEditor1 = false"
                    /></v-dialog>  
              </v-row>
            </v-card-actions>
          </v-col>
        </v-card>
      </v-card>
</template>

<script>
import AddNoteDialog from "@/components/UI/AddNoteDialog";
import AddNummberDialog from "@/components/UI/AddNummberDialog";
import { mapGetters, mapActions } from 'vuex';

export default {
  name: "Communication",
  data() {
    return {
      dialog: false,
      showEditor: false,
      showEditor1: false,
      note: '',
      chat: this.switchChat,
    };
  },
  computed: {
    ...mapGetters(['getSMS']),
  },
  components: { AddNoteDialog, AddNummberDialog },
  props: ["switchChat"],
  methods: {
    ...mapActions(['setupEvents']),
    openChat() {
      this.$emit('openChat')
    },
    async deleteCommunication() {
      alert("Deleted");
    },
  },
};
</script>

<style>
.scroll {
  overflow-y: scroll;
}
.card-outter {
  padding-bottom: 50px;
}
.card-actions {
  position: absolute;
  bottom: 0;
  width: 100%;
}


</style>


我认为解决方案是创建新数组,我将在其中存储我收到的每条短信。问题是我不知道如何以及在哪里做。

您已经有了名为 sms 的 vue 状态数组,这是一个好的开始。你需要更新你的 Vuex 以获得一个名为“addNewSMS”或其他东西的额外突变:

const mutations = {
    setSMS: (state, sms) => (state.sms = sms),
    addNewSMS: (state, newSMS) => state.sms.push(newSMS),
};

这将更新您的 state.sms 数组以包含多个元素,您应该能够在模板中使用 v-for 循环遍历这些元素。

当然,您还需要像这样更新您的操作:

const actions = {
    receiveSMS({ commit }, sms_data) {
        commit('addNewSMS', sms_data);
    },
};

作为旁注,我个人将 sms 变量名称更改为 messages,以便您和其他编码人员更清楚它包含多个对象。