guhongwei 4 роки тому
батько
коміт
f4d1c092a8

+ 5 - 0
package-lock.json

@@ -1130,6 +1130,11 @@
       "integrity": "sha1-YjqkBiNVDjuUdnz/6wlqb7WX7Qk=",
       "dev": true
     },
+    "@stomp/stompjs": {
+      "version": "5.4.4",
+      "resolved": "https://registry.npm.taobao.org/@stomp/stompjs/download/@stomp/stompjs-5.4.4.tgz",
+      "integrity": "sha1-9R0u35oA+sZF3eOklHONlsoX5ao="
+    },
     "@types/color-name": {
       "version": "1.1.1",
       "resolved": "https://registry.npm.taobao.org/@types/color-name/download/@types/color-name-1.1.1.tgz",

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@stomp/stompjs": "^5.4.4",
     "axios": "^0.19.2",
     "core-js": "^3.6.4",
     "element-ui": "^2.13.2",

+ 223 - 0
src/components/parts/chat.vue

@@ -0,0 +1,223 @@
+<template>
+  <div id="chat">
+    <el-row class="chat">
+      <div class="chatList">
+        <ul>
+          <li v-for="(i, index) in list" :key="index">
+            <p>
+              <span>[{{ i.send_time | getTime }}]</span><span style="font-weight: bold;">{{ i.sender_name }}:</span>
+              <span> {{ i.content }}</span>
+            </p>
+          </li>
+        </ul>
+        <el-row type="flex" :gutter="10" style="padding-top:20px;height:40px;line-height:40px">
+          <el-col :span="20">
+            <el-input v-model="text" size="mini"></el-input>
+          </el-col>
+          <el-col :span="4">
+            <el-button @click="send" size="mini" round style="background: #ff8500;color: #fff;">发送</el-button>
+          </el-col>
+        </el-row>
+      </div>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: chat } = createNamespacedHelpers('chat');
+var moment = require('moment');
+export default {
+  name: 'chat',
+  props: {},
+  components: {},
+  data: () => {
+    return {
+      list: [],
+      text: '',
+    };
+  },
+  created() {
+    //回车事件
+    // this.enterListen();
+    this.search();
+  },
+  mounted() {
+    this.channel();
+  },
+  methods: {
+    ...chat(['query', 'create']),
+    async search() {
+      const res = await this.query({ skip: 0, limit: 10 });
+      if (this.$checkRes(res)) this.$set(this, `list`, _.reverse(res.data));
+    },
+    async send() {
+      if (!this.user.uid) {
+        this.$message.error('游客不能发言,请先注册');
+        return;
+      }
+      if (this.text != '') {
+        let object = { sender_name: this.user.name, content: this.text };
+        if (this.user.uid) object.sender_id = this.user.uid;
+        //TODO接口
+        let res = await this.create(object);
+        this.$checkRes(res, null, res.errmsg || '发言失败');
+      } else this.$message.error('请输入信息后发送');
+    },
+    channel() {
+      console.log('in function:');
+      this.$stomp({
+        [`/exchange/public_chat`]: this.onMessage,
+      });
+    },
+    onMessage(message) {
+      // console.log('receive a message: ', message.body);
+      let body = _.get(message, 'body');
+      if (body) {
+        body = JSON.parse(body);
+        this.list.push(body);
+        this.text = '';
+      }
+      // const { content, contenttype, sendid, sendname, icon, groupid, sendtime, type } = message.headers;
+      // let object = { content, contenttype, sendid, sendname, icon, groupid, sendtime, type };
+      // this.list.push(object);
+    },
+    enterListen() {
+      var lett = this;
+      document.onkeydown = function(e) {
+        var key = window.event.keyCode;
+        if (key == 13) {
+          lett.send();
+        }
+      };
+    },
+  },
+  filters: {
+    getTime(date) {
+      if (!date) return '很久以前';
+      let today = moment().format('YYYY-MM-DD');
+      let dd = moment(date).format('YYYY-MM-DD');
+      let time;
+      if (today == dd) time = moment(date).format('HH:mm:ss');
+      else time = moment(date).format('YYYY-MM-DD HH:mm:ss');
+      return time;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    pageTitle() {
+      return `${this.$route.meta.title}`;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.chat {
+  float: left;
+  width: 100%;
+  height: 515px;
+  border-radius: 5px;
+  box-shadow: 0 0 5px #c20808;
+  padding: 0 10px 0px 10px;
+  margin: 4px 0px 0 3px;
+}
+
+.chat .luyanTop {
+  height: 30px;
+  line-height: 30px;
+}
+
+.chat .luyanTop span:first-child {
+  display: inline-block;
+  padding: 0 10px;
+  height: 30px;
+  color: #fff;
+  background-color: #ff8500;
+  border-bottom-left-radius: 10px;
+  border-bottom-right-radius: 10px;
+}
+
+.chat .luyanTop .icon {
+  float: right;
+  background: #f2f4f5;
+  border-radius: 20px;
+  color: #666;
+  padding: 0 5px;
+  margin: 0 0 0 5px;
+}
+
+.chat .luyanTop .icon {
+  cursor: pointer;
+}
+
+.chat .chatList {
+  background: #fff;
+  float: left;
+  width: 100%;
+  height: 480px;
+  overflow: hidden;
+}
+
+.chat .chatList ul {
+  float: left;
+  width: 100%;
+  height: 405px;
+  padding: 5px 0 0 0;
+  overflow: auto;
+  margin: 10px 0 0 0;
+}
+
+.chat .chatList ul li {
+  padding: 0 10px;
+  margin: 0 0 5px 0;
+}
+
+.chat .chatList ul li span:first-child {
+  color: #666;
+  padding: 0 5px 0 0;
+}
+
+.chat .chatList .input {
+  height: 40px;
+  line-height: 40px;
+  float: left;
+  width: 100%;
+}
+
+.chat .chatList .input input[data-v-5189f7b7] {
+  border: 1px solid #ccc;
+  float: left;
+  height: 33px;
+  width: 75%;
+  margin: 19px 3% 0 0;
+}
+.chat .chatList .input button {
+  float: left;
+  background: #ff8500;
+  color: #fff;
+  height: 34px;
+  width: 21%;
+  max-width: 109px;
+  border-radius: 5px;
+}
+.jiabinlist ul {
+  margin: 0;
+  padding: 0;
+}
+
+.anniu {
+  float: left;
+  background: #ff8500;
+  color: #fff;
+  height: 34px;
+  width: 21%;
+  max-width: 109px;
+  margin: 20px 0 0 0;
+  border-radius: 5px;
+}
+</style>

+ 39 - 0
src/store/chat.js

@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  interface: `/api/live/chat`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit = undefined, ...info } = {}) {
+    const res = await this.$axios.$get(api.interface, { skip, limit, ...info });
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.interface}`, payload);
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.interface}/${payload}`);
+    return res;
+  },
+  async update({ commit }, { id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.interface}/${id}`, { ...info });
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.interface}/${payload}`);
+    return res;
+  },
+};
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 2 - 0
src/store/index.js

@@ -18,6 +18,7 @@ import place from './place';
 import onliveUser from './onlive/user';
 import gensign from './onlive/gensign';
 import room from './onlive/room';
+import chat from './chat';
 import * as ustate from '@/store/common/state';
 import * as umutations from '@/store/common/mutations';
 
@@ -47,5 +48,6 @@ export default new Vuex.Store({
     onliveUser,
     room,
     gensign,
+    chat,
   },
 });

+ 7 - 3
src/views/live/parts/videoDetail.vue

@@ -8,7 +8,7 @@
           </video>
         </el-col>
         <el-col :span="24" class="chat">
-          <el-col :span="24" class="chatList">
+          <!-- <el-col :span="24" class="chatList">
             聊天列表
           </el-col>
           <el-col :span="24" class="chatInput">
@@ -18,7 +18,8 @@
             <el-col :span="5" class="btn">
               <el-button type="primary" size="mini" @click="onSubmit">发送</el-button>
             </el-col>
-          </el-col>
+          </el-col> -->
+          <chat></chat>
         </el-col>
       </el-col>
     </el-row>
@@ -28,10 +29,13 @@
 <script>
 import { mapState, createNamespacedHelpers } from 'vuex';
 const { mapActions: dock } = createNamespacedHelpers('dock');
+import chat from '@/components/parts/chat.vue';
 export default {
   name: 'videoDetail',
   props: {},
-  components: {},
+  components: {
+    chat,
+  },
   data: function() {
     return {
       input: '',