Przeglądaj źródła

智能白板大改版

limengbo 4 lat temu
rodzic
commit
d91e38ef2e
42 zmienionych plików z 3404 dodań i 191 usunięć
  1. 1 1
      config/dev.env.js
  2. 1 1
      config/index.js
  3. 1 0
      package.json
  4. 15 1
      src/App.vue
  5. 31 2
      src/api/table.js
  6. BIN
      src/assets/fileimg/cha.png
  7. BIN
      src/assets/fileimg/doc.png
  8. BIN
      src/assets/fileimg/docx.png
  9. BIN
      src/assets/fileimg/head.png
  10. BIN
      src/assets/fileimg/img.png
  11. BIN
      src/assets/fileimg/mp4.png
  12. BIN
      src/assets/fileimg/pdf.png
  13. BIN
      src/assets/fileimg/png.png
  14. BIN
      src/assets/fileimg/select1.png
  15. BIN
      src/assets/fileimg/select2.png
  16. BIN
      src/assets/fileimg/txt.png
  17. BIN
      src/assets/fileimg/xls.png
  18. BIN
      src/assets/fileimg/xlsx.png
  19. 539 0
      src/assets/fonts/demo.css
  20. 285 0
      src/assets/fonts/demo_index.html
  21. 37 0
      src/assets/fonts/iconfont.css
  22. BIN
      src/assets/fonts/iconfont.eot
  23. 1 0
      src/assets/fonts/iconfont.js
  24. 44 0
      src/assets/fonts/iconfont.json
  25. 41 0
      src/assets/fonts/iconfont.svg
  26. BIN
      src/assets/fonts/iconfont.ttf
  27. BIN
      src/assets/fonts/iconfont.woff
  28. BIN
      src/assets/fonts/iconfont.woff2
  29. 503 0
      src/components/video/video.vue
  30. 1 0
      src/main.js
  31. 1 1
      src/router/index.js
  32. 7 2
      src/store/getters.js
  33. 0 1
      src/store/index.js
  34. 109 3
      src/store/modules/list.js
  35. 1 1
      src/utils/auth.js
  36. 1154 0
      src/utils/city.js
  37. 205 62
      src/views/allFile/index.vue
  38. 77 70
      src/views/browse/index.vue
  39. 0 30
      src/views/dashboard/index.vue
  40. 212 0
      src/views/fileDetails/index.vue
  41. 137 16
      src/views/layout/components/Navbar.vue
  42. 1 0
      src/views/login/index.vue

+ 1 - 1
config/dev.env.js

@@ -4,6 +4,6 @@ const prodEnv = require('./prod.env')
 
 module.exports = merge(prodEnv, {
   NODE_ENV: '"development"',
-  BASE_API: '"https://whiteboardtest.ai160.com/sharedWhiteBoard"',
   // BASE_API: '"https://whiteboard.ai160.com/sharedWhiteBoard"',
+  BASE_API: '"http://login-test.efunbox.cn:81/sharedWhiteBoard"',
 })

+ 1 - 1
config/index.js

@@ -12,7 +12,7 @@ module.exports = {
     proxyTable: {},
 
     // Various Dev Server settings
-    host: 'localhost', // can be overwritten by process.env.HOST
+    host: '192.168.1.135', // can be overwritten by process.env.HOST
     port: 9528, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
     autoOpenBrowser: true,
     errorOverlay: true,

+ 1 - 0
package.json

@@ -21,6 +21,7 @@
     "nprogress": "0.2.0",
     "vue": "2.5.17",
     "vue-router": "3.0.1",
+    "vue-video-player": "^5.0.2",
     "vuex": "3.0.1"
   },
   "devDependencies": {

+ 15 - 1
src/App.vue

@@ -6,6 +6,20 @@
 
 <script>
 export default {
-  name: 'App'
+  name: 'App',
+  created() {
+    // 在页面加载时读取sessionStorage里的状态信息
+    if (sessionStorage.getItem('fileDetailsList')) {
+      // console.log(JSON.parse(sessionStorage.getItem('fileDetailsList')))
+      // console.log(this.$store.state.list.fileDetailsList)
+      this.$store.state.list.fileDetailsList = JSON.parse(sessionStorage.getItem('fileDetailsList'))
+      // this.$store.replaceState(Object.assign([], this.$store.state.list.fileDetailsList, JSON.parse(sessionStorage.getItem('fileDetailsList'))))
+    }
+
+    // 在页面刷新时将vuex里的信息保存到sessionStorage里
+    window.addEventListener('beforeunload', () => {
+      sessionStorage.setItem('fileDetailsList', JSON.stringify(this.$store.state.list.fileDetailsList))
+    })
+  }
 }
 </script>

+ 31 - 2
src/api/table.js

@@ -32,12 +32,11 @@ export function taskFile(taskId) {
   })
 }
 // 添加观看记录
-export function addViewLog(fileId, taskId) {
+export function addViewLog(taskId) {
   return request({
     url: `/wx/viewLog`,
     method: 'post',
     data: {
-      fileId,
       taskId
     }
   })
@@ -83,3 +82,33 @@ export function taskList(uid, pageNo, pageSize) {
     }
   })
 }
+/* 改版 */
+// 获取授权码订阅
+export function getSubscribe(data) {
+  return request({
+    url: `/user/subscribe`,
+    method: 'post',
+    data
+  })
+}
+// 获取订阅列表
+export function getSubscribeList(uid) {
+  return request({
+    url: `user/subscribeList`,
+    method: 'get',
+    params: {
+      uid
+    }
+  })
+}
+// 获取用户文件T
+// 获取订阅列表
+export function getTaskFileList(uid) {
+  return request({
+    url: `wx/task/taskFile`,
+    method: 'get',
+    params: {
+      uid
+    }
+  })
+}

BIN
src/assets/fileimg/cha.png


BIN
src/assets/fileimg/doc.png


BIN
src/assets/fileimg/docx.png


BIN
src/assets/fileimg/head.png


BIN
src/assets/fileimg/img.png


BIN
src/assets/fileimg/mp4.png


BIN
src/assets/fileimg/pdf.png


BIN
src/assets/fileimg/png.png


BIN
src/assets/fileimg/select1.png


BIN
src/assets/fileimg/select2.png


BIN
src/assets/fileimg/txt.png


BIN
src/assets/fileimg/xls.png


BIN
src/assets/fileimg/xlsx.png


+ 539 - 0
src/assets/fonts/demo.css

@@ -0,0 +1,539 @@
+/* Logo 字体 */
+@font-face {
+  font-family: "iconfont logo";
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
+}
+
+.logo {
+  font-family: "iconfont logo";
+  font-size: 160px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+/* tabs */
+.nav-tabs {
+  position: relative;
+}
+
+.nav-tabs .nav-more {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  height: 42px;
+  line-height: 42px;
+  color: #666;
+}
+
+#tabs {
+  border-bottom: 1px solid #eee;
+}
+
+#tabs li {
+  cursor: pointer;
+  width: 100px;
+  height: 40px;
+  line-height: 40px;
+  text-align: center;
+  font-size: 16px;
+  border-bottom: 2px solid transparent;
+  position: relative;
+  z-index: 1;
+  margin-bottom: -1px;
+  color: #666;
+}
+
+
+#tabs .active {
+  border-bottom-color: #f00;
+  color: #222;
+}
+
+.tab-container .content {
+  display: none;
+}
+
+/* 页面布局 */
+.main {
+  padding: 30px 100px;
+  width: 960px;
+  margin: 0 auto;
+}
+
+.main .logo {
+  color: #333;
+  text-align: left;
+  margin-bottom: 30px;
+  line-height: 1;
+  height: 110px;
+  margin-top: -50px;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.main .logo a {
+  font-size: 160px;
+  color: #333;
+}
+
+.helps {
+  margin-top: 40px;
+}
+
+.helps pre {
+  padding: 20px;
+  margin: 10px 0;
+  border: solid 1px #e7e1cd;
+  background-color: #fffdef;
+  overflow: auto;
+}
+
+.icon_lists {
+  width: 100% !important;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.icon_lists li {
+  width: 100px;
+  margin-bottom: 10px;
+  margin-right: 20px;
+  text-align: center;
+  list-style: none !important;
+  cursor: default;
+}
+
+.icon_lists li .code-name {
+  line-height: 1.2;
+}
+
+.icon_lists .icon {
+  display: block;
+  height: 100px;
+  line-height: 100px;
+  font-size: 42px;
+  margin: 10px auto;
+  color: #333;
+  -webkit-transition: font-size 0.25s linear, width 0.25s linear;
+  -moz-transition: font-size 0.25s linear, width 0.25s linear;
+  transition: font-size 0.25s linear, width 0.25s linear;
+}
+
+.icon_lists .icon:hover {
+  font-size: 100px;
+}
+
+.icon_lists .svg-icon {
+  /* 通过设置 font-size 来改变图标大小 */
+  width: 1em;
+  /* 图标和文字相邻时,垂直对齐 */
+  vertical-align: -0.15em;
+  /* 通过设置 color 来改变 SVG 的颜色/fill */
+  fill: currentColor;
+  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
+      normalize.css 中也包含这行 */
+  overflow: hidden;
+}
+
+.icon_lists li .name,
+.icon_lists li .code-name {
+  color: #666;
+}
+
+/* markdown 样式 */
+.markdown {
+  color: #666;
+  font-size: 14px;
+  line-height: 1.8;
+}
+
+.highlight {
+  line-height: 1.5;
+}
+
+.markdown img {
+  vertical-align: middle;
+  max-width: 100%;
+}
+
+.markdown h1 {
+  color: #404040;
+  font-weight: 500;
+  line-height: 40px;
+  margin-bottom: 24px;
+}
+
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+  color: #404040;
+  margin: 1.6em 0 0.6em 0;
+  font-weight: 500;
+  clear: both;
+}
+
+.markdown h1 {
+  font-size: 28px;
+}
+
+.markdown h2 {
+  font-size: 22px;
+}
+
+.markdown h3 {
+  font-size: 16px;
+}
+
+.markdown h4 {
+  font-size: 14px;
+}
+
+.markdown h5 {
+  font-size: 12px;
+}
+
+.markdown h6 {
+  font-size: 12px;
+}
+
+.markdown hr {
+  height: 1px;
+  border: 0;
+  background: #e9e9e9;
+  margin: 16px 0;
+  clear: both;
+}
+
+.markdown p {
+  margin: 1em 0;
+}
+
+.markdown>p,
+.markdown>blockquote,
+.markdown>.highlight,
+.markdown>ol,
+.markdown>ul {
+  width: 80%;
+}
+
+.markdown ul>li {
+  list-style: circle;
+}
+
+.markdown>ul li,
+.markdown blockquote ul>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown>ul li p,
+.markdown>ol li p {
+  margin: 0.6em 0;
+}
+
+.markdown ol>li {
+  list-style: decimal;
+}
+
+.markdown>ol li,
+.markdown blockquote ol>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown code {
+  margin: 0 3px;
+  padding: 0 5px;
+  background: #eee;
+  border-radius: 3px;
+}
+
+.markdown strong,
+.markdown b {
+  font-weight: 600;
+}
+
+.markdown>table {
+  border-collapse: collapse;
+  border-spacing: 0px;
+  empty-cells: show;
+  border: 1px solid #e9e9e9;
+  width: 95%;
+  margin-bottom: 24px;
+}
+
+.markdown>table th {
+  white-space: nowrap;
+  color: #333;
+  font-weight: 600;
+}
+
+.markdown>table th,
+.markdown>table td {
+  border: 1px solid #e9e9e9;
+  padding: 8px 16px;
+  text-align: left;
+}
+
+.markdown>table th {
+  background: #F7F7F7;
+}
+
+.markdown blockquote {
+  font-size: 90%;
+  color: #999;
+  border-left: 4px solid #e9e9e9;
+  padding-left: 0.8em;
+  margin: 1em 0;
+}
+
+.markdown blockquote p {
+  margin: 0;
+}
+
+.markdown .anchor {
+  opacity: 0;
+  transition: opacity 0.3s ease;
+  margin-left: 8px;
+}
+
+.markdown .waiting {
+  color: #ccc;
+}
+
+.markdown h1:hover .anchor,
+.markdown h2:hover .anchor,
+.markdown h3:hover .anchor,
+.markdown h4:hover .anchor,
+.markdown h5:hover .anchor,
+.markdown h6:hover .anchor {
+  opacity: 1;
+  display: inline-block;
+}
+
+.markdown>br,
+.markdown>p>br {
+  clear: both;
+}
+
+
+.hljs {
+  display: block;
+  background: white;
+  padding: 0.5em;
+  color: #333333;
+  overflow-x: auto;
+}
+
+.hljs-comment,
+.hljs-meta {
+  color: #969896;
+}
+
+.hljs-string,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-strong,
+.hljs-emphasis,
+.hljs-quote {
+  color: #df5000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+  color: #a71d5d;
+}
+
+.hljs-literal,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-attribute {
+  color: #0086b3;
+}
+
+.hljs-section,
+.hljs-name {
+  color: #63a35c;
+}
+
+.hljs-tag {
+  color: #333333;
+}
+
+.hljs-title,
+.hljs-attr,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo {
+  color: #795da3;
+}
+
+.hljs-addition {
+  color: #55a532;
+  background-color: #eaffea;
+}
+
+.hljs-deletion {
+  color: #bd2c00;
+  background-color: #ffecec;
+}
+
+.hljs-link {
+  text-decoration: underline;
+}
+
+/* 代码高亮 */
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+  color: black;
+  background: none;
+  text-shadow: 0 1px white;
+  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+  text-align: left;
+  white-space: pre;
+  word-spacing: normal;
+  word-break: normal;
+  word-wrap: normal;
+  line-height: 1.5;
+
+  -moz-tab-size: 4;
+  -o-tab-size: 4;
+  tab-size: 4;
+
+  -webkit-hyphens: none;
+  -moz-hyphens: none;
+  -ms-hyphens: none;
+  hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection,
+pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection,
+code[class*="language-"] ::-moz-selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection,
+pre[class*="language-"] ::selection,
+code[class*="language-"]::selection,
+code[class*="language-"] ::selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+@media print {
+
+  code[class*="language-"],
+  pre[class*="language-"] {
+    text-shadow: none;
+  }
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+  padding: 1em;
+  margin: .5em 0;
+  overflow: auto;
+}
+
+:not(pre)>code[class*="language-"],
+pre[class*="language-"] {
+  background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre)>code[class*="language-"] {
+  padding: .1em;
+  border-radius: .3em;
+  white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+  color: slategray;
+}
+
+.token.punctuation {
+  color: #999;
+}
+
+.namespace {
+  opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+  color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+  color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+  color: #9a6e3a;
+  background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+  color: #07a;
+}
+
+.token.function,
+.token.class-name {
+  color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+  color: #e90;
+}
+
+.token.important,
+.token.bold {
+  font-weight: bold;
+}
+
+.token.italic {
+  font-style: italic;
+}
+
+.token.entity {
+  cursor: help;
+}

+ 285 - 0
src/assets/fonts/demo_index.html

@@ -0,0 +1,285 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8"/>
+  <title>IconFont Demo</title>
+  <link rel="shortcut icon" href="https://gtms04.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
+  <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
+  <link rel="stylesheet" href="demo.css">
+  <link rel="stylesheet" href="iconfont.css">
+  <script src="iconfont.js"></script>
+  <!-- jQuery -->
+  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
+  <!-- 代码高亮 -->
+  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
+</head>
+<body>
+  <div class="main">
+    <h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
+    <div class="nav-tabs">
+      <ul id="tabs" class="dib-box">
+        <li class="dib active"><span>Unicode</span></li>
+        <li class="dib"><span>Font class</span></li>
+        <li class="dib"><span>Symbol</span></li>
+      </ul>
+      
+      <a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1468000" target="_blank" class="nav-more">查看项目</a>
+      
+    </div>
+    <div class="tab-container">
+      <div class="content unicode" style="display: block;">
+          <ul class="icon_lists dib-box">
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe660;</span>
+                <div class="name">全屏</div>
+                <div class="code-name">&amp;#xe660;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe63a;</span>
+                <div class="name">播放</div>
+                <div class="code-name">&amp;#xe63a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60a;</span>
+                <div class="name">暂停</div>
+                <div class="code-name">&amp;#xe60a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe617;</span>
+                <div class="name">声音</div>
+                <div class="code-name">&amp;#xe617;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe8b8;</span>
+                <div class="name">声音关闭</div>
+                <div class="code-name">&amp;#xe8b8;</div>
+              </li>
+          
+          </ul>
+          <div class="article markdown">
+          <h2 id="unicode-">Unicode 引用</h2>
+          <hr>
+
+          <p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
+          <ul>
+            <li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
+            <li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
+            <li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
+          </ul>
+          <blockquote>
+            <p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式</p>
+          </blockquote>
+          <p>Unicode 使用步骤如下:</p>
+          <h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
+<pre><code class="language-css"
+>@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.eot');
+  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
+      url('iconfont.woff2') format('woff2'),
+      url('iconfont.woff') format('woff'),
+      url('iconfont.ttf') format('truetype'),
+      url('iconfont.svg#iconfont') format('svg');
+}
+</code></pre>
+          <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
+<pre><code class="language-css"
+>.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+</code></pre>
+          <h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
+<pre>
+<code class="language-html"
+>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
+</code></pre>
+          <blockquote>
+            <p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
+          </blockquote>
+          </div>
+      </div>
+      <div class="content font-class">
+        <ul class="icon_lists dib-box">
+          
+          <li class="dib">
+            <span class="icon iconfont icon-quanping"></span>
+            <div class="name">
+              全屏
+            </div>
+            <div class="code-name">.icon-quanping
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-bofang"></span>
+            <div class="name">
+              播放
+            </div>
+            <div class="code-name">.icon-bofang
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-zanting"></span>
+            <div class="name">
+              暂停
+            </div>
+            <div class="code-name">.icon-zanting
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-shengyin"></span>
+            <div class="name">
+              声音
+            </div>
+            <div class="code-name">.icon-shengyin
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-shengyinguanbi"></span>
+            <div class="name">
+              声音关闭
+            </div>
+            <div class="code-name">.icon-shengyinguanbi
+            </div>
+          </li>
+          
+        </ul>
+        <div class="article markdown">
+        <h2 id="font-class-">font-class 引用</h2>
+        <hr>
+
+        <p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
+        <p>与 Unicode 使用方式相比,具有如下特点:</p>
+        <ul>
+          <li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
+          <li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
+          <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
+          <li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
+        </ul>
+        <p>使用步骤如下:</p>
+        <h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
+<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
+</code></pre>
+        <h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
+<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
+</code></pre>
+        <blockquote>
+          <p>"
+            iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
+        </blockquote>
+      </div>
+      </div>
+      <div class="content symbol">
+          <ul class="icon_lists dib-box">
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-quanping"></use>
+                </svg>
+                <div class="name">全屏</div>
+                <div class="code-name">#icon-quanping</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-bofang"></use>
+                </svg>
+                <div class="name">播放</div>
+                <div class="code-name">#icon-bofang</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-zanting"></use>
+                </svg>
+                <div class="name">暂停</div>
+                <div class="code-name">#icon-zanting</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-shengyin"></use>
+                </svg>
+                <div class="name">声音</div>
+                <div class="code-name">#icon-shengyin</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-shengyinguanbi"></use>
+                </svg>
+                <div class="name">声音关闭</div>
+                <div class="code-name">#icon-shengyinguanbi</div>
+            </li>
+          
+          </ul>
+          <div class="article markdown">
+          <h2 id="symbol-">Symbol 引用</h2>
+          <hr>
+
+          <p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
+            这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
+          <ul>
+            <li>支持多色图标了,不再受单色限制。</li>
+            <li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
+            <li>兼容性较差,支持 IE9+,及现代浏览器。</li>
+            <li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
+          </ul>
+          <p>使用步骤如下:</p>
+          <h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
+<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
+</code></pre>
+          <h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
+<pre><code class="language-html">&lt;style&gt;
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+&lt;/style&gt;
+</code></pre>
+          <h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
+<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
+  &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
+&lt;/svg&gt;
+</code></pre>
+          </div>
+      </div>
+
+    </div>
+  </div>
+  <script>
+  $(document).ready(function () {
+      $('.tab-container .content:first').show()
+
+      $('#tabs li').click(function (e) {
+        var tabContent = $('.tab-container .content')
+        var index = $(this).index()
+
+        if ($(this).hasClass('active')) {
+          return
+        } else {
+          $('#tabs li').removeClass('active')
+          $(this).addClass('active')
+
+          tabContent.hide().eq(index).fadeIn()
+        }
+      })
+    })
+  </script>
+</body>
+</html>

Plik diff jest za duży
+ 37 - 0
src/assets/fonts/iconfont.css


BIN
src/assets/fonts/iconfont.eot


Plik diff jest za duży
+ 1 - 0
src/assets/fonts/iconfont.js


+ 44 - 0
src/assets/fonts/iconfont.json

@@ -0,0 +1,44 @@
+{
+  "id": "1468000",
+  "name": "video",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "807275",
+      "name": "全屏",
+      "font_class": "quanping",
+      "unicode": "e660",
+      "unicode_decimal": 58976
+    },
+    {
+      "icon_id": "1111441",
+      "name": "播放",
+      "font_class": "bofang",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "1458367",
+      "name": "暂停",
+      "font_class": "zanting",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "9459583",
+      "name": "声音",
+      "font_class": "shengyin",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "11372697",
+      "name": "声音关闭",
+      "font_class": "shengyinguanbi",
+      "unicode": "e8b8",
+      "unicode_decimal": 59576
+    }
+  ]
+}

Plik diff jest za duży
+ 41 - 0
src/assets/fonts/iconfont.svg


BIN
src/assets/fonts/iconfont.ttf


BIN
src/assets/fonts/iconfont.woff


BIN
src/assets/fonts/iconfont.woff2


+ 503 - 0
src/components/video/video.vue

@@ -0,0 +1,503 @@
+<template>
+  <div
+    ref="custom-video_container"
+    class="custom-video_container"
+    @mouseover="handleControls($event, 'start')"
+    @mouseleave="handleControls($event, 'end')"
+  >
+    <video
+      ref="custom-video"
+      :poster="videoOption.poster"
+      class="custom-video_video"
+    >
+      <source :src="videoSrc" type="video/mp4">
+      <p>设备不支持</p>
+    </video>
+    <span
+      v-if="videoState.play"
+      ref="videoPlay"
+      class="custom-video_play custom-video_play-pause iconfont icon-zanting"
+      @click="pause('btn')"
+    />
+    <span
+      v-else
+      class="custom-video_play custom-video_play-play iconfont icon-bofang"
+      @click="play('btn')"
+    />
+    <!-- 控制区域背景 -->
+    <transition
+      name="fade"
+    >
+      <div
+        v-show="!videoState.hideControl || !videoState.play"
+        class="custom-video_control"
+      >
+        <!-- 进度条 -->
+        <div
+          class="custom-video_control-bg"
+          @mousedown="handlePrograssDown"
+          @mousemove="handlePrograssMove"
+          @mouseup="handlePrograssUp"
+        >
+          <div
+            ref="custom-video_control-bg-outside"
+            class="custom-video_control-bg-outside"
+          >
+            <span
+              ref="custom-video_control-bg-inside"
+              class="custom-video_control-bg-inside"
+            />
+            <span
+              ref="custom-video_control-bg-inside-point"
+              class="custom-video_control-bg-inside-point"
+            />
+          </div>
+        </div>
+        <!-- 声音 -->
+        <div
+          class="custom-video_control-voice"
+        >
+          <span
+            class="custom-video_control-voice-play iconfont icon-shengyin"
+          />
+          <div
+            ref="custom-video_control-voice-bg"
+            class="custom-video_control-voice-bg"
+            @mousedown="handleVolPrograssDown"
+            @mousemove="handleVolPrograssMove"
+            @mouseup="handleVolPrograssUp"
+          >
+            <div
+              ref="custom-video_control-voice-bg-outside"
+              class="custom-video_control-voice-bg-outside"
+            >
+              <span
+                ref="custom-video_control-voice-bg-inside"
+                class="custom-video_control-voice-bg-inside"
+              />
+              <span
+                ref="custom-video_control-voice-bg-point"
+                class="custom-video_control-voice-bg-point"
+              />
+            </div>
+          </div>
+        </div>
+        <!-- 时间 -->
+        <div
+          class="custom-video_control-time"
+        >
+          <span>{{ currentTime ? currentTime : "00:00" }}</span>
+          /
+          <span>{{ duration ? duration : "00:00" }}</span>
+        </div>
+        <!-- 全屏缩放 -->
+        <span
+          class="custom-video_control-full iconfont icon-quanping"
+          @click="handleScreen"
+        />
+      </div>
+    </transition>
+  </div>
+</template>
+<script>
+export default {
+  name: 'Video',
+  props: {
+    videoSrc: {
+      type: '',
+      default: ''
+    },
+    videoName: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      videoOption: {
+        poster: '', // 初始化占位图片
+        volume: 20 // 初始化声音
+      },
+      videoState: {
+        play: false, // 播放状态
+        hideControl: false, // 控制栏状态
+        distance: 0, // 移动的距离
+        downState: false, // 鼠标点击进度条
+        playState: false,
+        leftInit: 0, // 当前进度初始偏移量
+        screenState: false
+      },
+      voiceState: { // 同上
+        distance: 0,
+        downState: false,
+        topInit: 0
+      },
+      videoDom: null, // video
+      videoProOut: null, // 视频总进度条
+      videoPro: null, // 视频进度条
+      videoPoi: null, // 视频进度点
+      duration: 0, // 视频总时长
+      currentTime: 0, // 视频当前播放时长
+      processWidth: 0, // 视频进度条总长度
+      voiceProOut: null, // 音频总进度条
+      voicePro: null, // 音频进度条
+      voicePoi: null, // 音频进度点
+      volProcessHeight: 0
+    }
+  },
+  mounted() {
+    // 初始化相关元数据
+    this.videoDom = this.$refs['custom-video']
+    this.videoProOut = this.$refs['custom-video_control-bg-outside']
+    this.videoPro = this.$refs['custom-video_control-bg-inside']
+    this.videoPoi = this.$refs['custom-video_control-bg-inside-point']
+
+    this.voiceProOut = this.$refs['custom-video_control-voice-bg-outside']
+    this.voicePro = this.$refs['custom-video_control-voice-bg-inside']
+    this.voicePoi = this.$refs['custom-video_control-voice-bg-point']
+
+    this.processWidth = this.videoProOut.clientWidth
+    this.videoState.leftInit = this.getOffset(this.videoProOut).left
+    this.videoDom.volume = this.videoOption.volume / 100 // 设置初始化声音
+    this.initMedaData()
+    this.play('btn')
+  },
+  methods: {
+    initMedaData() { // 初始化video相关事件
+      this.videoDom.addEventListener('loadedmetadata', () => { // 获取视频总时长
+        this.duration = this.timeTranslate(this.videoDom.duration)
+      })
+      this.videoDom.addEventListener('click', () => { // 点击视频区域可以进行播放或者暂停
+        this.$emit('myFull', this.videoName)
+        // 点击视频区域改为可以放大缩小
+        // if (this.videoDom.paused || this.videoDom.ended) {
+        //   if (this.videoDom.ended) {
+        //     this.videoDom.currentTime = 0
+        //   }
+        //   this.play('btn')
+        // } else {
+        //   this.pause('btn')
+        // }
+      })
+      this.videoDom.addEventListener('timeupdate', () => { // 监听视频播放过程中的时间
+        const percentage = 100 * this.videoDom.currentTime / this.videoDom.duration
+        this.videoPro.style.width = percentage + '%'
+        this.videoPoi.style.left = percentage - 1 + '%'
+        this.currentTime = this.timeTranslate(this.videoDom.currentTime)
+      })
+      this.videoDom.addEventListener('ended', () => { // 监听结束播放事件
+        this.videoPro.style.width = 0
+        this.videoPoi.style.left = 0
+        this.currentTime = 0
+        this.videoState.play = false
+        this.videoState.hideControl = false
+      })
+      this.videoDom.addEventListener('volumechange', () => {
+        const percentage = this.videoDom.volume * 100
+        this.voicePro.style.height = percentage + '%'
+        this.voicePoi.style.bottom = percentage + '%'
+      })
+    },
+    play(flag) { // 播放按钮事件
+      if (flag) this.videoState.playState = true
+      this.videoState.play = true
+      console.log(this.videoDom)
+      this.videoDom.play()
+    },
+    pause(flag) { // 暂停按钮事件
+      if (flag) this.videoState.playState = false
+      this.videoDom.pause()
+      this.videoState.play = false
+    },
+    handlePrograssDown(ev) { // 监听点击进度条事件,方便获取初始点击的位置
+      // 视频暂停
+      this.videoState.downState = true // 按下鼠标标志
+      this.pause()
+      this.videoState.distance = ev.clientX - this.videoState.leftInit
+    },
+    handlePrograssMove(ev) { // 监听移动进度条事件,同步播放相关事件
+      if (!this.videoState.downState) return
+      let disX = ev.clientX - this.videoState.leftInit
+      if (disX > this.processWidth) {
+        disX = this.processWidth
+      }
+      if (disX < 0) {
+        disX = 0
+      }
+      this.videoState.distance = disX
+      this.videoDom.currentTime = this.videoState.distance / this.processWidth * this.videoDom.duration
+    },
+    handlePrograssUp() { // 松开鼠标,播放当前进度条视频
+      this.videoState.downState = false
+      // 视频播放
+      this.videoDom.currentTime = this.videoState.distance / this.processWidth * this.videoDom.duration
+      this.currentTime = this.timeTranslate(this.videoDom.currentTime)
+      if (this.videoState.playState) {
+        this.play()
+      }
+    },
+    handleVolPrograssDown(ev) { // 监听声音点击事件
+      this.voiceState.topInit = this.getOffset(this.voiceProOut).top
+      this.volProcessHeight = this.voiceProOut.clientHeight
+      this.voiceState.downState = true // 按下鼠标标志
+      this.voiceState.distance = ev.clientY - this.voiceState.topInit
+    },
+    handleVolPrograssMove(ev) { // 监听声音进度条移动事件
+      if (!this.voiceState.downState) return
+      let disY = this.voiceState.topInit + this.volProcessHeight - ev.clientY
+      if (disY > this.volProcessHeight - 2) {
+        disY = this.volProcessHeight - 2
+      }
+      if (disY < 0) {
+        disY = 0
+      }
+      this.voiceState.distance = disY
+      this.videoDom.volume = this.voiceState.distance / this.volProcessHeight
+      this.videoOption.volume = Math.round(this.videoDom.volume * 100)
+    },
+    handleVolPrograssUp() { // 监听声音鼠标离开事件
+      this.voiceState.downState = false // 按下鼠标标志
+      this.videoDom.volume = this.voiceState.distance / this.volProcessHeight
+      this.videoOption.volume = Math.round(this.videoDom.volume * 100)
+    },
+    handleControls(ev, flag) { // 监听离开或者进入视频区域隐藏或者展示控制栏
+      switch (flag) {
+        case 'start':
+          this.videoState.hideControl = false
+          break
+        case 'end':
+          this.videoState.hideControl = true
+          break
+        default:
+          break
+      }
+    },
+    handleScreen() { // 全屏操作
+      this.$emit('myFull', this.videoName)
+    // 全屏事件暂时注释
+    //   this.videoState.screenState = !this.videoState.screenState
+    //   if (this.videoState.screenState) {
+    //     this.fullScreen()
+    //   } else {
+    //     this.exitFullscreen()
+    //   }
+    },
+    timeTranslate(t) { // 时间转化
+      let m = Math.floor(t / 60)
+      m < 10 && (m = '0' + m)
+      return m + ':' + (t % 60 / 100).toFixed(2).slice(-2)
+    },
+    getOffset(node, offset) { // 获取当前屏幕下进度条的左偏移量和又偏移量
+      if (!offset) {
+        offset = {}
+        offset.left = 0
+        offset.top = 0
+      }
+      if (node === document.body || node === null) {
+        return offset
+      }
+      offset.top += node.offsetTop
+      offset.left += node.offsetLeft
+      return this.getOffset(node.offsetParent, offset)
+    },
+    fullScreen() {
+      const ele = document.documentElement
+      if (ele.requestFullscreen) {
+        ele.requestFullscreen()
+      } else if (ele.mozRequestFullScreen) {
+        ele.mozRequestFullScreen()
+      } else if (ele.webkitRequestFullScreen) {
+        ele.webkitRequestFullScreen()
+      }
+      this.$refs['custom-video_container'].style.width = '100%'
+      this.$refs['custom-video_container'].style.height = '100%'
+    },
+    exitFullscreen() {
+      const de = document
+      if (de.exitFullscreen) {
+        de.exitFullscreen()
+      } else if (de.mozCancelFullScreen) {
+        de.mozCancelFullScreen()
+      } else if (de.webkitCancelFullScreen) {
+        de.webkitCancelFullScreen()
+      }
+      this.$refs['custom-video_container'].style.width = '100%'
+      this.$refs['custom-video_container'].style.height = '100%'
+    }
+  }
+}
+</script>
+<style scoped>
+/* 总容器 */
+.custom-video_container{
+  width: 100%;
+  height: 100%;
+  position: relative;
+  overflow: hidden;
+  background: #000;
+}
+/* 视频标签 */
+.custom-video_video{
+  width: 100%;
+  height: 100%;
+}
+/* 暂停 或者 播放 */
+.custom-video_play{
+  display: inline-block;
+  position: absolute;
+  right: 50px;
+  bottom: 50px;
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  font-size: 30px;
+  color: cornflowerblue;
+}
+/* 暂停隐藏 */
+.custom-video_play-pause{
+  display: none;
+}
+/* hover 显示 */
+.custom-video_container:hover > .custom-video_play-pause{
+  display: inline-block;
+}
+/* hover 播放按钮动画 */
+.custom-video_play:hover{
+  box-shadow: 0 0 10px #5A4180;
+  transition: all 0.4s;
+}
+/* 控制栏 */
+.custom-video_control{
+  position: absolute;
+  width: 100%;
+  height: 50px;
+  left: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, .55);
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+/* 控制栏进度条 */
+.custom-video_control-bg{
+  flex: 1;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin: 0 10px;
+}
+/* 控制栏进度条 —— 总长度 */
+.custom-video_control-bg-outside{
+  width: 100%;
+  height: 5px;
+  border-radius: 2.5px;
+  background-color: #aaa;
+  position: relative;
+  cursor: pointer;
+}
+/* 控制栏进度条 —— 播放长度 */
+.custom-video_control-bg-inside{
+  position: absolute;
+  display: inline-block;
+  width: 0;
+  height: 100%;
+  border-radius: 2.5px;
+  left: 0;
+  top: 0;
+  background-color: #fff;
+  transition: all 0.2s;
+}
+/* 控制栏进度条 —— 播放点 */
+.custom-video_control-bg-inside-point{
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  background-color: #fff;
+  border-radius: 50%;
+  position: absolute;
+  top: -2.5px;
+  left: -1%;
+  transition: all 0.2s;
+}
+/* 控制栏 —— 声音、时间、全屏缩放 */
+.custom-video_control-voice,
+.custom-video_control-time,
+.custom-video_control-full{
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  color: #fff;
+  position: relative;
+}
+.custom-video_control-voice:hover > .custom-video_control-voice-bg{
+  display: block;
+}
+.custom-video_control-voice-play{
+  z-index: 10;
+}
+.custom-video_control-voice-bg{
+  display: none;
+  position: absolute;
+  width: 30px;
+  height: 100px;
+  background-color: rgba(0, 0, 0, .55);
+  left: 0;
+  bottom: 0px;
+  border-radius: 15px;
+}
+.custom-video_control-voice-bg-outside{
+  width: 5px;
+  height: 70px;
+  border-radius: 2.5px;
+  background-color: #aaa;
+  position: absolute;
+  left: 50%;
+  transform: translate3d(-50%, 10%, 0);
+  cursor: pointer;
+}
+.custom-video_control-voice-bg-inside{
+  display: inline-block;
+  position: absolute;
+  width: 100%;
+  bottom: 0;
+  left: 0;
+  border-radius: 2.5px;
+  background-color: #fff;
+  height: 0;
+}
+.custom-video_control-voice-bg-point{
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  background-color: #fff;
+  border-radius: 50%;
+  position: absolute;
+  left: -2.5px;
+  bottom: -1px;
+}
+.custom-video_control-time{
+  font-size: 12px;
+}
+.custom-video_control-full{
+  font-size: 14px;
+}
+.custom-video_control-voice,
+.custom-video_control-full{
+  width: 30px;
+  height: 30px;
+  cursor: pointer;
+}
+/* 控制栏隐藏动画 */
+.fade-enter-active {
+  transition: all .3s ease;
+}
+.fade-leave-active {
+  transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
+}
+.fade-enter, .fade-leave-to {
+  transform: translateY(50px);
+  opacity: 0;
+}
+</style>

+ 1 - 0
src/main.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 
 import 'normalize.css/normalize.css' // A modern alternative to CSS resets
+import './assets/fonts/iconfont.css'
 
 import ElementUI from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'

+ 1 - 1
src/router/index.js

@@ -60,7 +60,7 @@ export const constantRouterMap = [
       }
     ]
   },
-
+  { path: '/fileDetails', component: () => import('@/views/fileDetails/index'), hidden: true },
   {
     path: '/browse',
     component: Layout,

+ 7 - 2
src/store/getters.js

@@ -23,11 +23,16 @@ const getters = {
   logList: state => {
     return {
       logList: state.list.logList,
-      logSize: state.list.logSize
+      logSize: state.list.logSize,
+      logNameList: state.list.logNameList
     }
   },
   codeList: state => {
     return state.list.codeList
-  }
+  },
+  subscribeList: state => state.list.subscribeList,
+  taskFileList: state => state.list.taskFileList,
+  fileDetailsList: state => state.list.fileDetailsList,
+  taskNameList: state => state.list.taskNameList
 }
 export default getters

+ 0 - 1
src/store/index.js

@@ -5,7 +5,6 @@ import user from './modules/user'
 import list from './modules/list'
 import getters from './getters'
 // Vue.use(Vuex)
-
 const store = new Vuex.Store({
   modules: {
     app,

+ 109 - 3
src/store/modules/list.js

@@ -1,5 +1,6 @@
-import { joinUser, taskFile, getViewLogList, codeFile, taskList } from '@/api/table'
+import { joinUser, taskFile, getViewLogList, codeFile, taskList, getSubscribeList, getTaskFileList } from '@/api/table'
 import { getToken } from '@/utils/auth'
+import { parseTime } from '@/utils/index'
 
 const user = {
   state: {
@@ -7,9 +8,14 @@ const user = {
     joinUserList: [],
     fileList: [],
     logList: [],
+    logNameList: [],
     codeList: [],
     totalSize: 0,
-    logSize: 0
+    logSize: 0,
+    subscribeList: [],
+    taskFileList: [],
+    fileDetailsList: [],
+    taskNameList: []
   },
 
   mutations: {
@@ -20,7 +26,40 @@ const user = {
       state.fileList = [...data.localFile, ...data.screenshot, ...data.mergeFile, ...data.recordFile]
     },
     SET_LOGLIST: (state, data) => {
-      state.logList = data.list
+      // 转换数据格式
+      const list = data.list
+      const newArr = []
+      const logNameList = []
+      if (list.length > 0) {
+        list.forEach((item, ind) => {
+          logNameList.push(
+            {
+              name: item.task.title,
+              created: parseTime(item.task.gmtCreated)
+            }
+          )
+          newArr.push([])
+          item.recordFile.length === 0 ? newArr : newArr[ind].push(
+            {
+              fileName: item.recordFile[0].fileName,
+              path: item.recordFile[0].path,
+              ind
+            }
+          )
+          item.screenshot.length === 0 ? newArr : newArr[ind].push(
+            {
+              fileName: item.screenshot[0].fileName,
+              path: item.screenshot[0].path,
+              ind
+            }
+          )
+          item.localFile.forEach(file => {
+            newArr[ind].push(file)
+          })
+        })
+      }
+      state.logList = newArr
+      state.logNameList = logNameList
       state.logSize = data.totalSize
     },
     SET_TOTALSIZE: (state, size) => {
@@ -28,6 +67,50 @@ const user = {
     },
     SET_CODELIST: (state, data) => {
       state.codeList = [...data.localFile, ...data.screenshot]
+    },
+    // 获取订阅用户
+    SET_SUBSCRIBELIST: (state, list) => {
+      state.subscribeList = list
+    },
+    // 获取订阅用户文件
+    SET_TASKFILELIST: (state, list) => {
+      state.fileDetailsList = list
+      // 转换数据格式
+      const newArr = []
+      const taskNameList = []
+      if (list.length > 0) {
+        list.forEach((item, ind) => {
+          taskNameList.push(
+            {
+              name: item.task.title,
+              created: parseTime(item.task.gmtCreated)
+            }
+          )
+          newArr.push([])
+          item.recordFile.length === 0 ? newArr : newArr[ind].push(
+            {
+              fileName: item.recordFile[0].fileName,
+              path: item.recordFile[0].path,
+              ind,
+              taskId: item.task.id
+            }
+          )
+          item.screenshot.length === 0 ? newArr : newArr[ind].push(
+            {
+              fileName: item.screenshot[0].fileName,
+              path: item.screenshot[0].path,
+              ind,
+              taskId: item.task.id
+            }
+          )
+          item.localFile.forEach(file => {
+            file.taskId = item.task.id
+            newArr[ind].push(file)
+          })
+        })
+      }
+      state.taskNameList = taskNameList
+      state.taskFileList = newArr
     }
   },
 
@@ -95,6 +178,29 @@ const user = {
           reject(error)
         })
       })
+    },
+    // 获取订阅列表
+    GetSubscribeList({ commit }) {
+      return new Promise((resolve, reject) => {
+        getSubscribeList(getToken()).then(response => {
+          const data = response.data
+          commit('SET_SUBSCRIBELIST', data)
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+    // 获取订阅列表文件
+    GetTaskFileList({ commit }, uid) {
+      return new Promise((resolve, reject) => {
+        getTaskFileList(uid).then(response => {
+          const data = response.data
+          commit('SET_TASKFILELIST', data)
+          resolve(data)
+        }).catch(error => {
+          reject(error)
+        })
+      })
     }
   }
 }

+ 1 - 1
src/utils/auth.js

@@ -1,6 +1,6 @@
 import Cookies from 'js-cookie'
 
-const TokenKey = 'Admin-Token'
+const TokenKey = 'uid'
 
 export function getToken() {
   return Cookies.get(TokenKey)

Plik diff jest za duży
+ 1154 - 0
src/utils/city.js


+ 205 - 62
src/views/allFile/index.vue

@@ -1,35 +1,47 @@
 <template>
   <div class="app-container">
-    <div class="empower">
-      <el-input v-model="input" placeholder="输入授权码获取最新会议资料" @keyup.enter.native="findByCode" />
+    <div class="friend">
+      <el-form ref="ruleForm" :rules="rules" :inline="true" :model="formInline" class="demo-form-inline">
+        <el-form-item prop="code">
+          <el-input v-model="formInline.code" placeholder="请输入授权码"/>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit">确认</el-button>
+        </el-form-item>
+      </el-form>
+      <ul class="user-list">
+        <li v-for=" ( item, index ) in subscribeList" :key="item.id" :class="{ color: index === ind }" @click="see(index, item.id)">
+          <img :src="item.avatar ? item.avatar : require(`@/assets/fileimg/head.png`)" class="avter">
+          <div class="message">
+            <p style="margin: 35px 0 15px 0;">{{ item.nickName }}</p>
+            <p>{{ item.description }}</p>
+          </div>
+        </li>
+      </ul>
     </div>
-    <el-table
-      ref="multipleTable"
-      :data="joinUserList"
-      tooltip-effect="dark"
-      style="width: 100%"
-      @row-click="detail">
-      <el-table-column
-        label="文件/文件夹">
-        <template slot-scope="scope">
-          <img src="@/icons/image/file_icon.png" alt="file_icon" style="vertical-align: middle; margin-right: 10px">
-          <span>{{ scope.row.title }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="日期"
-        width="160"
-        show-overflow-tooltip>
-        <template slot-scope="scope">{{ scope.row.gmtCreated }}</template>
-      </el-table-column>
-    </el-table>
-    <div v-if="totalSize !== 0" class="page">
-      <el-pagination
-        :total="totalSize"
-        background
-        layout="prev, pager, next"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"/>
+    <div class="file">
+      <div class="title">
+        <span class="title-name">文件名</span>
+        <span class="title-date" style="margin-right: 70px;">日期</span>
+      </div>
+      <ul v-for="(item, index) in taskFileList" :key="index" class="file-con">
+        <li>
+          <span style="float: left;">{{ taskNameList[index].name }}</span>
+          <span style="float: right;">{{ taskNameList[index].created }}</span>
+        </li>
+        <li v-for="(items, index) in item" :key="index" class="border">
+          <span style="float: left;"><img :src="imgUrl(items)" alt="file_icon">{{ items.fileName }}</span>
+          <span style="float: right; cursor:pointer" @click="detail(items)">查看详情</span>
+        </li>
+      </ul>
+      <div v-if="totalSize !== 0" class="page">
+        <el-pagination
+          :total="totalSize"
+          background
+          layout="prev, pager, next"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"/>
+      </div>
     </div>
   </div>
 </template>
@@ -37,51 +49,77 @@
 <script>
 import { mapGetters } from 'vuex'
 import { parseTime } from '@/utils/index'
+import { getSubscribe } from '@/api/table'
+import { addViewLog } from '@/api/table'
 // import { deleteList } from '@/api/table'
 
 export default {
   data() {
     return {
+      formInline: {
+        code: ''
+      },
+      rules: {
+        code: [
+          { required: true, message: '请输入授权码', trigger: 'blur' }
+        ]
+      },
+      ind: -1,
       delect: true,
-      input: ''
+      followUid: ''
     }
   },
   computed: {
     ...mapGetters([
-      'joinUserList',
-      'totalSize'
+      'totalSize',
+      'subscribeList',
+      'taskFileList',
+      'taskNameList'
     ])
   },
   created() {
-    this.getList()
+    // 获取订阅列表
+    this.getSubscribeList()
   },
   methods: {
-    getList() {
-      this.$store.dispatch('TaskList', 1).then((res) => {
-        // 格式化时间
-        res.forEach((item, index) => {
-          this.joinUserList[index].gmtCreated = parseTime(item.gmtCreated)
-        })
+    // 输入授权码
+    onSubmit() {
+      this.$refs['ruleForm'].validate((valid) => {
+        if (valid) {
+          getSubscribe(this.formInline).then(res => {
+            this.$message({
+              message: '恭喜你,关注成功',
+              type: 'success'
+            })
+          })
+          this.ind = -1
+          setTimeout(() => {
+            this.getSubscribeList()
+          }, 1000)
+        } else {
+          console.log('error submit!!')
+          return false
+        }
       })
     },
-    // 输入验证码
-    findByCode() {
-      if (!this.input) {
-        alert('请输入授权码')
-        return false
+    imgUrl(url) {
+      if (url.path) {
+        const ind = url.path.lastIndexOf('.') + 1
+        const type = url.path.substr(ind)
+        return require(`@/assets/fileimg/${type}.png`)
       }
-      this.$store.dispatch('CodeFile', this.input).then((res) => {
-        // 格式化时间
-        res.forEach((item, index) => {
-          this.joinUserList[index].gmtCreated = parseTime(item.gmtCreated)
-        })
-      })
     },
     // 跳转详情
-    detail(row, event) {
-      const taskId = row.id
-      const title = row.title
-      this.$router.push({ path: `/fileDetail/fileDetail`, query: { 'taskId': taskId, 'title': title }})
+    detail(row) {
+      const type = row.path.substr(-3)
+      const ind = row.ind
+      if (type === 'mp4' || type === 'jpg' || type === 'png') {
+        // this.$router.push({ path: `/fileDetails`, query: { 'followUid': this.followUid, type, ind }})
+        window.open(`#/fileDetails?followUid=${this.followUid}&type=${type}&ind=${ind}`)
+      } else {
+        window.open(`https://view.officeapps.live.com/op/view.aspx?src=${row.path}`)
+      }
+      addViewLog(row.taskId)
     },
     handleSizeChange(page) {
       console.log(page)
@@ -94,21 +132,108 @@ export default {
           this.joinUserList[index].task.gmtCreated = parseTime(item.task.gmtCreated)
         })
       })
+    },
+    // 获取关注列表
+    getSubscribeList() {
+      this.$store.dispatch('GetSubscribeList')
+    },
+    // 获取关注人的文件
+    see(index, uid) {
+      console.log(index)
+      this.followUid = uid
+      this.ind = index
+      this.$store.dispatch('GetTaskFileList', uid)
     }
   }
 }
 </script>
 
 <style rel="stylesheet/scss" lang="scss" scoped>
-.empower {
-  display: flex;
-  justify-content: space-between;
-  .el-input {
-    height: 47px;
-    width: 400px;
+.friend {
+  width: 390px;
+  border-right: 1px solid #D3D3D3;
+  height: calc(100vh - 110px);
+  float: left;
+}
+.user-list {
+  padding: 0;
+  margin: 0;
+  list-style: none;
+  li {
+    width: 365px;
+    height: 126px;
+    background: url('../../assets/fileimg/select1.png');
+    margin-bottom: 36px;
+  }
+  .color {
+    background: url('../../assets/fileimg/select2.png');
+  }
+  .avter {
+    width: 59px;
+    height: 59px;
+    border-radius: 50%;
+    float: left;
+    margin: 30px 25px 0 28px;
+  }
+  .message {
+    padding-left: 25px;
+    border-left: 1px solid #979797;
+    box-sizing: border-box;
+    float: left;
+    height: 106px;
+    margin-top: 10px;
+    p {
+      margin: 0;
+    }
   }
 }
-
+.file {
+  margin-left: 45px;
+  float: left;
+  width: calc(100% - 460px);
+  height: calc(100vh - 115px);
+  overflow: scroll;
+  color: #484848;
+  .title {
+    font-size: 16px;
+    margin-top: 30px;
+    height: 30px;
+    .title-name {
+      float: left;
+    }
+    .title-date {
+      float: right;
+    }
+  }
+  .file-con {
+      padding: 10px 0;
+      list-style: none;
+      background: rgba(240,244,248,1);
+      margin-bottom: 30px;
+      .border {
+        border-bottom: 1px solid #fff
+      }
+      li {
+          height: 70px;
+          width: 100%;
+          line-height: 70px;
+          color: #484848;
+          padding: 0 20px;
+          &:last-child {
+            border: none
+          }
+          img {
+            width: 48px;
+            height: 48px;
+            vertical-align: middle;
+            margin-right: 10px;
+          }
+      }
+  }
+}
+.file::-webkit-scrollbar {
+      display: none;
+  }
 .line{
   text-align: center;
 }
@@ -127,4 +252,22 @@ export default {
   background: #FAFAFA;
 }
 </style>
-
+<style>
+.is-required {
+    display: inline-block;
+    vertical-align: top;
+    margin-right: 0;
+    width: 275px;
+    height: 42px;
+}
+.el-input__inner {
+    width: 275px;
+    height: 42px;
+    border-radius: 0;
+}
+.el-button--primary {
+    border-radius: 0;
+    height: 42px;
+    margin-left: -14px;
+}
+</style>

+ 77 - 70
src/views/browse/index.vue

@@ -1,34 +1,27 @@
 <template>
   <div class="app-container">
-    <el-table
-      ref="multipleTable"
-      :data="logList.logList"
-      tooltip-effect="dark"
-      style="width: 100%">
-      <el-table-column
-        :label="title">
-        <template slot-scope="scope">
-          <img :src="(scope.row.taskFile.fileType == 'png' || scope.row.taskFile.fileType == 'jpg') ? scope.row.taskFile.path : imgUrl(scope.row)" alt="file_icon" style="vertical-align: middle; margin-right: 10px">
-          <span>{{ scope.row.taskFile.fileName }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="日期"
-        width="160"
-        show-overflow-tooltip>
-        <template slot-scope="scope">{{ scope.row.taskFile.gmtCreated }}</template>
-      </el-table-column>
-      <el-table-column
-        label="操作"
-        width="80">
-        <template slot-scope="scope"><i class="el-icon-download" @click="detail(scope.row)"/></template>
-      </el-table-column>
-    </el-table>
+    <div class="file">
+      <div class="title">
+        <span class="title-name">文件名</span>
+        <span class="title-date" style="margin-right: 70px;">日期</span>
+      </div>
+      <ul v-for="(item, index) in logList.logList" :key="index" class="file-con">
+        <li>
+          <span style="float: left;">{{ logList.logNameList[index].name }}</span>
+          <span style="float: right;">{{ logList.logNameList[index].created }}</span>
+        </li>
+        <li v-for="(items, index) in item" :key="index" class="border">
+          <span style="float: left;"><img :src="imgUrl(items)" alt="file_icon">{{ items.fileName }}</span>
+          <span style="float: right; cursor:pointer" @click="detail(items)">查看详情</span>
+        </li>
+      </ul>
+    </div>
     <div v-if="logList.logList.length !== 0" class="page">
       <el-pagination
         :total="logList.logSize"
         background
         layout="prev, pager, next"
+        style="text-align: center;"
         @current-change="handleCurrentChange"/>
     </div>
   </div>
@@ -36,15 +29,11 @@
 
 <script>
 import { mapGetters } from 'vuex'
-import { parseTime } from '@/utils/index'
-// import { addViewLog } from '@/api/table'
 
 export default {
   data() {
     return {
-      title: '',
-      multipleSelection: [],
-      'xls': require('@/assets/fileimg/xls.png')
+      title: ''
     }
   },
 
@@ -63,58 +52,76 @@ export default {
 
   methods: {
     getFileList(taskId) {
-      this.$store.dispatch('GetViewLogList', 1).then((res) => {
-        console.log(this.logList.logList)
-        // 格式化时间和文件格式
-        res.list.forEach((item, index) => {
-          this.logList.logList[index].taskFile.gmtCreated = parseTime(item.taskFile.gmtCreated)
-          this.logList.logList[index].taskFile.fileType = item.taskFile.path.slice(item.taskFile.path.lastIndexOf('.') + 1)
-        })
-      })
+      this.$store.dispatch('GetViewLogList', 1)
     },
-    detail(row) {
-      const link = document.createElement('a')
-      link.style.display = 'none'
-      // link.href = `https://whiteboardtest.ai160.com/download?path=${row.taskFile.path}&fileName=${row.taskFile.fileName}`
-      link.href = `https://whiteboard.ai160.com/sharedWhiteBoard/download?path=${row.taskFile.path}&fileName=${row.taskFile.fileName}`
-      link.setAttribute('download', 'excel.xlsx')
-      document.body.appendChild(link)
-      link.click()
-      // addViewLog(row.id, row.taskId)
+    // 跳转详情
+    detail(row, event) {
+      const type = row.path.substr(-3)
+      const ind = row.ind
+      if (type === 'mp4' || type === 'jpg' || type === 'png') {
+        // this.$router.push({ path: `/fileDetails`, query: { 'followUid': this.followUid, type, ind }})
+        window.open(`#/fileDetails?followUid=${this.followUid}&type=${type}&ind=${ind}`)
+      } else {
+        window.open(`https://view.officeapps.live.com/op/view.aspx?src=${row.path}`)
+      }
     },
     handleCurrentChange(page) {
-      this.$store.dispatch('GetViewLogList', page).then((res) => {
-        console.log(this.logList.logList)
-        // 格式化时间和文件格式
-        res.list.forEach((item, index) => {
-          this.logList.logList[index].taskFile.gmtCreated = parseTime(item.taskFile.gmtCreated)
-          this.logList.logList[index].taskFile.fileType = item.taskFile.path.slice(item.taskFile.path.lastIndexOf('.') + 1)
-        })
-      })
+      this.$store.dispatch('GetViewLogList', page)
     },
     imgUrl(url) {
-      if (url.taskFile.fileType) {
-        return require(`@/assets/fileimg/${url.taskFile.fileType}.png`)
+      if (url.path) {
+        const ind = url.path.lastIndexOf('.') + 1
+        const type = url.path.substr(ind)
+        return require(`@/assets/fileimg/${type}.png`)
       }
     }
   }
 }
 </script>
 
-<style scoped>
-.line{
-  text-align: center;
-}
-.cell img {
-  width:48px;
-  height: 49px;
-}
-.page {
-  margin: 20px;
-  text-align: center;
-}
-.el-icon-download {
-  cursor: pointer;
+<style lang="scss" scoped>
+.file {
+  width: 98%;
+  color: #484848;
+  .title {
+    font-size: 16px;
+    margin-top: 30px;
+    height: 30px;
+    .title-name {
+      float: left;
+    }
+    .title-date {
+      float: right;
+    }
+  }
+  .file-con {
+      padding: 10px 0;
+      list-style: none;
+      background: rgba(240,244,248,1);
+      margin-bottom: 30px;
+      .border {
+        border-bottom: 1px solid #fff
+      }
+      li {
+          height: 70px;
+          width: 100%;
+          line-height: 70px;
+          color: #484848;
+          padding: 0 20px;
+          &:last-child {
+            border: none
+          }
+          img {
+            width: 48px;
+            height: 48px;
+            vertical-align: middle;
+            margin-right: 10px;
+          }
+      }
+  }
 }
+.file::-webkit-scrollbar {
+      display: none;
+  }
 </style>
 

+ 0 - 30
src/views/dashboard/index.vue

@@ -1,30 +0,0 @@
-<template>
-  <div class="dashboard-container">
-    欢迎页
-  </div>
-</template>
-
-<script>
-
-export default {
-  name: 'Dashboard',
-  data() {
-    return {
-
-    }
-  }
-}
-</script>
-
-<style rel="stylesheet/scss" lang="scss" scoped>
-.dashboard {
-  &-container {
-    margin: 30px;
-    text-align: center;
-  }
-  &-text {
-    font-size: 30px;
-    line-height: 46px;
-  }
-}
-</style>

+ 212 - 0
src/views/fileDetails/index.vue

@@ -0,0 +1,212 @@
+<template>
+  <div class="file-details">
+    <div v-if="type === 'mp4'" class="video">
+      <div ref="live1" :class="['live1', styleBig === 'live1' ? 'live-big' : styleBig === 'live2' ? 'live-small' : '']">
+        <videoPlayer :video-src="path1" video-name="live1" @myFull="myFull"/>
+      </div>
+      <div ref="live2" :class="['live2', styleBig === 'live2' ? 'live-big' : styleBig === 'live1' ? 'live-small' : '']">
+        <videoPlayer :video-src="path2" video-name="live2" @myFull="myFull"/>
+      </div>
+      <div v-if="styleBig" class="close" @click="close">
+        <img :src="require(`@/assets/fileimg/cha.png`)">
+      </div>
+    </div>
+    <div v-else class="photo">
+      <el-carousel :autoplay="false" :loop="false" trigger="click" indicator-position="none" height="100%" @change="getImgInd">
+        <el-carousel-item v-for="item in imgUrl" :key="item.id">
+          <div :class="['photo1', styleBig === 'live1' ? 'photo-big' : styleBig === 'live2' ? 'photo-small' : '']" @click="change('live1')">
+            <img :src="item[0].path" style="width: 100%; height: 100%;" >
+          </div>
+          <div :class="['photo2', styleBig === 'live2' ? 'photo-big' : styleBig === 'live1' ? 'photo-small' : '']" @click="change('live2')" >
+            <img :src="item[1].path" style="width: 100%; height: 100%;" >
+          </div>
+        </el-carousel-item>
+      </el-carousel>
+      <div class="identification">{{ imgInd }}/{{ imgUrl.length }}</div>
+      <div v-if="styleBig" class="close" @click="close">
+        <img :src="require(`@/assets/fileimg/cha.png`)">
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import videoPlayer from '@/components/video/video.vue'
+import 'video.js/dist/video-js.css'
+
+// import { videoPlayer } from 'vue-video-player'
+import { mapGetters } from 'vuex'
+export default {
+  components: {
+    videoPlayer
+  },
+  data() {
+    return {
+      styleBig: '',
+      path1: '',
+      path2: '',
+      imgUrl: [],
+      type: '',
+      videoBigFlag: true,
+      imgBigFlag: true,
+      imgInd: 1
+    }
+  },
+  computed: {
+    ...mapGetters([
+      'fileDetailsList'
+    ])
+  },
+  created() {
+    this.type = this.$route.query.type
+    // this.$route.query.followUid,
+    this.innitData(this.$route.query.ind)
+  },
+  mounted() {
+    // 监听键盘按键事件
+    const self = this
+    this.$nextTick(function() {
+      document.addEventListener('keyup', function(e) {
+        // 此处填写你的业务逻辑即可
+        if (e.keyCode === 27) {
+          self.close()
+        }
+      })
+    })
+  },
+  methods: {
+    change(live) {
+      console.log(live)
+      this.styleBig = live
+    },
+    myFull(type) {
+      this.change(type)
+    },
+    close() {
+      this.styleBig = ''
+    },
+    innitData(ind) {
+      console.log(this.fileDetailsList[ind])
+      const data = this.fileDetailsList[ind]
+      const imgArr = data.screenshot
+      const videoArr = data.recordFile
+      this.path1 = videoArr[0].path
+      this.path2 = videoArr[1].path
+      console.log(this.path1)
+      this.imgUrl = this.arrTrans(imgArr, 2)
+    },
+    getImgInd(ind) {
+      console.log(ind)
+      this.imgInd = ind + 1
+    },
+    arrTrans(arr, num) {
+      const newArr = []
+      arr.forEach((item, index) => {
+        const page = Math.floor(index / num) // 计算该元素为第几个素组内
+        if (!newArr[page]) { // 判断是否存在
+          newArr[page] = []
+        }
+        newArr[page].push(item)
+      })
+      return newArr
+    }
+  }
+}
+</script>
+<style lang="scss" scope>
+    .file-details {
+        width: 100%;
+        height: 100%;
+        background: #6AA1F1;
+        .video,
+        .photo {
+            width: 100%;
+            height: 100%;
+            position: relative;
+            .live1 {
+                width: 46%;
+                height: 50%;
+                position: absolute;
+                left: 3%;
+                top: 30%;
+            }
+            .live2 {
+                width: 46%;
+                height: 50%;
+                position: absolute;
+                left: 51%;
+                top: 30%;
+            }
+            .live-big {
+                position: absolute;
+                left: 5%;
+                top: 11%;
+                width: 90%;
+                height: 80%;
+            }
+            .live-small {
+                 display: none;
+                // position: absolute;
+                // left: 75%;
+                // top: 15%;
+                // width: 15%;
+                // height: 15%;
+                // z-index: 1;
+            }
+            // 图片样式
+            .photo1 {
+                width: 45%;
+                height: 50%;
+                position: absolute;
+                left: 4%;
+                top: 30%;
+                background: #fff;
+            }
+            .photo2 {
+                width: 45%;
+                height: 50%;
+                position: absolute;
+                left: 51%;
+                top: 30%;
+                background: #E1E1E1;
+            }
+            .photo-big {
+                position: absolute;
+                left: 5%;
+                top: 11%;
+                width: 90%;
+                height: 80%;
+            }
+            .photo-small {
+                display: none;
+                // position: absolute;
+                // left: 75%;
+                // top: 15%;
+                // width: 15%;
+                // height: 15%;
+                // z-index: 1;
+            }
+            .close {
+                position: absolute;
+                right: 6%;
+                top: 12%;
+                z-index: 2;
+                width: 32px;
+                height: 32px;
+                text-align: center;
+                line-height: 32px;
+            }
+            .identification {
+              position: absolute;
+              left: 50%;
+              bottom: 12%;
+              width: 30px;
+              font-size: 20px;
+            }
+        }
+    }
+</style>
+<style>
+    .el-carousel {
+        height: 100%;
+    }
+</style>

+ 137 - 16
src/views/layout/components/Navbar.vue

@@ -10,26 +10,94 @@
     <!--<hamburger :toggle-click="toggleSideBar" :is-active="sidebar.opened" class="hamburger-container"/>-->
     <breadcrumb />
     <div class="user">
-      <a href="https://efunimgs.ai160.com/sharedWhiteBoard/智能共享白板.msi">客户端下载</a>
-      <el-dropdown class="avatar-container" trigger="click">
-        <div class="avatar-wrapper">
-          <span class="name">{{ name }}</span>
-          <!--<img src="@/icons/image/vip.png" class="vip">-->
-          <i class="el-icon-arrow-down"/>
+      <a href="https://efunimgs.ai160.com/sharedWhiteBoard/智能共享白板.msi" style="float: left">客户端下载</a>
+      <div class="avatar-wrapper" style="float: left">
+        <img :src="require(`@/assets/fileimg/head.png`)" class="head">
+        <span class="name">测试</span>
+        <i slot="reference" class="el-icon-arrow-down"/>
+      </div>
+      <el-popover
+        placement="right-start"
+        width="400"
+        trigger="click"
+        offset="100">
+        <div class="head-container">
+          <div class="head-title">修改头像</div>
+          <img :src="require(`@/assets/fileimg/head.png`)" class="head-img">
+          <div class="autograph">请输入个性签名</div>
         </div>
-        <el-dropdown-menu slot="dropdown" class="user-dropdown" style="top: 55px">
-          <!--
-          <router-link class="inlineBlock" to="/">
-            <el-dropdown-item>
-              Home
-            </el-dropdown-item>
-          </router-link>
-          -->
+        <el-form ref="ruleForm" :model="ruleForm" label-width="60px" class="demo-ruleForm">
+          <el-form-item label="昵称" style="width: 314px;">
+            <el-input v-model="ruleForm.name" placeholder="请输入昵称" size="mini"/>
+          </el-form-item>
+          <el-form-item label="性别" style="width: 314px;">
+            <el-radio-group v-model="ruleForm.sex">
+              <el-radio label="男"/>
+              <el-radio label="女"/>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="学校" style="width: 314px;">
+            <el-input v-model="ruleForm.school" placeholder="请输入学校" size="mini"/>
+          </el-form-item>
+          <el-form-item label="年级" style="width: 314px;">
+            <el-input v-model="ruleForm.grade" placeholder="请输入年级" size="mini"/>
+          </el-form-item>
+          <el-form-item label="地区" style="width: 314px;">
+            <el-cascader
+              v-model="ruleForm.region"
+              :options="options"
+              placeholder="请选择活动区域"
+              size="mini"/>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="submitForm('ruleForm')">保存</el-button>
+            <el-button type="info" @click="resetForm('ruleForm')">放弃</el-button>
+          </el-form-item>
+        </el-form>
+        <el-button
+          slot="reference"
+          style="width: 50px;height: 50px;position: absolute;top: 20px;right: 0px; opacity: 0;" />
+      </el-popover>
+      <!--
+      <el-dropdown :hide-on-click="false" class="avatar-container" trigger="click">
+        <el-dropdown-menu slot="dropdown" class="user-dropdown" style="top: 55px; width: 463px;">
+          <el-form ref="ruleForm" :model="ruleForm" label-width="60px" class="demo-ruleForm">
+            <el-form-item label="昵称" style="width: 314px;">
+              <el-input v-model="ruleForm.name" placeholder="请输入昵称" size="mini"/>
+            </el-form-item>
+            <el-form-item label="性别" style="width: 314px;">
+              <el-radio-group v-model="ruleForm.sex">
+                <el-radio label="男"/>
+                <el-radio label="女"/>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="学校" style="width: 314px;">
+              <el-input v-model="ruleForm.school" placeholder="请输入学校" size="mini"/>
+            </el-form-item>
+            <el-form-item label="年级" style="width: 314px;">
+              <el-input v-model="ruleForm.grade" placeholder="请输入年级" size="mini"/>
+            </el-form-item>
+            <el-form-item label="地区" style="width: 314px;">
+              <el-cascader
+                v-model="ruleForm.region"
+                :options="options"
+                placeholder="请选择活动区域"
+                size="mini"/>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" @click="submitForm('ruleForm')">保存</el-button>
+              <el-button type="info" @click="resetForm('ruleForm')">放弃</el-button>
+            </el-form-item>
+          </el-form>
+        </el-dropdown-menu>
+      </el-dropdown>
+      -->
+      <!--
           <el-dropdown-item divided style="border: 0">
             <span style="display:block;" @click="logout">退出</span>
           </el-dropdown-item>
         </el-dropdown-menu>
-      </el-dropdown>
+        -->
     </div>
   </el-menu>
 </template>
@@ -37,12 +105,25 @@
 <script>
 import { mapGetters } from 'vuex'
 import Breadcrumb from '@/components/Breadcrumb'
+import city from '@/utils/city'
 // import Hamburger from '@/components/Hamburger'
 export default {
   components: {
     Breadcrumb
     // Hamburger
   },
+  data() {
+    return {
+      ruleForm: {
+        name: '',
+        sex: '',
+        school: '',
+        grade: '',
+        region: []
+      },
+      options: city
+    }
+  },
   computed: {
     ...mapGetters([
       'name',
@@ -74,11 +155,21 @@ export default {
       font-size: 16px;
       color: #4883FB;
       margin-right: 15px;
+      padding-right: 15px;
+      border-right: 1px solid #979797;
+      height: 24px;
+      margin-top: 35px;
+      line-height: 25px;
+    }
+    .head {
+      width: 42px;
+      height: 42px;
+      border-radius: 50%;
     }
   }
   .user-avatar,
   .name,
-  .vip,
+  .head,
   .el-icon-arrow-down {
     vertical-align: middle;
   }
@@ -110,6 +201,36 @@ export default {
       }
     }
   }
+  .el-input {
+    input {
+      width: 300px
+    }
+  }
+}
+</style>
+<style>
+.el-input /deep/ .el-input__icon {
+  position: absolute;
+  right: 0
+}
+.el-popover .head-container {
+  width: 100%;
+  height: 84px;
+  background: #F6F6F6;
+  position: relative;
+  line-height: 84px;
+}
+.head-img {
+  width: 56px;
+  height: 56px;
+  border-radius: 50%;
+  float: left;
+  margin: 14px 24px 0 21px;
+}
+.head-title {
+  position: absolute;
+  top: 0;
+  left: 20px;
 }
 </style>
 

+ 1 - 0
src/views/login/index.vue

@@ -125,6 +125,7 @@ export default {
           this.loading = true
           this.$store.dispatch('loginByPhone', this.loginForm).then((res) => {
             this.loading = false
+            // res.data.id
             setToken(res.data.id)
             this.$router.push({ path: this.redirect || '/' })
           }).catch(() => {