guhongwei 4 年之前
父节点
当前提交
eb1720d6d7

+ 18 - 0
src/App.vue

@@ -4,6 +4,8 @@
   </div>
 </template>
 <script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: trainlive } = createNamespacedHelpers('trainlive');
 export default {
   name: 'App',
   provide() {
@@ -16,7 +18,20 @@ export default {
       alive: true,
     };
   },
+  created() {
+    // this.$router.beforeEach((to, from, next) => {
+    //   if (to.path != '/exporthall/index' && to.path == '/hallList/index') {
+    //     // this.Logout();
+    //   }
+    //   next();
+    // });
+  },
   methods: {
+    ...trainlive(['userLogout']),
+    async Logout() {
+      let res = await this.userLogout({ id: this.user._id });
+      location.reload();
+    },
     reload() {
       this.alive = false;
       this.$nextTick(() => {
@@ -24,6 +39,9 @@ export default {
       });
     },
   },
+  computed: {
+    ...mapState(['user']),
+  },
 };
 </script>
 <style lang="less">

二进制
src/assets/bg2.jpg


+ 1 - 1
src/components/swiper-frame.vue

@@ -42,7 +42,7 @@ export default {
 <style lang="less" scoped>
 .swiper-box {
   .swiper-container {
-    height: 40px;
+    height: 45px;
   }
 }
 // 选中背景颜色,字颜色

+ 19 - 4
src/layout/live/head.vue

@@ -37,10 +37,11 @@
               </span>
               <el-button v-else type="primary" size="mini" @click="adminLogin">管理登录</el-button>
             </span>
-            <span v-else>
-              <span class="name">{{ user.title }}</span>
-              <el-button @click="tuCenter" type="info" size="mini">个人中心</el-button>
-              <el-button @click="zhuxiao" type="danger" size="mini">退出登录</el-button>
+            <span v-else-if="user._id">
+              <span class="name">{{ user.user || user.user_title }}</span>
+              <el-button @click="tuCenter" type="info" size="mini" v-if="user.room_id">个人中心</el-button>
+              <el-button @click="zhuxiao" type="danger" size="mini" v-if="user.room_id">退出登录</el-button>
+              <el-button @click="userLogoutBtn" type="danger" size="mini" v-else>退出登录</el-button>
             </span>
           </el-col>
         </div>
@@ -93,6 +94,7 @@
 import { mapState, createNamespacedHelpers } from 'vuex';
 const { mapActions: login } = createNamespacedHelpers('login');
 const { mapActions: dockLogin } = createNamespacedHelpers('dockLogin');
+const { mapActions: trainlive } = createNamespacedHelpers('trainlive');
 import QRCode from 'qrcode';
 export default {
   name: 'heads',
@@ -113,6 +115,7 @@ export default {
   methods: {
     ...login({ logout: 'logout', transactiondtetle: 'delete' }),
     ...dockLogin({ docklogout: 'logout', transactiondtetle: 'delete' }),
+    ...trainlive(['userLogout']),
     // 跳转
     turnTo(type) {
       if (type == 'index') {
@@ -157,6 +160,7 @@ export default {
         this.$router.push({ path: '/kjpdCenter/index', query: { num: '1' } });
       }
     },
+    // 注销登录
     async zhuxiao() {
       if (this.user.role === '3' || this.user.role === '8') {
         this.docklogout();
@@ -174,6 +178,17 @@ export default {
         window.location.reload();
       }
     },
+    // 展会用户注销登录
+    async userLogoutBtn() {
+      let res = await this.userLogout({ id: this.user._id });
+      if (this.$checkRes(res)) {
+        this.$message({
+          message: '注销成功',
+          type: 'success',
+        });
+        window.location.reload();
+      }
+    },
     // 关注公众号
     guanzhu() {
       if (this.view) {

+ 2 - 0
src/store/index.js

@@ -33,6 +33,7 @@ import flower from './live/flower';
 import imgtxtdock from './live/imgtxtdock';
 // 培训问诊
 import trainlive from './live/trainlive';
+import trainchat from './live/trainchat';
 // 专家
 import expertsuser from './market/exportuser';
 // 产品
@@ -94,6 +95,7 @@ export default new Vuex.Store({
     flower,
     imgtxtdock,
     trainlive,
+    trainchat,
     // 专家
     expertsuser,
     // 产品

+ 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,
+};

+ 30 - 1
src/store/live/trainlive.js

@@ -13,6 +13,7 @@ const state = () => ({});
 const mutations = {};
 
 const actions = {
+  // 展会列表
   async query({ commit }, { skip = 0, limit = undefined, ...info } = {}) {
     const res = await this.$axios.$get(api.trainliveInfo, {
       skip,
@@ -21,24 +22,29 @@ const actions = {
     });
     return res;
   },
+  // 展会创建
   async create({ commit }, payload) {
     const res = await this.$axios.$post(`${api.trainliveInfo}`, payload);
     return res;
   },
+  // 展会详情
   async fetch({ commit }, payload) {
     const res = await this.$axios.$get(`${api.trainliveInfo}/${payload}`);
     return res;
   },
+  // 展会修改
   async update({ commit }, { id, ...info } = {}) {
     const res = await this.$axios.$post(`${api.trainliveInfo}/update/${id}`, {
       ...info,
     });
     return res;
   },
+  // 展会删除
   async delete({ commit }, payload) {
     const res = await this.$axios.$delete(`${api.trainliveInfo}/${payload}`);
     return res;
   },
+  // 展会用户登录
   async login({ commit, dispatch }, { user, router, path = '/', needReturn = false, typeCheck = false, isWx = false, needNotice = true }) {
     let res = await this.$axios.$post(`${api.logininfo}`, user);
     if (res.errcode == '0') {
@@ -59,6 +65,15 @@ const actions = {
       });
     }
   },
+  // 用户列表
+  async userQuery({ commit }, { skip = 0, limit = undefined, id, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.userloginInfo}/${id}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
   // 参加用户
   async userCreate({ commit }, { id, ...info } = {}) {
     const res = await this.$axios.$post(`${api.trainliveInfo}/user/${id}`, {
@@ -66,18 +81,21 @@ const actions = {
     });
     return res;
   },
+  // 用户删除
   async userDelete({ commit }, { id, ...info } = {}) {
     const res = await this.$axios.$delete(`${api.trainliveInfo}/user/${id}`, {
       ...info,
     });
     return res;
   },
+  // 用户修改
   async userUpdate({ commit }, { id, ...info } = {}) {
     const res = await this.$axios.$post(`${api.trainliveInfo}/user/update/${id}`, {
       ...info,
     });
     return res;
   },
+  // 用户登录
   async userLogin({ commit }, { id, ...info } = {}) {
     const res = await this.$axios.$post(`${api.userloginInfo}/login/${id}`, {
       ...info,
@@ -98,12 +116,23 @@ const actions = {
         message: `失败原因:${res.errmsg || '登陆失败'}`,
         type: 'error',
       });
+      return res;
     }
   },
+  // 用户退出
   async userLogout({ commit }, { id } = {}) {
     window.localStorage.removeItem('user');
-    const res = await this.$axios.$post(`${api.userloginInfo}/logout/${id}`);
     commit('deleteUser');
+    const res = await this.$axios.$post(`${api.userloginInfo}/logout/${id}`);
+  },
+  // 用户定时请求
+  async userLonger({ commit }, { skip = 0, limit = undefined, id, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.userloginInfo}/longer/${id}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
   },
 };
 

+ 0 - 211
src/views/exporthall/index copy.vue

@@ -1,211 +0,0 @@
-<template>
-  <div id="index">
-    <el-row>
-      <el-col :span="24" class="main">
-        <div class="w_1200">
-          <el-col :span="24" class="one">
-            <el-col :span="24" class="top">
-              <p>培训问诊在线展会模板</p>
-              <p>主办方:吉林省计算中心</p>
-            </el-col>
-          </el-col>
-          <el-col :span="24" class="two">
-            <el-col :span="22" class="left" :offset="1">
-              <el-col :span="24" class="top">
-                <span style="color:#409eff">专家培训直播</span>
-                <span>直播</span>
-              </el-col>
-              <el-col :span="24" class="down">
-                视频播放框
-              </el-col>
-            </el-col>
-            <el-col :span="22" class="right" :offset="1">
-              <el-col :span="24" class="top">
-                公共聊天
-              </el-col>
-              <el-col :span="24" class="down">
-                <el-col :span="24" class="list">
-                  <el-col :span="24" class="chatList" v-for="(item, index) in chatList" :key="index">
-                    <el-col :span="1" class="image">
-                      <el-image :src="touxiang" style="width:30px;height:30px"></el-image>
-                    </el-col>
-                    <el-col :span="23" class="other">
-                      <el-col :span="24" class="otherone">
-                        <span>{{ item.name }}</span>
-                        <span>{{ item.date }}</span>
-                      </el-col>
-                      <el-col :span="24" class="othertwo">
-                        <p class="remark">{{ item.content }}</p>
-                      </el-col>
-                    </el-col>
-                  </el-col>
-                </el-col>
-                <el-col :span="24" class="chat">
-                  <el-col :span="21" class="input">
-                    <el-input v-model="text" placeholder="请输入聊天内容"></el-input>
-                  </el-col>
-                  <el-col :span="3" class="btn">
-                    <el-button type="primary" size="mini">发送</el-button>
-                  </el-col>
-                </el-col>
-              </el-col>
-            </el-col>
-          </el-col>
-        </div>
-        <div class="pz_down">
-          <live-foot></live-foot>
-        </div>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script>
-import liveFoot from '@/layout/live/foot.vue';
-import { mapState, createNamespacedHelpers } from 'vuex';
-export default {
-  name: 'index',
-  props: {},
-  components: { liveFoot },
-  data: function() {
-    return {
-      // 聊天列表 超过6个就有滚动条
-      chatList: [
-        { name: '顾红伟', date: '10:00', content: '信息内容' },
-        { name: '顾红伟', date: '10:00', content: '信息内容' },
-      ],
-      touxiang: require('@/assets/emotion/touxiang.png'),
-      // 发言内容
-      text: '',
-      per: require('@/assets/personal.jpg'),
-      // 招聘信息
-    };
-  },
-  created() {},
-  methods: {},
-  computed: {
-    ...mapState(['user']),
-  },
-  metaInfo() {
-    return { title: this.$route.meta.title };
-  },
-};
-</script>
-
-<style lang="less" scoped>
-.main {
-  .one {
-    .top {
-      text-align: center;
-      margin: 50px 0;
-      p:nth-child(1) {
-        font-size: 50px;
-        font-family: cursive;
-      }
-      p:nth-child(2) {
-        font-size: 18px;
-        padding: 15px 0;
-      }
-    }
-  }
-  .two {
-    margin: 0 0 15px 0;
-    text-align: center;
-    .left {
-      height: 600px;
-      overflow: hidden;
-      border: 5px solid #000;
-      background: #fff;
-      border-radius: 5px;
-      padding: 10px;
-      .top {
-        height: 30px;
-        line-height: 30px;
-        font-weight: bold;
-        font-size: 20px;
-        margin: 0 0 5px 0;
-      }
-      .down {
-        height: 535px;
-        background-color: #000;
-        color: #fff;
-      }
-    }
-    .right {
-      height: 560px;
-      margin-top: 30px;
-      border-top-left-radius: 5px;
-      border-bottom-left-radius: 5px;
-      overflow: hidden;
-      background: #f0ffff5f;
-      border-bottom: 1px solid #f1f1f1;
-      .top {
-        height: 40px;
-        line-height: 40px;
-        padding: 0 10px;
-        font-weight: bold;
-        font-size: 18px;
-        color: #fff;
-        background-color: #409eff;
-      }
-      .down {
-        overflow: hidden;
-        padding: 0 0 0 10px;
-        .list {
-          height: 480px;
-          overflow-y: auto;
-          .chatList {
-            padding: 10px 0;
-            border-bottom: 1px dashed #409eff;
-            .image {
-              text-align: center;
-            }
-            .other {
-              .otherone {
-                text-align: left;
-                span:nth-child(1) {
-                  color: #000;
-                  font-size: 16px;
-                  font-weight: bold;
-                }
-                span:nth-child(2) {
-                  display: inline-block;
-                  margin: 0 0 0 15px;
-                  color: #ccc;
-                }
-              }
-              .othertwo {
-                margin: 5px 0 0 0;
-                color: #000;
-                .remark {
-                  min-height: 20px;
-                  font-size: 15px;
-                  padding: 5px;
-                  border-radius: 5px;
-                  background: #cccccc5f;
-                }
-              }
-            }
-          }
-        }
-        .chat {
-          height: 40px;
-          .input {
-            /deep/.el-input__inner {
-              height: 35px;
-              line-height: 35px;
-            }
-          }
-          .btn {
-            /deep/.el-button--mini,
-            .el-button--mini.is-round {
-              padding: 10px 15px;
-              width: 100%;
-            }
-          }
-        }
-      }
-    }
-  }
-}
-</style>

+ 106 - 20
src/views/exporthall/index.vue

@@ -1,12 +1,25 @@
 <template>
   <div id="index">
     <el-row>
-      <el-col :span="24">
-        <el-col :span="24">
-          {{ liveInfo.title }}
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="one">
+          <div class="w_1200">
+            <p>{{ liveInfo.title }}</p>
+            <p>
+              <span>主办方:{{ liveInfo.sponsor }}</span>
+              <span>办展城市:{{ liveInfo.province }}-{{ liveInfo.place }}</span>
+            </p>
+          </div>
         </el-col>
-        <el-col :span="24">
-          <el-button type="primary" size="mini" @click="loginOut">退出</el-button>
+        <el-col :span="24" class="two">
+          <div class="w_1200">
+            <el-col :span="12" class="left">
+              <videoSwiper :liveInfo="liveInfo" :videoData="videoData"></videoSwiper>
+            </el-col>
+            <el-col :span="12" class="right">
+              <imgTxt :liveInfo="liveInfo"></imgTxt>
+            </el-col>
+          </div>
         </el-col>
       </el-col>
     </el-row>
@@ -14,7 +27,10 @@
 </template>
 
 <script>
+import videoSwiper from './parts/videoSwiper.vue';
+import imgTxt from './parts/imgTxt.vue';
 import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: place } = createNamespacedHelpers('place');
 const { mapActions: trainlive } = createNamespacedHelpers('trainlive');
 export default {
   metaInfo() {
@@ -22,32 +38,51 @@ export default {
   },
   name: 'index',
   props: {},
-  components: {},
+  components: {
+    videoSwiper,
+    imgTxt,
+  },
   data: function() {
     return {
-      // 展会详情
       liveInfo: {},
+      videoData: [],
+      provinceList: [],
+      placeList: [],
+      times: 1800,
     };
   },
   async created() {
+    await this.searchType();
     await this.search();
   },
   methods: {
-    ...trainlive(['fetch', 'userLogout']),
+    ...place({ palcequery: 'query', palcefetch: 'fetch' }),
+    ...trainlive(['query', 'fetch', 'create', 'update', 'delete', 'userLonger']),
     async search() {
-      if (this.id) {
-        let res = await this.fetch(this.id);
-        if (this.$checkRes(res)) {
-          this.$set(this, `liveInfo`, res.data);
-        }
-      }
-    },
-    async loginOut() {
-      let res = await this.userLogout({ id: '6006333bc54267a190981cea' });
+      let res = await this.fetch(this.id);
       if (this.$checkRes(res)) {
-        console.log(res.data);
+        res.data.province = this.provinceList.find(i => i.code == res.data.province).name;
+        res.data.place = this.placeList.find(i => i.code == res.data.place).name;
+        this.$set(this, `liveInfo`, res.data);
+        this.$set(this, `videoData`, res.data.video_data);
       }
     },
+    async searchType() {
+      let res = await this.palcequery({ level: 1 });
+      this.$set(this, `provinceList`, res.data);
+      res = await this.palcequery({ level: 2 });
+      this.$set(this, `placeList`, res.data);
+    },
+    setDate() {
+      this.timer = setInterval(async () => {
+        this.times--;
+        if (this.times === 0) {
+          let res = await this.userLonger({ id: this.user._id });
+          this.times = 1800;
+          clearInterval(this.timer);
+        }
+      }, 1000);
+    },
   },
   computed: {
     ...mapState(['user']),
@@ -55,8 +90,59 @@ export default {
       return this.$route.query.id;
     },
   },
-  watch: {},
+  watch: {
+    times: {
+      handler(val) {
+        if (val == 1800) {
+          this.setDate();
+        }
+      },
+      immediate: true,
+    },
+  },
 };
 </script>
 
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.main {
+  .one {
+    p {
+      text-align: center;
+    }
+    p:nth-child(1) {
+      font-size: 80px;
+      font-family: cursive;
+      transform: scale(0.8);
+      font-weight: bolder;
+      -webkit-text-stroke: 1px #fff;
+      -webkit-text-fill-color: #191970;
+      letter-spacing: 3px;
+      padding: 30px 0;
+    }
+    p:nth-child(2) {
+      span {
+        font-size: 30px;
+        padding: 0 20px 15px 20px;
+        font-family: cursive;
+        font-weight: bold;
+      }
+    }
+  }
+  .two {
+    padding: 5% 0;
+    .left {
+      width: 49%;
+      height: 550px;
+      margin: 0 15px 0 0;
+      border: 2px solid #409eff;
+      border-radius: 5px;
+    }
+    .right {
+      width: 49%;
+      height: 550px;
+      box-shadow: 0 0 5px #409eff;
+      border-radius: 5px;
+    }
+  }
+}
+</style>

+ 217 - 0
src/views/exporthall/parts/chat.vue

@@ -0,0 +1,217 @@
+<template>
+  <div id="chat">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="list">
+          <el-col :span="24" class="chatlist" 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-col :span="24" class="send">
+          <el-col :span="17" class="text">
+            <el-input v-model="text"></el-input>
+          </el-col>
+          <el-col :span="7" class="btn">
+            <el-popover placement="top" width="200" trigger="click">
+              <p>
+                <span class="kjfyList" v-for="(i, index) in kjfyList" :key="index" @click="changekjfy(i.name)">{{ i.name }}</span>
+              </p>
+              <el-button type="primary" size="mini" slot="reference">快捷发言</el-button>
+            </el-popover>
+            <el-button type="primary" size="mini" @click="send">发送</el-button>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: trainchat } = createNamespacedHelpers('trainchat');
+var moment = require('moment');
+import _ from 'lodash';
+export default {
+  name: 'chat',
+  props: {
+    liveInfo: { type: Object },
+  },
+  components: {},
+  data: function() {
+    return {
+      list: [],
+      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.liveInfo.id });
+      if (this.$checkRes(res)) this.$set(this, `list`, res.data);
+    },
+    isEmotion(word) {
+      return word.startsWith('<img');
+    },
+    channel() {
+      this.$stomp({
+        [`/exchange/train_live/${this.liveInfo.id}`]: this.onMessage,
+      });
+    },
+    onMessage(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.liveInfo.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();
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  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;
+    },
+  },
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .list {
+    height: 429px;
+    overflow-y: auto;
+    border: 1px solid red;
+    padding: 0 0 10px 0;
+    .chatlist {
+      padding: 0 10px;
+      .one {
+        padding: 10px 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;
+        }
+      }
+    }
+  }
+  .send {
+    height: 40px;
+    border: 1px solid #000;
+    margin: 10px 0 0 0;
+    border-radius: 5px;
+    .text {
+      /deep/.el-input__inner {
+        height: 38px;
+        line-height: 38px;
+      }
+    }
+    .btn {
+      text-align: center;
+      padding: 5px 0;
+      .el-button {
+        margin: 0 0 0 5px;
+      }
+    }
+  }
+}
+.kjfyList {
+  display: inline-block;
+  margin: 0 10px 0 0;
+}
+.kjfyList:hover {
+  cursor: pointer;
+  color: #409eff;
+  font-weight: bold;
+}
+</style>

+ 46 - 0
src/views/exporthall/parts/imgTxt.vue

@@ -0,0 +1,46 @@
+<template>
+  <div id="imgTxt">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-tabs class="tabs" type="border-card">
+          <el-tab-pane label="公共聊天"><chat :liveInfo="liveInfo"></chat></el-tab-pane>
+          <el-tab-pane label="展会信息"><message :liveInfo="liveInfo"></message></el-tab-pane>
+        </el-tabs>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import chat from './chat.vue';
+import message from './message.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'imgTxt',
+  props: {
+    liveInfo: { type: Object },
+  },
+  components: {
+    chat,
+    message,
+  },
+  data: function() {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .tabs {
+    height: 548px;
+    overflow-y: auto;
+  }
+}
+</style>

+ 66 - 0
src/views/exporthall/parts/message.vue

@@ -0,0 +1,66 @@
+<template>
+  <div id="message">
+    <el-row>
+      <el-col :span="24" class="main">
+        <p>
+          标题:<span>{{ liveInfo.title }}</span>
+        </p>
+        <p>
+          开始时间:<span>{{ liveInfo.create_date }}</span>
+        </p>
+        <p>
+          办展城市:<span>{{ liveInfo.province }}-{{ liveInfo.place }}</span>
+        </p>
+        <p>
+          主办方:<span>{{ liveInfo.sponsor }}</span>
+        </p>
+        <p>
+          负责人:<span>{{ liveInfo.user }}</span>
+        </p>
+        <p>
+          联系电话:<span>{{ liveInfo.phone }}</span>
+        </p>
+        <p>信息简介:{{ liveInfo.brief }}</p>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'message',
+  props: {
+    liveInfo: { type: Object },
+  },
+  components: {},
+  data: function() {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  watch: {},
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  p {
+    font-size: 18px;
+    padding: 10px 0;
+    border-bottom: 1px dashed #ccc;
+    color: #666;
+    span {
+      color: #000;
+    }
+  }
+  p:last-child {
+    border-bottom: none;
+    line-height: 10px;
+    line-height: 30px;
+  }
+}
+</style>

+ 158 - 0
src/views/exporthall/parts/videoSwiper.vue

@@ -0,0 +1,158 @@
+<template>
+  <div id="videoSwiper">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="one">
+          <el-col :span="4" class="txt">
+            <span style="color: rgb(255, 132, 0);">视频</span>
+            <span>直播</span>
+          </el-col>
+          <el-col :span="20" class="title textOver">
+            {{ liveInfo.title }}
+          </el-col>
+        </el-col>
+        <el-col :span="24" class="two">
+          <video :src="videoPath" controls autoplay loop v-if="videoData.length > 0">
+            <source src="movie.mp4" type="video/mp4" />
+            <source src="movie.ogg" type="video/ogg" />
+          </video>
+          <div class="videointro" v-else>
+            <p>{{ liveInfo.title }}</p>
+          </div>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <swiper :list="videoData" :options="options">
+            <template v-slot="{ index, item }">
+              <p :class="`${menuIndex == index ? 'indexClass' : 'videodata'}`" @click="changeMenu(index, item)">{{ item.video_title }}</p>
+            </template>
+          </swiper>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+import swiper from '@c/swiper-frame.vue';
+export default {
+  name: 'videoSwiper',
+  props: {
+    liveInfo: { type: Object },
+    videoData: { type: Array },
+  },
+  components: {
+    swiper,
+  },
+  data: function() {
+    return {
+      videoPath: '',
+      menuIndex: '0',
+      options: {
+        slidesPerView: 5,
+        spaceBetween: 10,
+        // 分页
+        navigation: {
+          nextEl: '.swiper-button-next',
+          prevEl: '.swiper-button-prev',
+        },
+      },
+    };
+  },
+  created() {},
+  methods: {
+    changeMenu(index, item) {
+      if (item) {
+        this.menuIndex = index;
+        this.$set(this, `videoPath`, item.video_url);
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  watch: {
+    videoData: {
+      immediate: true,
+      handler(val) {
+        this.changeMenu('0', this.videoData[0]);
+      },
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .one {
+    height: 60px;
+    .txt {
+      height: 60px;
+      line-height: 40px;
+      font-size: 20px;
+      font-weight: 700;
+      text-align: center;
+    }
+    .title {
+      height: 60px;
+      line-height: 65px;
+      font-weight: bolder;
+      -webkit-text-stroke: 1px #191970;
+      -webkit-text-fill-color: #fff;
+      letter-spacing: 3px;
+      font-size: 20px;
+    }
+  }
+  .two {
+    height: 440px;
+    video {
+      width: 100%;
+      height: 440px;
+      background-color: #000;
+    }
+    .videointro {
+      height: 440px;
+      text-align: center;
+      background-image: url('~@/assets/directBack.png');
+      background-size: 100% 100%;
+      background-repeat: no-repeat;
+      p {
+        text-align: center;
+        font-size: 30px;
+        padding: 60px 15px;
+        color: #fff;
+      }
+    }
+  }
+  .thr {
+    height: 50px;
+    .videodata {
+      border-radius: 10px;
+      background: #cccccc8f;
+      height: 39px;
+      line-height: 39px;
+      text-align: center;
+      margin: 2px 0 0 0;
+      font-weight: bold;
+    }
+    .videodata:hover {
+      cursor: pointer;
+      color: #fff;
+      background: #409eff;
+    }
+    .indexClass {
+      border-radius: 10px;
+      height: 39px;
+      line-height: 39px;
+      text-align: center;
+      margin: 2px 0 0 0;
+      font-weight: bold;
+      color: #fff;
+      background: #409eff;
+    }
+  }
+}
+</style>

+ 14 - 3
src/views/hallList/parts/trainlive.vue

@@ -30,6 +30,7 @@
       <div slot="footer" style="text-align:center">
         <el-button @click="resetBtn">取消</el-button>
         <el-button type="primary" @click="onSubmit">确认</el-button>
+        <el-button type="primary" @click="logout">注销</el-button>
       </div>
     </el-dialog>
   </div>
@@ -65,7 +66,7 @@ export default {
     await this.search();
   },
   methods: {
-    ...trainlive(['query', 'userLogin']),
+    ...trainlive(['query', 'userLogin', 'userLogout']),
     // 查询
     async search({ skip = 0, limit = 10, ...info } = {}) {
       let res = await this.query({ skip, ...info });
@@ -94,17 +95,27 @@ export default {
     // 进入频道
     userBtn(data) {
       this.$set(this, `live_id`, data.id);
-      this.dialog = true;
+      let user = this.user;
+      if (user._id) {
+        this.$router.push({ path: '/exporthall/index', query: { id: data.id } });
+      } else {
+        this.dialog = true;
+      }
     },
     // 确定
     async onSubmit() {
       let data = this.form;
       data.id = this.live_id;
       const res = await this.userLogin(data);
-      if (this.$checkRes(res)) {
+      if (res.errcode == '0') {
         this.$router.push({ path: '/exporthall/index', query: { id: data.id } });
+      } else {
+        this.resetBtn();
       }
     },
+    async logout() {
+      let res = await this.userLogout({ id: '6006333bc54267a190981cea' });
+    },
     // 取消
     resetBtn() {
       this.form = {};

+ 2 - 2
src/views/superAdminCenter/index.vue

@@ -101,8 +101,8 @@ export default {
   methods: {
     setRight(menu) {
       let { name, cpt } = menu;
-      this.$set(this, `topTitle`, '培训问诊管理');
-      this.$set(this, `cpt`, 'trainlive');
+      this.$set(this, `topTitle`, name);
+      this.$set(this, `cpt`, cpt);
     },
   },
   computed: {

+ 15 - 8
src/views/superAdminCenter/patent/index.vue

@@ -33,19 +33,23 @@
             <el-button type="primary" size="mini" @click="back">返回</el-button>
           </el-col>
           <el-col :span="24" class="import">
-            <uploadFile :limit="1" :data="fileForm.uri" listType="" type="uri" :url="'/files/uri/upload'" @upload="importSuccess"></uploadFile>
-            <el-col :span="24" class="btn">
-              <el-button type="primary" size="mini" @click="importSubmit">确定导入</el-button>
-            </el-col>
+            <el-form ref="fileForm" :model="fileForm" label-width="80px">
+              <el-form-item label="信息来源">
+                <el-input v-model="fileForm.origin" placeholder="请输入信息来源"></el-input>
+              </el-form-item>
+              <el-form-item label="信息文件">
+                <uploadFile :limit="1" :data="fileForm.uri" listType="" type="uri" :url="'/files/uri/upload'" @upload="importSuccess"></uploadFile>
+              </el-form-item>
+              <el-col :span="24" class="btn">
+                <el-button type="primary" size="mini" @click="importSubmit">确定导入</el-button>
+              </el-col>
+            </el-form>
             <el-col :span="24" class="error" v-if="errorList.length > 0">
               <el-col :span="24" class="title">
                 错误列表
               </el-col>
               <el-col :span="24" class="errorList">
-                <p>
-                  <span>序号</span>
-                  <span>错误信息</span>
-                </p>
+                <p><span>序号</span><span>错误信息</span></p>
                 <p v-for="(item, index) in errorList" :key="index">
                   <span>{{ index + 1 }}</span>
                   <span>{{ item }}</span>
@@ -363,6 +367,9 @@ export default {
         }
       }
     }
+    .origin {
+      margin: 10px 0;
+    }
   }
 }
 </style>

+ 9 - 6
src/views/trainCenter/userInfo/index.vue

@@ -12,7 +12,7 @@
               <el-button type="primary" size="mini" @click="add">添加</el-button>
             </el-col>
             <el-col :span="24" class="list">
-              <list :videoList="videoList" :total="totla" @handleEdit="handleEdit" @handleDelete="handleDelete"></list>
+              <list :userList="userList" :total="totla" @handleEdit="handleEdit" @handleDelete="handleDelete"></list>
             </el-col>
           </span>
           <span v-else>
@@ -49,8 +49,8 @@ export default {
       display: 'list',
       // 展会信息
       info: {},
-      // 视频列表
-      videoList: [],
+      // 用户列表
+      userList: [],
       totla: 0,
       // 视频添加
       form: {},
@@ -65,15 +65,18 @@ export default {
     await this.search();
   },
   methods: {
-    ...trainlive(['fetch', 'userCreate', 'userUpdate', 'userDelete']),
+    ...trainlive(['fetch', 'userCreate', 'userUpdate', 'userDelete', 'userQuery']),
     // 查询
     async search() {
       let data = this.user;
       let res = await this.fetch(data.id);
       if (this.$checkRes(res)) {
         this.$set(this, `info`, res.data);
-        this.$set(this, `videoList`, res.data.user_data);
-        this.$set(this, `totla`, res.data.user_data.length);
+      }
+      res = await this.userQuery({ id: data.id });
+      if (this.$checkRes(res)) {
+        this.$set(this, `userList`, res.data);
+        this.$set(this, `totla`, res.data.length);
       }
     },
     // 添加

+ 2 - 2
src/views/trainCenter/userInfo/parts/list.vue

@@ -36,7 +36,7 @@ import { mapState, createNamespacedHelpers } from 'vuex';
 export default {
   name: 'list',
   props: {
-    videoList: { type: Array },
+    userList: { type: Array },
     total: { type: Number },
   },
   components: {},
@@ -67,7 +67,7 @@ export default {
     ...mapState(['user']),
   },
   watch: {
-    videoList: {
+    userList: {
       immediate: true,
       deep: true,
       handler(val) {