lrf402788946 4 gadi atpakaļ
vecāks
revīzija
1c96b80c54

+ 2 - 0
src/store/index.js

@@ -10,6 +10,7 @@ import column from './live/column';
 import news from './live/news';
 // 培训问诊
 import trainlive from './live/trainlive';
+import trainchat from './live/trainchat';
 // 项目路演
 import newsroadshow from './live/newsroadshow';
 import newsguidance from './live/newsguidance';
@@ -64,6 +65,7 @@ export default new Vuex.Store({
     newsroadshow,
     // 培训问诊
     trainlive,
+    trainchat,
     // 科技超市
     product,
     exportuser,

+ 39 - 0
src/store/live/trainchat.js

@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+Vue.use(Vuex);
+const api = {
+  interface: `/api/live/trainchat`,
+};
+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,
+};

+ 117 - 4
src/views/live/detail/jnpxDetail.vue

@@ -1,26 +1,80 @@
 <template>
   <div id="jnpxDetail">
     <el-row>
-      <el-col :span="24">
-        <p>jnpxDetail</p>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="video">
+          <el-col :span="24" class="top">
+            <!-- 直播 -->
+            <!-- <video id="videoElement" controls class="h5video"></video> -->
+            <!-- 视频播放 -->
+            <video
+              autoplay="autoplay"
+              controls="controls"
+              preload="meta"
+              x-webkit-airplay="true"
+              webkit-playsinline="true"
+              playsinline="true"
+              x5-video-player-type="h5"
+              x5-video-player-fullscreen="true"
+              :src="videoPath"
+              v-if="videoData.length > 0"
+              loop="loop"
+            >
+              <source src="movie.ogg" type="video/ogg" />
+              <source src="movie.mp4" type="video/mp4" />
+            </video>
+            <p v-else>{{ info.title }}</p>
+          </el-col>
+          <el-col :span="24" class="down">
+            <el-button type="primary" size="mini" @click="back()">返回列表</el-button>
+            <el-button type="primary" size="mini" @click="showPopup()">选择视频</el-button>
+          </el-col>
+        </el-col>
+      </el-col>
+      <el-col :span="24" class="imgchat">
+        <van-tabs v-model="active">
+          <van-tab title="公共聊天">
+            <dockchat></dockchat>
+          </van-tab>
+        </van-tabs>
       </el-col>
     </el-row>
+    <van-popup v-model="show" position="bottom">
+      <van-picker
+        title="视频信息"
+        v-model="show"
+        show-toolbar
+        :columns="videoData"
+        @confirm="onConfirm"
+        @cancel="onCancel"
+        @change="onChange"
+        value-key="videointro"
+      />
+    </van-popup>
   </div>
 </template>
 
 <script>
 import { mapState, createNamespacedHelpers } from 'vuex';
 const { mapActions: trainlive } = createNamespacedHelpers('trainlive');
+// 公共聊天
+import dockchat from '../liveParts/trainchat.vue';
 export default {
   metaInfo() {
     return { title: this.$route.meta.title };
   },
   name: 'jnpxDetail',
   props: {},
-  components: {},
+  components: {
+    dockchat,
+  },
   data: function() {
     return {
       info: {},
+      videoPath: '',
+      videoData: [],
+      show: false,
+      active: 0,
     };
   },
   created() {
@@ -28,6 +82,31 @@ export default {
   },
   methods: {
     ...trainlive(['fetch']),
+    back() {
+      this.$router.push({ path: '/live/index' });
+    },
+    showPopup() {
+      this.show = true;
+    },
+    // 选择视频
+    changeMenu(index, value) {
+      const item = this.info.video_data[index];
+      if (item) {
+        this.$set(this, `videoPath`, item.video_url);
+      }
+    },
+    // 确定选择
+    onConfirm(value, index) {
+      this.changeMenu(index, value);
+      this.onCancel();
+    },
+    onChange(value, index) {
+      this.changeMenu(index, value);
+    },
+    // 取消
+    onCancel() {
+      this.show = false;
+    },
     async search() {
       if (!this.id) {
         this.$toast.fail('缺少必要信息,加载数据失败!');
@@ -36,6 +115,12 @@ export default {
       const res = await this.fetch(this.id);
       if (this.$checkRes(res)) {
         this.$set(this, 'info', res.data);
+        this.$set(
+          this,
+          `videoData`,
+          res.data.video_data.map(i => i.video_title)
+        );
+        this.$set(this, `videoPath`, _.get(_.head(this.info.video_data), 'video_url'));
       }
     },
   },
@@ -49,4 +134,32 @@ export default {
 };
 </script>
 
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.main {
+  .video {
+    .top {
+      height: 215px;
+      background-color: #000;
+      video {
+        width: 100%;
+        height: 215px;
+      }
+      .h5video {
+        width: 100%;
+        height: 215px;
+      }
+      p {
+        font-size: 18px;
+      }
+    }
+    .down {
+      text-align: center;
+      height: 40px;
+      padding: 5px 0;
+    }
+  }
+  .imgchat {
+    padding: 0 10px;
+  }
+}
+</style>

+ 258 - 0
src/views/live/liveParts/trainchat.vue

@@ -0,0 +1,258 @@
+<template>
+  <div id="trainchat">
+    <el-row>
+      <el-col :span="24" class="style">
+        <el-col :span="24" class="list" v-for="(i, index) in list" :key="index">
+          <span v-if="!isEmotion(i.content)">
+            <el-col :span="24" class="one">
+              [<span>{{ i.send_time | getTime }}</span
+              >]
+              <span>{{ i.sender_name }}</span>
+            </el-col>
+            <el-col :span="24" class="two">
+              <span> {{ i.content }}</span>
+            </el-col>
+          </span>
+          <span v-else>
+            <el-col :span="24" class="thr">
+              <span class="textOver">{{ i.sender_name }}</span>
+              <span>送出一朵/个</span>
+              <span v-html="i.content"></span>
+            </el-col>
+          </span>
+        </el-col>
+      </el-col>
+    </el-row>
+    <el-col :span="24" class="sendtxt">
+      <van-button icon="chat" type="info" round @click="show = true" />
+    </el-col>
+    <van-popup v-model="show" position="bottom" class="popup">
+      <van-col span="24" class="one">
+        <p>快捷发言</p>
+        <p>
+          <span v-for="(i, index) in kjfyList" :key="index" @click="changekjfy(i.name)">{{ i.name }}</span>
+        </p>
+      </van-col>
+      <van-col span="24" class="two">
+        <van-col span="19">
+          <van-field v-model="text" placeholder="请输入内容" />
+        </van-col>
+        <van-col span="5" style="text-align:center;">
+          <van-button round type="info" @click="send()">发言</van-button>
+        </van-col>
+      </van-col>
+    </van-popup>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: trainchat } = createNamespacedHelpers('trainchat');
+var moment = require('moment');
+import _ from 'lodash';
+export default {
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  name: 'trainchat',
+  props: {},
+  components: {},
+  data: function() {
+    return {
+      list: [],
+      // 发言
+      show: false,
+      text: '',
+      // 快捷发言列表
+      kjfyList: [{ name: '欢迎欢迎' }, { name: '科技创新' }, { name: '大咖云集' }],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  mounted() {
+    this.channel();
+  },
+  methods: {
+    ...trainchat(['query', 'create']),
+    async search() {
+      const res = await this.query({ skip: 0, unit_id: this.id });
+      if (this.$checkRes(res)) this.$set(this, `list`, res.data);
+    },
+    isEmotion(word) {
+      return word.startsWith('<img');
+    },
+    channel() {
+      this.$stomp({
+        [`/exchange/train_live/${this.id}`]: this.onMessage,
+      });
+    },
+    onMessage(message) {
+      console.log(message);
+      let body = _.get(message, 'body');
+      if (body) {
+        body = JSON.parse(body);
+        this.list.push(body);
+        this.text = '';
+      }
+      this.search();
+    },
+    // 发言
+    async send() {
+      if (this.text != '') {
+        let object = { sender_name: this.user.user_title, content: this.text, unit_id: this.id };
+        if (this.user._id) {
+          object.sender_id = this.user._id;
+        }
+        let res = await this.create(object);
+        this.text = '';
+        this.show = false;
+        this.$checkRes(res, null, res.errmsg || '发言失败');
+      } else this.$message.error('请输入信息后发送');
+    },
+    // 选择快捷发言
+    changekjfy(data) {
+      this.$set(this, `text`, data);
+      this.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');
+      else time = moment(date).format('YYYY-MM-DD');
+      return time;
+    },
+  },
+  computed: {
+    // ...mapState(['user']),
+    user() {
+      let user = localStorage.getItem('user');
+      if (user) user = JSON.parse(user);
+      return user;
+    },
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.style {
+  // min-height: 365px;
+  // max-height: 365px;
+  overflow-y: auto;
+  .list {
+    padding: 5px 0;
+    .one {
+      padding: 5px 0;
+      span:nth-child(1) {
+        color: #ff0000;
+      }
+      span:nth-child(2) {
+        font-size: 16px;
+        color: #999;
+      }
+    }
+    .two {
+      min-height: 30px;
+      span {
+        font-size: 15px;
+        background: #f1f1f1;
+        padding: 5px;
+        border-radius: 5px;
+        min-width: 30%;
+        display: inline-block;
+      }
+    }
+    .thr {
+      text-align: center;
+      background: #f1f1f1;
+      border-radius: 25px;
+      width: 80%;
+      margin: 0 10%;
+      padding: 5px 0;
+      span:nth-child(1) {
+        color: #db7093;
+        font-weight: bold;
+        position: relative;
+        top: -3px;
+        font-size: 15px;
+        display: inline-block;
+        width: 45%;
+      }
+      span:nth-child(2) {
+        color: #000000;
+        position: relative;
+        top: -7px;
+        font-size: 15px;
+      }
+      span:nth-child(3) {
+        position: relative;
+        top: 2px;
+        left: 5px;
+      }
+    }
+  }
+}
+// 发言
+.sendtxt {
+  position: fixed;
+  bottom: 10px;
+  right: 10px;
+  width: 100%;
+  z-index: 999;
+  text-align: right;
+}
+.popup {
+  .one {
+    color: #fff;
+    p:nth-child(1) {
+      text-align: center;
+      padding: 25px 0;
+      font-size: 20px;
+    }
+    p:nth-child(2) {
+      padding: 0 10px;
+      text-align: center;
+      span {
+        background-color: #409eff9f;
+        display: inline-block;
+        border-radius: 25px;
+        margin: 0 10px 10px 0;
+        font-size: 15px;
+        padding: 5px 10px;
+      }
+      span:nth-child(4n) {
+        margin: 0 0 10px 0;
+      }
+    }
+  }
+  .two {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    background: #fff;
+    padding: 5px 5px;
+    height: 40px;
+    /deep/.van-cell {
+      padding: 3px 5px;
+      border-radius: 5px;
+      border: 1px solid #ccc;
+      width: 98%;
+    }
+    /deep/.van-button {
+      height: 31px;
+    }
+  }
+}
+/deep/.van-popup {
+  height: 30%;
+  background-color: #0000005f !important;
+}
+</style>