Quellcode durchsuchen

莅临外出 id

y595705120 vor 3 Jahren
Ursprung
Commit
a225362b7d

+ 81 - 0
src/api/paper.js

@@ -0,0 +1,81 @@
+import service from '@/utils/request'
+
+export const getPaperList = (data) => {
+    return service({
+        url: "/admin/getPaperList",
+        method: 'post',
+		data
+    })
+}
+
+export const getPaper = (data) => {
+    return service({
+        url: "/admin/getPaper",
+        method: 'post',
+		data
+    })
+}
+
+export const addPaper = (data) => {
+    return service({
+        url: "/admin/addPaper",
+        method: 'post',
+		data
+    })
+}
+
+export const delPaper = (data) => {
+    return service({
+        url: "/admin/delPaper",
+        method: 'post',
+		data
+    })
+}
+
+export const getPaperMatrixList = (data) => {
+    return service({
+        url: "/admin/getPaperMatrixList",
+        method: 'post',
+		data
+    })
+}
+
+export const addPaperMatrix = (data) => {
+    return service({
+        url: "/admin/addPaperMatrix",
+        method: 'post',
+		data
+    })
+}
+
+export const deladdPaperMatrix = (data) => {
+    return service({
+        url: "/admin/delPaperMatrix",
+        method: 'post',
+		data
+    })
+}
+
+export const getPaperMatrixInfoList = (data) => {
+    return service({
+        url: "/admin/getPaperMatrixInfoList",
+        method: 'post',
+		data
+    })
+}
+
+export const addPaperMatrixInfo = (data) => {
+    return service({
+        url: "/admin/addPaperMatrixInfo",
+        method: 'post',
+		data
+    })
+}
+
+export const delPaperMatrixInfo = (data) => {
+    return service({
+        url: "/admin/delPaperMatrixInfo",
+        method: 'post',
+		data
+    })
+}

+ 76 - 0
src/components/upload/BImage.vue

@@ -0,0 +1,76 @@
+<template>
+	<div>
+		<el-upload class="image-uploader"
+		 action="/admin/upload" 
+		 :headers="{ 'x-token': token }" 
+		 :multiple="false"
+		:show-file-list="false" 
+		:on-success="handleImageSuccess" 
+		:before-upload="beforeImageUpload">
+			<el-button type="primary" :style="{'width': width}" style="margin: 8px auto">
+				{{placeholder}}
+			</el-button>
+		</el-upload>
+	</div>
+</template>
+<script>
+	const path = process.env.VUE_APP_BASE_API;
+	import {mapGetters} from "vuex";
+	import ImageCompress from "@/utils/image.js";
+	export default {
+		name: "upload-image",
+		props: {
+			index: {
+				type: Number,
+				default: 0,
+			},
+			placeholder: {
+				type: String,
+				default: "",
+			},
+			width:{
+			  type: String,
+			  default: "200px",
+			},
+			fileSize: {
+				type: Number,
+				default: 1024, // 1M 超出后执行压缩
+			},
+			maxWH: {
+				type: Number,
+				default: 1080, // 图片长宽上限
+			},
+		},
+		data() {
+			return {
+				path: path,
+			};
+		},
+		computed: {
+			...mapGetters("user", ["userInfo", "token"]),
+		},
+		methods: {
+			beforeImageUpload(file) {
+				let isRightSize = file.size / 1024 < this.fileSize;
+				if (!isRightSize) {
+					let compress = new ImageCompress(file, this.fileSize, this.maxWH);
+					return compress.compress();
+				}
+				return isRightSize;
+			},
+			rmImage() {
+				this.$emit("rmImage");
+			},
+			handleImageSuccess(res) {
+				const {data} = res;
+				if (data) {
+					this.$emit("onFinish", data.url, this.index);
+				}
+			},
+		},
+	};
+</script>
+
+<style lang="scss" scoped>
+	
+</style>

+ 0 - 1
src/components/upload/image.vue

@@ -6,7 +6,6 @@
       :headers="{ 'x-token': token }"
 	  :multiple="false"
       :show-file-list="false"
-	  drag
       :on-success="handleImageSuccess"
       :before-upload="beforeImageUpload"
     >

+ 9 - 0
src/components/viewer/index.js

@@ -0,0 +1,9 @@
+import VueViewer from './viewer/index.vue';
+let obj = {};
+obj.install = function(Vue) {
+  Vue.component(VueViewer.name, VueViewer);
+};
+export {
+  VueViewer
+};
+export default obj.install;

BIN
src/components/viewer/viewer/images/icons.png


BIN
src/components/viewer/viewer/images/null.png


+ 161 - 0
src/components/viewer/viewer/index.vue

@@ -0,0 +1,161 @@
+<template>
+  <span>
+    <template v-if="Array.isArray(thumb)">
+      <ul :class="listUlClass">
+        <li v-for="(img, index) in thumb" :key="index" style="position:relative">
+          <img :width="width" :height="height" @click="showFullViewer(index)" 
+            :src="img" alt=""/>
+          <slot :index="index"></slot>
+        </li>
+      </ul>
+    </template>
+    <template v-else>
+      <img :width="width" :height="height" @click="showFullViewer" :onerror="errorImg"
+      :src="thumb" alt="">
+    </template>
+    <transition name="fade"
+      enter-active-class="fadeIn"
+      leave-active-class="fadeOut">
+      <div v-show="fullViewerVisible" class="viewer-container viewer-backdrop viewer-fixed viewer-fade viewer-transition viewer-in"
+        touch-action="none" style="z-index: 2015;">
+        <div class="viewer-canvas" data-viewer-action="hide">
+          <img ref="fullImage" @mousewheel="toggleZoomFullImage"
+            :src="Array.isArray(full) ? full[listActiveIndex] : full"
+            id="full-image" alt="" class="viewer-move full-image animate-transform"
+            :style="fullImageStyle" />
+        </div>
+        <div class="viewer-footer">
+          <div class="viewer-title">
+          {{multiple ? title[listActiveIndex] || '-' : title}} ({{fullImageWidth}} &times; {{fullImageHeight}})
+          </div>
+          <div class="viewer-toolbar">
+            <ul>
+              <li role="button" class="viewer-zoom-in" @click="zoomIn" data-viewer-action="zoom-in"></li>
+              <li role="button" class="viewer-zoom-out" @click="zoomOut" data-viewer-action="zoom-out"></li>
+              <li role="button" class="viewer-one-to-one" @click="resetFullImageSize" data-viewer-action="one-to-one"></li>
+              <li role="button" class="viewer-reset" @click="resetFullImage" data-viewer-action="reset"></li>
+              <li role="button" class="viewer-prev" @click="prev" v-if="multiple" data-viewer-action="prev"></li>
+              <li role="button" class="viewer-play viewer-large" @click="fullScreenPlay" v-if="multiple" data-viewer-action="play"></li>
+              <li role="button" class="viewer-next" @click="next" v-if="multiple" data-viewer-action="next"></li>
+              <li role="button" class="viewer-rotate-left" @click="fullImageRotateLeft" data-viewer-action="rotate-left"></li>
+              <li role="button" class="viewer-rotate-right" @click="fullImageRotateRight" data-viewer-action="rotate-right"></li>
+              <li role="button" class="viewer-flip-horizontal" @click="toggleFullImageScaleX" data-viewer-action="flip-horizontal"></li>
+              <li role="button" class="viewer-flip-vertical" @click="toggleFullImageScaleY" data-viewer-action="flip-vertical"></li>
+            </ul>
+          </div>
+          <div class="viewer-navbar" v-show="multiple">
+            <ul v-if="multiple" class="viewer-list viewer-transition" :style="listStyle">
+              <li v-for="(item, index) in thumb"
+                :key="index"
+                @click="switchActiveIndex(index)"
+                :class="{'viewer-active': listActiveIndex === index}">
+                <img :src="item" role="button" data-viewer-action="view" data-index="0"
+                  data-original-url="images/tibet-1.jpg" alt="Cuo Na Lake" data-filled="true"
+                  style="width: 50px; height: 50px; transform: translateX(-10px);" />
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="viewer-tooltip viewer-show viewer-fade viewer-transition">
+          1%
+        </div>
+        <div role="button" @click="hideFullViewer" class="viewer-button viewer-close" data-viewer-action="mix"></div>
+        <div class="viewer-player"></div>
+      </div>
+    </transition>
+  </span>
+</template>
+<script>
+import MxinMethods from './mixin-methods';
+require('vue2-animate/dist/vue2-animate.min.css');
+export default {
+  name: 'vue-viewer',
+  mixins: [MxinMethods],
+  data() {
+    return {
+      animateTimer: null,
+      fullPlayTimer: null,
+      fullViewerVisible: false,
+      fullViewZoom: 1,
+      fullImageWidth: 0,
+      fullImageHeight: 0,
+      fullImageMoveX: 0,
+      fullImageMoveY: 0,
+      fullImageRotateX: 0,
+      fullImageRotateY: 0,
+      fullImageScaleX: 0,
+      fullImageScaleY: 0,
+      listActiveIndex: 0,
+	  errorImg:'this.src="' + require('./images/null.png') + '"'
+    };
+  },
+  props: {
+    thumb: {
+      required: false,
+    },
+    full: {
+      required: false,
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    listUlClass: {
+      type: String,
+      required: false
+    },
+	width: {
+	  type: String,
+	  default: '100'
+	},
+	height: {
+	  type: String,
+	  default: '80'
+	},
+    title: {
+      required: false,
+      default: '-'
+    }
+  },
+  computed: {
+    fullImageMarginLeft() {
+      return 0 - this.$data.fullImageWidth / 2 + this.$data.fullImageMoveX;
+    },
+    fullImageMarginTop() {
+      return 0 - this.$data.fullImageHeight / 2 - 87 + this.$data.fullImageMoveY;
+    },
+    // 大图样式
+    fullImageStyle() {
+      return {
+        // eslint-disable-next-line max-len
+        transform: `scale(${this.$data.fullViewZoom}) rotate(${this.$data.fullImageRotateX}deg) ${this.$data.fullImageScaleX === 0 ? '' : 'scaleX(' + -1 + ')' } ${this.$data.fullImageScaleY === 0 ? '' : 'scaleY(' + -1 + ')' }`,
+        width: this.$data.fullImageWidth + 'px',
+        height: this.$data.fullImageHeight + 'px',
+        'margin-left': this.fullImageMarginLeft + 'px',
+        'margin-top': this.fullImageMarginTop + 'px',
+        position: 'absolute',
+        left: '50%', top: '50%'
+      };
+    },
+    // 列表的宽度
+    listStyle() {
+      return {
+        width: Array.isArray(this.thumb) ? this.thumb.length * 31 + 'px' : 0,
+        marginLeft: document.body.clientWidth / 2 - (this.$data.listActiveIndex + 1) * 31 + 'px'
+      };
+    }
+  },
+  methods: {},
+  mounted() {
+    this.resetFullImage();
+    this.addFullScreenListener();
+    this.$refs['fullImage'].addEventListener('mousedown', () => {
+      document.body.addEventListener('mousemove', this.mouseMove);
+    });
+    this.$refs['fullImage'].addEventListener('mouseup', () => {
+      document.body.removeEventListener('mousemove', this.mouseMove);
+    });
+  }
+};
+</script>
+<style src="./style.css" scoped></style>

+ 202 - 0
src/components/viewer/viewer/mixin-methods.js

@@ -0,0 +1,202 @@
+/* eslint-disable no-nested-ternary */
+export default {
+  methods: {
+    /**
+     * 全屏显示
+     * @param {Object} el 要全屏显示的dom节点
+     */
+    fullScreen(el) {
+      const isFullscreen=document.fullScreen||document.mozFullScreen||document.webkitIsFullScreen;
+      if (!isFullscreen) { // 进入全屏,多重短路表达式
+        (el.requestFullscreen&&el.requestFullscreen())||
+        (el.mozRequestFullScreen&&el.mozRequestFullScreen())||
+        (el.webkitRequestFullscreen&&el.webkitRequestFullscreen())||(el.msRequestFullscreen&&el.msRequestFullscreen());
+      } else {	// 退出全屏,三目运算符
+        document.exitFullscreen?document.exitFullscreen():
+          document.mozCancelFullScreen?document.mozCancelFullScreen():
+            document.webkitExitFullscreen?document.webkitExitFullscreen():'';
+      }
+    },
+    /**
+     * 重置大图的状态
+     * @param {*} index
+     */
+    resetFullImageStatus(index) {
+      this.$data.listActiveIndex = index;
+      var img = this.$refs['fullImage'];
+      if (!img) return false;
+      img.style.display = 'none';
+      setTimeout(() => {
+        let fullImageSizeAry = this.getImgNaturalStyle(img);
+        this.$data.fullImageWidth = fullImageSizeAry[0];
+        this.$data.fullImageHeight = fullImageSizeAry[1];
+        img.style.display = '';
+      }, 300);
+    },
+    /**
+     * 显示大图,如果是多图需要指定显示的图片的序号
+     * @param {Number} index
+     */
+    showFullViewer(index) {
+      this.$data.fullViewerVisible = true;
+      this.resetFullImageStatus(index);
+    },
+    switchActiveIndex(index) {
+      this.resetFullImageStatus(index);
+    },
+    hideFullViewer() {
+      this.$data.fullViewerVisible = false;
+    },
+    /**
+     * 放大
+     */
+    zoomIn() {
+      this.$data.fullViewZoom += 0.1;
+    },
+    /**
+     * 缩小
+     */
+    zoomOut() {
+      this.$data.fullViewZoom -= 0.1;
+    },
+    /**
+     * 大图鼠标滚轮
+     */
+    toggleZoomFullImage(obj) {
+      // const zoom = parseInt(obj.style.zoom,10)||100;
+      if (this.$data.animateTimer) {
+        clearTimeout(this.$data.animateTimer);
+        this.$data.animateTimer = null;
+      }
+      obj.target.classList.remove('animate-transform');
+      const zoom = obj.wheelDelta / 12;
+      if (zoom > 0) {
+        this.$data.fullViewZoom += 0.1;
+      } else if (this.$data.fullViewZoom > 1) {
+        this.$data.fullViewZoom -= 0.1;
+      }
+      this.$data.animateTimer = setTimeout(() => {
+        obj.target.classList.add('animate-transform');
+      }, 400);
+    },
+    /**
+     * 重置大小
+     */
+    resetFullImageSize() {
+      this.$data.fullViewZoom = 1;
+    },
+    /**
+     * 获取src指向的图片的宽高尺寸
+     */
+    getImgNaturalStyle(img, callback) {
+      var nWidth, nHeight;
+      if (img.naturalWidth) { // 现代浏览器
+        nWidth = img.naturalWidth;
+        nHeight = img.naturalHeight;
+      } else {  // IE6/7/8
+        var image = new Image();
+        image.src = img.src;
+        image.onload = function() {
+          callback(image.width, image.height);
+        };
+      }
+      return [nWidth, nHeight];
+    },
+    /**
+     * 拖拽大图
+     */
+    mouseMove(e) {
+      e.preventDefault();
+      this.$data.fullImageMoveX += e.movementX;
+      this.$data.fullImageMoveY += e.movementY;
+    },
+    /**
+     * 重置大图的状态
+     */
+    resetFullImage() {
+      this.$data.fullViewZoom = 1;
+      this.$data.fullImageMoveX = 0;
+      this.$data.fullImageMoveY = 0;
+      this.$data.fullImageMoveX = 0;
+      this.$data.fullImageMoveY = 0;
+      this.$data.fullImageRotateX = 0;
+      this.$data.fullImageScaleX = 0;
+      this.$data.fullImageScaleY = 0;
+    },
+    /**
+     * 水平方向上逆时针旋转
+     */
+    fullImageRotateLeft() {
+      this.$data.fullImageRotateX -= 90;
+    },
+    /**
+     * 水平方向上顺时针旋转
+     */
+    fullImageRotateRight() {
+      this.$data.fullImageRotateX += 90;
+    },
+    /**
+     * 水平方向翻转
+     */
+    toggleFullImageScaleX() {
+      this.$data.fullImageScaleX = this.$data.fullImageScaleX === 0 ? -1 : 0;
+    },
+    /**
+     * 垂直方向翻转
+     */
+    toggleFullImageScaleY() {
+      this.$data.fullImageScaleY = this.$data.fullImageScaleY === 0 ? -1 : 0;
+    },
+    prev() {
+      if (this.$data.listActiveIndex >= 1) {
+        this.resetFullImage();
+        this.switchActiveIndex(this.$data.listActiveIndex - 1);
+      }
+    },
+    next() {
+      if (this.$data.listActiveIndex < this.thumb.length - 1) {
+        this.resetFullImage();
+        this.switchActiveIndex(this.$data.listActiveIndex + 1);
+      }
+    },
+    handleFullScreenChange() {
+      const isFullscreen = document.fullScreen||document.mozFullScreen||document.webkitIsFullScreen;
+      if (!isFullscreen && this.$data.fullPlayTimer) {
+        clearInterval(this.$data.fullPlayTimer);
+        this.$data.fullPlayTimer = null;
+      }
+    },
+    /**
+     * 监听全屏状态的变化
+     */
+    addFullScreenListener() {
+      document.addEventListener('fullscreenchange', () => {
+        this.handleFullScreenChange();
+      });
+      document.addEventListener('mozfullscreenchange', () => {
+        this.handleFullScreenChange();
+      });
+      document.addEventListener('webkitfullscreenchange', () => {
+        this.handleFullScreenChange();
+      });
+      document.addEventListener('msfullscreenchange', () => {
+        this.handleFullScreenChange();
+      });
+    },
+    /**
+     * 点击播放按钮进入全拼播放
+     */
+    fullScreenPlay() {
+      this.fullScreen(this.$el.querySelector('.full-image'));
+      this.$data.fullPlayTimer = setInterval(() => {
+        const currIndex = this.$data.listActiveIndex;
+        if (currIndex >= this.thumb.length - 1) {
+          this.$data.listActiveIndex = 0;
+        } else {
+          this.$data.listActiveIndex = currIndex + 1;
+        }
+        this.switchActiveIndex(this.$data.listActiveIndex);
+      }, 2000);
+    }
+  }
+};

+ 393 - 0
src/components/viewer/viewer/style.css

@@ -0,0 +1,393 @@
+.viewer-zoom-in::before,
+.viewer-zoom-out::before,
+.viewer-one-to-one::before,
+.viewer-reset::before,
+.viewer-prev::before,
+.viewer-play::before,
+.viewer-next::before,
+.viewer-rotate-left::before,
+.viewer-rotate-right::before,
+.viewer-flip-horizontal::before,
+.viewer-flip-vertical::before,
+.viewer-fullscreen::before,
+.viewer-fullscreen-exit::before,
+.viewer-close::before {
+  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAAUCAYAAABWOyJDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAQPSURBVHic7Zs/iFxVFMa/0U2UaJGksUgnIVhYxVhpjDbZCBmLdAYECxsRFBTUamcXUiSNncgKQbSxsxH8gzAP3FU2jY0kKKJNiiiIghFlccnP4p3nPCdv3p9778vsLOcHB2bfveeb7955c3jvvNkBIMdxnD64a94GHMfZu3iBcRynN7zAOI7TG15gHCeeNUkr8zaxG2lbYDYsdgMbktBsP03jdQwljSXdtBhLOmtjowC9Mg9L+knSlcD8TNKpSA9lBpK2JF2VdDSR5n5J64m0qli399hNFMUlpshQii5jbXTbHGviB0nLNeNDSd9VO4A2UdB2fp+x0eCnaXxWXGA2X0au/3HgN9P4LFCjIANOJdrLr0zzZ+BEpNYDwKbpnQMeAw4m8HjQtM6Z9qa917zPQwFr3M5KgA6J5rTJCdFZJj9/lyvGhsDvwFNVuV2MhhjrK6b9bFiE+j1r87eBl4HDwCF7/U/k+ofAX5b/EXBv5JoLMuILzf3Ap6Z3EzgdqHMCuF7hcQf4HDgeoHnccncqdK/TvSDWffFXI/exICY/xZyqc6XLWF1UFZna4gJ7q8BsRvgd2/xXpo6P+D9dfT7PpECtA3cnWPM0GXGFZh/wgWltA+cDNC7X+AP4GzjZQe+k5dRxuYPeiuXU7e1qwLpDz7dFjXKRaSwuMLvAlG8zZlG+YmiK1HoFqT7wP2z+4Q45TfEGcMt01xLoNZEBTwRqD4BLpnMLeC1A41UmVxsXgXeBayV/Wx20rpTyrpnWRft7p6O/FdqzGrDukPNtkaMoMo3FBdBSQMOnYBCReyf05s126fU9ytfX98+mY54Kxnp7S9K3kj6U9KYdG0h6UdLbkh7poFXMfUnSOyVvL0h6VtIXHbS6nOP+s/Zm9mvyXW1uuC9ohZ72E9uDmXWLJOB1GxsH+DxPftsB8B6wlGDN02TAkxG6+4D3TWsbeC5CS8CDFce+AW500LhhOW2020TRjK3b21HEmgti9m0RonxbdMZeVzV+/4tF3cBpP7E9mKHNL5q8h5g0eYsCMQz0epq8gQrwMXAgcs0FGXGFRcB9wCemF9PkbYqM/Bas7fxLwNeJPdTdpo4itQti8lPMqTpXuozVRVXPpbHI3KkNTB1NfkL81j2mvhDp91HgV9MKuRIqrykj3WPq4rHyL+axj8/qGPmTqi6F9YDlHOvJU6oYcTsh/TYSzWmTE6JT19CtLTJt32D6CmHe0eQn1O8z5AXgT4sx4Vcu0/EQecMydB8z0hUWkTd2t4CrwNEePqMBcAR4mrBbwyXLPWJa8zrXmmLEhNBmfpkuY2102xxrih+pb+ieAb6vGhuA97UcJ5KR8gZ77K+99xxeYBzH6Q3/Z0fHcXrDC4zjOL3hBcZxnN74F+zlvXFWXF9PAAAAAElFTkSuQmCC");
+  background-repeat: no-repeat;
+  color: transparent;
+  display: block;
+  font-size: 0;
+  height: 20px;
+  line-height: 0;
+  width: 20px;
+}
+
+.viewer-zoom-in::before {
+  background-position: 0 0;
+  content: "Zoom In";
+}
+
+.viewer-zoom-out::before {
+  background-position: -20px 0;
+  content: "Zoom Out";
+}
+
+.viewer-one-to-one::before {
+  background-position: -40px 0;
+  content: "One to One";
+}
+
+.viewer-reset::before {
+  background-position: -60px 0;
+  content: "Reset";
+}
+
+.viewer-prev::before {
+  background-position: -80px 0;
+  content: "Previous";
+}
+
+.viewer-play::before {
+  background-position: -100px 0;
+  content: "Play";
+}
+
+.viewer-next::before {
+  background-position: -120px 0;
+  content: "Next";
+}
+
+.viewer-rotate-left::before {
+  background-position: -140px 0;
+  content: "Rotate Left";
+}
+
+.viewer-rotate-right::before {
+  background-position: -160px 0;
+  content: "Rotate Right";
+}
+
+.viewer-flip-horizontal::before {
+  background-position: -180px 0;
+  content: "Flip Horizontal";
+}
+
+.viewer-flip-vertical::before {
+  background-position: -200px 0;
+  content: "Flip Vertical";
+}
+
+.viewer-fullscreen::before {
+  background-position: -220px 0;
+  content: "Enter Full Screen";
+}
+
+.viewer-fullscreen-exit::before {
+  background-position: -240px 0;
+  content: "Exit Full Screen";
+}
+
+.viewer-close::before {
+  background-position: -260px 0;
+  content: "Close";
+}
+
+.viewer-container {
+  bottom: 0;
+  direction: ltr;
+  font-size: 0;
+  left: 0;
+  line-height: 0;
+  overflow: hidden;
+  position: absolute;
+  right: 0;
+  -webkit-tap-highlight-color: transparent;
+  top: 0;
+  -webkit-touch-callout: none;
+  touch-action: none;
+  user-select: none;
+}
+.viewer-container::selection, .viewer-container *::selection {
+  background-color: transparent;
+}
+.viewer-container img {
+  display: block;
+  height: auto;
+  max-height: none !important;
+  max-width: none !important;
+  min-height: 0 !important;
+  min-width: 0 !important;
+  width: 100%;
+}
+
+.viewer-canvas {
+  bottom: 0;
+  left: 0;
+  overflow: hidden;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+.viewer-canvas > img {
+  height: auto;
+  margin: 15px auto;
+  max-width: 90% !important;
+  width: auto;
+}
+
+.viewer-footer {
+  bottom: 0;
+  left: 0;
+  overflow: hidden;
+  position: absolute;
+  right: 0;
+  text-align: center;
+}
+
+.viewer-navbar {
+  background-color: rgba(0, 0, 0, 0.5);
+  overflow: hidden;
+}
+
+.viewer-list {
+  box-sizing: content-box;
+  height: 50px;
+  margin: 0;
+  overflow: hidden;
+  padding: 1px 0;
+}
+.viewer-list > li {
+  color: transparent;
+  cursor: pointer;
+  float: left;
+  font-size: 0;
+  height: 50px;
+  line-height: 0;
+  opacity: 0.5;
+  overflow: hidden;
+  transition: opacity 0.15s;
+  width: 30px;
+}
+.viewer-list > li:hover {
+  opacity: 0.75;
+}
+.viewer-list > li + li {
+  margin-left: 1px;
+}
+.viewer-list > .viewer-loading {
+  position: relative;
+}
+.viewer-list > .viewer-loading::after {
+  border-width: 2px;
+  height: 20px;
+  margin-left: -10px;
+  margin-top: -10px;
+  width: 20px;
+}
+.viewer-list > .viewer-active, .viewer-list > .viewer-active:hover {
+  opacity: 1;
+}
+
+.viewer-player {
+  background-color: #000;
+  bottom: 0;
+  cursor: none;
+  display: none;
+  left: 0;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+.viewer-player > img {
+  left: 0;
+  position: absolute;
+  top: 0;
+}
+
+.viewer-toolbar > ul {
+  display: inline-block;
+  margin: 0 auto 5px;
+  overflow: hidden;
+  padding: 3px 0;
+}
+.viewer-toolbar > ul > li {
+  background-color: rgba(0, 0, 0, 0.5);
+  border-radius: 50%;
+  cursor: pointer;
+  float: left;
+  height: 24px;
+  overflow: hidden;
+  transition: background-color 0.15s;
+  width: 24px;
+}
+.viewer-toolbar > ul > li:hover {
+  background-color: rgba(0, 0, 0, 0.8);
+}
+.viewer-toolbar > ul > li::before {
+  margin: 2px;
+}
+.viewer-toolbar > ul > li + li {
+  margin-left: 1px;
+}
+.viewer-toolbar > ul > .viewer-small {
+  height: 18px;
+  margin-bottom: 3px;
+  margin-top: 3px;
+  width: 18px;
+}
+.viewer-toolbar > ul > .viewer-small::before {
+  margin: -1px;
+}
+.viewer-toolbar > ul > .viewer-large {
+  height: 30px;
+  margin-bottom: -3px;
+  margin-top: -3px;
+  width: 30px;
+}
+.viewer-toolbar > ul > .viewer-large::before {
+  margin: 5px;
+}
+
+.viewer-tooltip {
+  background-color: rgba(0, 0, 0, 0.8);
+  border-radius: 10px;
+  color: #fff;
+  display: none;
+  font-size: 12px;
+  height: 20px;
+  left: 50%;
+  line-height: 20px;
+  margin-left: -25px;
+  margin-top: -10px;
+  position: absolute;
+  text-align: center;
+  top: 50%;
+  width: 50px;
+}
+
+.viewer-title {
+  color: #ccc;
+  display: inline-block;
+  font-size: 12px;
+  line-height: 1;
+  margin: 0 5% 5px;
+  max-width: 90%;
+  opacity: 0.8;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  transition: opacity 0.15s;
+  white-space: nowrap;
+}
+.viewer-title:hover {
+  opacity: 1;
+}
+
+.viewer-button {
+  background-color: rgba(0, 0, 0, 0.5);
+  border-radius: 50%;
+  cursor: pointer;
+  height: 80px;
+  overflow: hidden;
+  position: absolute;
+  right: -40px;
+  top: -40px;
+  transition: background-color 0.15s;
+  width: 80px;
+}
+.viewer-button:focus, .viewer-button:hover {
+  background-color: rgba(0, 0, 0, 0.8);
+}
+.viewer-button::before {
+  bottom: 15px;
+  left: 15px;
+  position: absolute;
+}
+
+.viewer-fixed {
+  position: fixed;
+}
+
+.viewer-open {
+  overflow: hidden;
+}
+
+.viewer-show {
+  display: block;
+}
+
+.viewer-hide {
+  display: none;
+}
+
+.viewer-backdrop {
+  background-color: rgba(0, 0, 0, 0.5);
+}
+
+.viewer-invisible {
+  visibility: hidden;
+}
+
+.viewer-move {
+  cursor: move;
+  cursor: grab;
+}
+
+.viewer-fade {
+  opacity: 0;
+}
+
+.viewer-in {
+  opacity: 1;
+}
+
+.viewer-transition {
+  transition: all 0.3s;
+}
+
+@keyframes viewer-spinner {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+.viewer-loading::after {
+  animation: viewer-spinner 1s linear infinite;
+  border: 4px solid rgba(255, 255, 255, 0.1);
+  border-left-color: rgba(255, 255, 255, 0.5);
+  border-radius: 50%;
+  content: "";
+  display: inline-block;
+  height: 40px;
+  left: 50%;
+  margin-left: -20px;
+  margin-top: -20px;
+  position: absolute;
+  top: 50%;
+  width: 40px;
+  z-index: 1;
+}
+
+@media (max-width: 767px) {
+  .viewer-hide-xs-down {
+    display: none;
+  }
+}
+@media (max-width: 991px) {
+  .viewer-hide-sm-down {
+    display: none;
+  }
+}
+@media (max-width: 1199px) {
+  .viewer-hide-md-down {
+    display: none;
+  }
+}
+.full-image{
+  transition: width .5s, height .5s;
+  transform-origin: 50% 50%;
+}
+.full-image.animate-transform{
+  transition: transform .5s;
+}

+ 6 - 3
src/main.js

@@ -7,9 +7,12 @@ import 'element-ui/lib/theme-chalk/index.css';
 ElementUI.Dialog.props.closeOnClickModal.default = false
 Vue.use(ElementUI);
 Vue.component(ElementUI.Message)
-import Viewer from 'v-viewer'
-import 'viewerjs/dist/viewer.css'
-Vue.use(Viewer);
+// import Viewer from 'v-viewer'
+// import 'viewerjs/dist/viewer.css'
+// Vue.use(Viewer);
+
+import ImageViewer from '@/components/viewer';
+Vue.use(ImageViewer);
 
 Vue.prototype.$message.successMsg = function (msg, duration=3) {
     return ElementUI.Message.success({

+ 116 - 0
src/style/paper.css

@@ -0,0 +1,116 @@
+.m-account {
+  position: relative;
+  margin-left: 10px;
+}
+.m-account .account-tit {
+  height: 30px;
+  padding-bottom: 5px;
+  border-bottom: 1px solid #ddd;
+  margin-bottom: 10px;
+  box-sizing: content-box;
+}
+.m-account .account-tit a {
+  font-size: 16px;
+  display: inline-block;
+  line-height: 29px;
+  margin-right: 30px;
+  padding: 0 15px 5px;
+}
+.m-account .account-tit a:hover {
+  color: #3290d4;
+  text-decoration: none;
+}
+.m-account .account-tit .current {
+  color: #3290d4;
+  border-bottom: 3px solid #3290d4;
+}
+.m-account .account-tit .ui-btn {
+  height: 28px;
+  line-height: 28px;
+  padding: 0 15px;
+  margin-right: 0;
+  font-size: 14px;
+}
+.m-account .account-tit .ui-btn:hover {
+  color: #fff;
+}
+.m-account .ul-form {
+  margin-bottom: 30px;
+}
+.m-account .ul-form li {
+  line-height: 35px;
+}
+.m-account .ul-form li .a-txt {
+  color: #3290d4;
+  text-decoration: underline;
+}
+.m-account .ul-form li .ui-btn {
+  width: 120px;
+  height: 35px;
+  line-height: 35px;
+  margin-top: 10px;
+}
+.m-account .ul-form .l-t {
+  width: 160px;
+}
+.m-account .ul-form .ipt {
+  width: 278px;
+  color: #777;
+  line-height: 1.5;
+}
+.m-account .ul-form .ipt-m {
+  width: 100px;
+}
+.m-account .ul-form .w4 {
+  width: 400px;
+}
+.m-account .ul-form-2 {
+  width: auto;
+  border: 1px solid #ddd;
+  padding: 10px 0;
+}
+.m-account .ul-form-2 li {
+  margin-bottom: 0;
+}
+.m-account .ul-form-2 .l-t {
+  width: 100px;
+}
+.m-account .m-img {
+  position: absolute;
+  top: 90px;
+  right: 50px;
+}
+.m-account .m-img img {
+  width: 160px;
+  height: 160px;
+  display: block;
+  border: 1px solid #ddd;
+  padding: 5px;
+  background-color: #fff;
+}
+.m-account .upload {
+  width: 100px;
+  height: 30px;
+  position: relative;
+  display: inline-block;
+  overflow: hidden;
+  cursor: pointer;
+}
+.m-account .upload:hover .btn-o {
+  background-color: #ffbe51;
+}
+.m-account .upload .ui-btn {
+  width: 100px;
+  height: 30px;
+  line-height: 30px;
+}
+.m-account .upload .file {
+  position: absolute;
+  top: 0;
+  left: 0;
+  font-size: 24px;
+  cursor: pointer;
+  opacity: 0;
+  filter: alpha(opacity=0);
+  text-indent: -999px;
+}

+ 5 - 0
src/utils/date.js

@@ -66,4 +66,9 @@ export function getDate( days ) {
     var d = new Date();
     d.setDate(d.getDate() + days);
     return toDate( d )
+}
+
+export function getStr( info ) {	
+	if( !info ) return '';
+	return (''+info).trim();
 }

+ 12 - 7
src/view/import/out/components/IUploadOut.vue

@@ -45,7 +45,7 @@
 <script>
 import UploadExcelComponent from '@/components/UploadExcel/index.vue'
 import { importOutList } from "@/api/importOut.js";
-import {excelDate} from "@/utils/date.js"
+import {excelDate,getStr} from "@/utils/date.js"
 export default {
   name: 'UploadExcel',
   components: { UploadExcelComponent },
@@ -88,11 +88,16 @@ export default {
 		importOutList( param ).then( res=>{
 			if(res.code == 200){
 				let logId = res.data.id;
-				this.$router.push( {name:'import-out-info', query:{logId}})
+				this.$emit("finish", logId)
 			}
 		})	
 	},
 	checkData( data ){
+		if( !data.post ) return `[${data.username}]职务不能为空`;
+		if( !data.reasons ) return `[${data.username}]外出事由不能为空`;
+		if( !data.fromDate ) return `[${data.username}]外出时间不能为空`;
+		if( !data.toDate ) return `[${data.username}]回来时间不能为空`;
+		if( !data.signName && !data.signConfirm ) return `[${data.username}]至少一个签批人`;
 		return false
 	},
 	deleteRow(index){
@@ -106,13 +111,13 @@ export default {
 	  ).map( item=>{
 		  // 姓名,性别 身份证号, 手机号, 学历, 工作单位,岗位名称, 证书编号,继续教育年份
 		return {
-			username: 	(''+item["姓名"]||'').trim(),
-			post: 	(''+item["职务"]||'').trim(),
-			reasons: 		(''+item["外出事由"]||'').trim(),
+			username: 	getStr(item["姓名"]),
+			post: 		getStr(item["职务"]),
+			reasons: 	getStr(item["外出事由"]),
 			fromDate: 	excelDate(item["外出时间"]),
 			toDate: 	excelDate(item["回来时间"]),
-			signName: (''+item['签批人1']||'').trim(),
-			signConfirm: (''+item["签批人2"]||'').trim(),
+			signName:	getStr(item["签批人1"]),
+			signConfirm: getStr(item["签批人2"]),
 			edit: false,
 		}
 	  })

+ 5 - 1
src/view/import/out/index.vue

@@ -63,7 +63,7 @@
     ></el-pagination>
 	
 	<el-dialog title="外出excel导入" center :visible.sync="openCourseDialog" :fullscreen="true">
-		<UploadModel> </UploadModel>
+		<UploadModel @finish="finishImport"> </UploadModel>
 	</el-dialog>
 	
   </div>
@@ -93,6 +93,10 @@ export default {
       this.pageSize = 10;
       this.getTableData();
     },
+	finishImport(logId){
+		this.openCourseDialog = false;
+		this.$router.push( {name:'import-out-info', query:{logId}})
+	},
     gotoDetail( row ) {
 	  let logId = row.id; 
       this.$router.push( {name:'import-out-info', query:{logId}})

+ 15 - 9
src/view/import/visit/components/IUploadVisit.vue

@@ -47,7 +47,8 @@
 <script>
 import UploadExcelComponent from '@/components/UploadExcel/index.vue'
 import { importVisitList } from "@/api/importVisit.js";
-import {excelDate} from "@/utils/date.js"
+import {excelDate, getStr} from "@/utils/date.js"
+
 export default {
   name: 'UploadExcel',
   components: { UploadExcelComponent },
@@ -90,12 +91,17 @@ export default {
 		importVisitList( param ).then( res=>{
 			if(res.code == 200){
 				let logId = res.data.id;
-				this.$router.push( {name:'import-visit-info', query:{logId}})
+				this.$emit("finish", logId)
 			}
 		})	
 	},
 	checkData( data ){
-		
+		if( !data.post ) return `[${data.username}]职务不能为空`;
+		if( !data.tripSummary ) return `[${data.username}]行程概要不能为空`;
+		if( !data.organUnit ) return `[${data.username}]机关单位不能为空`;
+		if( !data.recvDate ) return `[${data.username}]来文日期不能为空`;
+		if( !data.fromDate ) return `[${data.username}]莅临时间不能为空`;
+		if( !data.toDate ) return `[${data.username}]返程时间不能为空`;
 		return false
 	},
 	deleteRow(index){
@@ -108,15 +114,15 @@ export default {
 	  ).map( item=>{
 		  // 姓名,职务,行程概要,陪同情况,机关单位,来文日期,莅临时间,返程时间,拟办意见
 		return {
-			username: 	(''+item["姓名"]||'').trim(),
-			post: 	(''+item["职务"]||'').trim(),
-			tripSummary: 		(''+item["行程概要"]||'').trim(),
-			accompany: 		(''+item["陪同情况"]||'').trim(),
-			organUnit: 		(''+item["机关单位"]||'').trim(),
+			username: 	getStr(item["姓名"]),
+			post: 		getStr(item["职务"]),
+			tripSummary: getStr(item["行程概要"]),
+			accompany: 	getStr(item["陪同情况"]),
+			organUnit: 	getStr(item["机关单位"]),
 			recvDate: 	excelDate(item["来文日期"]),
 			fromDate: 	excelDate(item["莅临时间"]),
 			toDate: 	excelDate(item["返程时间"]),
-			proposed: (''+(item["拟办意见"]||'')).trim(),
+			proposed: 	getStr(item["拟办意见"]),
 			edit: false,
 		}
 	  })

+ 5 - 1
src/view/import/visit/index.vue

@@ -63,7 +63,7 @@
     ></el-pagination>
 	
 	<el-dialog title="莅临excel导入" center :visible.sync="openCourseDialog" :fullscreen="true">
-		<UploadModel> </UploadModel>
+		<UploadModel @finish="finishImport()"> </UploadModel>
 	</el-dialog>
 	
   </div>
@@ -93,6 +93,10 @@ export default {
       this.pageSize = 10;
       this.getTableData();
     },
+	finishImport(logId){
+		this.openCourseDialog = false;
+		this.$router.push( {name:'import-visit-info', query:{logId}})
+	},
     gotoDetail( row ) {
 	  let logId = row.id; 
       this.$router.push( {name:'import-visit-info', query:{logId}})

+ 84 - 0
src/view/weixin/components/Inode.vue

@@ -0,0 +1,84 @@
+<template>
+	<div>
+		<el-row v-for="item in list" class="p5" style="border: 1px solid #E9E9E9; ">
+			<block v-if="item.type=='image'">
+				<el-col :span="8" >
+					<img :src="tow60(item.image)" width="300px" height="150px"></img>
+				</el-col>
+				<el-col :span="8">
+					<el-form :inline="true">
+						<el-form-item label="描述">
+							<el-input v-model="item.desc" class="w230"></el-input>
+						</el-form-item>
+						<el-form-item label="样式">
+							<el-input v-model="item.style" class="w230"></el-input>
+						</el-form-item>
+						<el-form-item label="跳转id">
+							<el-input v-model="item.link" class="w230"></el-input>
+						</el-form-item>
+					</el-form>
+				</el-col>
+				<el-col :span="8">
+					<el-form :inline="true">
+						<el-form-item label="图文描述">
+							<el-input v-model="item.marks" class="w230"></el-input>
+						</el-form-item>
+						<el-form-item label="图文样式">
+							<el-input v-model="item.marksStyle" class="w230"></el-input>
+						</el-form-item>
+						
+					</el-form>
+				</el-col>
+			</block>
+			
+			<block v-if="item.type=='video'">
+				<el-col :span="8">
+					<video  width="300px" height="150px"
+					webkit-playsinline playsinline x-webkit-airplay x5-playsinline preload="preload" :poster="item.poster" controls :src="item.video"></video>
+				</el-col>
+				<el-col :span="8">
+					<el-form :inline="true">
+						<el-form-item label="描述">
+							<el-input v-model="item.desc" class="w230"></el-input>
+						</el-form-item>
+						<el-form-item label="样式">
+							<el-input v-model="item.style" class="w230"></el-input>
+						</el-form-item>
+					</el-form>
+				</el-col>
+			</block>
+			
+			<block v-if="item.type=='text'">
+				<el-form :inline="true">
+					<el-col :span="16">
+						<el-form-item label="描述">
+							<el-input v-model="item.text" style="min-width:500px;" type="textarea"></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="8">
+						<el-form-item label="样式">
+							<el-input v-model="item.style" class="w230"></el-input>
+						</el-form-item>
+					</el-col>
+				</el-form>
+			</block>
+		</el-row>
+	</div>
+  
+</template>
+
+<script>
+ import { tow60 } from "@/utils/stringFun";
+export default {
+  name: 'UploadExcel',
+  data() {
+    return {
+		tow60
+    }
+  },
+  props:["list"],
+  methods: {
+   
+  }
+}
+</script>

+ 15 - 0
src/view/weixin/index.vue

@@ -0,0 +1,15 @@
+<template>
+  <div>
+    <keep-alive>
+      <router-view v-if="$route.meta.keepAlive"></router-view>
+    </keep-alive>
+    <router-view v-if="!$route.meta.keepAlive"></router-view>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "member",
+};
+</script>
+<style lang="scss"></style>

+ 195 - 0
src/view/weixin/info.vue

@@ -0,0 +1,195 @@
+<template>
+  <div class="main">
+    <div class="main-body">
+      <el-form label-width="90px"  label-position="center"
+      ref="elForm" :model="info" :rules="rules" >
+        <el-row>
+          <el-col :span="12" >
+			<el-form-item label="考察团" class="mt20" prop="title" >
+				<el-input v-model="info.title"></el-input>
+			</el-form-item>
+          </el-col>
+		</el-row>
+		
+		<div class="m-account ml20">
+		  <div class="account-tit" style="height:30px">
+		    <a :class="{'current':show===1}" style="text-decoration: none;padding-bottom: 5px" @click="show=1" class="">导航图片</a>
+		    <a :class="{'current':show===2}" style="text-decoration: none;padding-bottom: 5px" @click="show=2" class="">主页引导</a>
+			<a :class="{'current':show===3}" style="text-decoration: none;padding-bottom: 5px" @click="show=3" class="">精彩视频</a>
+			<a :class="{'current':show===4}" style="text-decoration: none;padding-bottom: 5px" @click="show=4" class="">宁德风貌</a>
+			<a :class="{'current':show===5}" style="text-decoration: none;padding-bottom: 5px" @click="show=5" class="">考察点</a>
+			<a :class="{'current':show===6}" style="text-decoration: none;padding-bottom: 5px" @click="show=6" class="">行程安排</a>
+			<a :class="{'current':show===7}" style="text-decoration: none;padding-bottom: 5px" @click="show=7" class="">详细页面</a>
+		  </div>
+		</div>
+		<!-- 导航图片 -->
+		<div v-if="show===1" class="lwh-ul-form p20">
+			<el-row>
+			  <el-col :span="6" v-for="(slider, index) in info.main.nodes.slider.children" :key="index">
+				<vue-viewer class="preview" width="200px" height="200px" :thumb="tow60(slider.image)" :full="slider.image"></vue-viewer>
+				<b-image @onFinish="(url)=>{slider.image=url}"placeholder="更换图片"> </b-image>
+			  </el-col>
+			</el-row>
+		</div>
+		
+		<div v-if="show===2" class="lwh-ul-form p20">
+			<el-row v-for="(matrix,index) in info.main.nodes.matrix.children" :key="index">
+				<el-col :span="6">
+					<img :src="tow60(matrix.image)" width="180px" height="180px"></img>
+				</el-col>
+				
+				<el-col :span="6">
+					<el-form-item label="图片标题">
+						<el-input v-model="matrix.marks" style="width: 200px;"></el-input>
+					</el-form-item>
+					<el-form-item label-width="20px">
+						<b-image @onFinish="(url)=>{matrix.image=url}"placeholder="更换图片" width="100px"> </b-image>
+					</el-form-item>
+					
+				</el-col>
+			</el-row>
+		</div>
+		
+		<div v-if="show===3" class="lwh-ul-form p20">
+			<Inode :list="info.pages.video.nodes"></Inode>
+		</div>
+		<div v-if="show===4" class="lwh-ul-form p20">
+			<Inode :list="info.pages.image.nodes"></Inode>
+		</div>
+		<div v-if="show===5" class="lwh-ul-form p20">
+			<Inode :list="info.pages.brief.nodes"></Inode>
+		</div>
+		<div v-if="show===6" class="lwh-ul-form p20">
+			<Inode :list="info.pages.trip.nodes"></Inode>
+		</div>
+		
+		<div v-if="show===7" class="lwh-ul-form p20">
+			<el-row >
+				<el-col :span="6" style="width:200px">
+					<el-row v-for="(item,id) in info.pages" :key="id">
+						<el-button @click="curPage=id" style="width:100px" type="primary"> {{item.id}}</el-button>
+					</el-row>
+				</el-col>
+				<el-col :span="18">
+					<Inode :list="info.pages[curPage].nodes"></Inode>
+				</el-col>
+			</el-row>
+			
+		</div>
+      </el-form>
+    </div>
+  </div>
+
+</template>
+
+<script>
+  import BImage from '@/components/upload/BImage.vue'
+  import Inode from './components/Inode.vue'
+  import { tow60 } from "@/utils/stringFun";
+  import { getPaper, addPaper } from "@/api/paper";
+  export default {
+    name: 'application',
+    data() {
+      return {
+		tow60,
+        loading:false,
+        isLike: 0,
+        id:0,
+        recover: false,
+		show:7,
+		matrixId:0,
+		curPage:"3-1",
+        info: {
+			config:{},
+			main:{
+				title:'',
+				nodes:{
+					logo:{
+						type:'',
+						image:'',
+						style:''
+					},
+					sliders:{
+						type: "slider",
+						style: "height: 200px;",
+						children:[]
+					},
+					matrix:{
+						type: "matrix",
+						children:[]
+					}
+				}
+			},
+			pages:{
+				video:{id:"1", nodes:[]},
+				image:{id:"",  nodes:[]},
+				brief:{id:'',  nodes:[]},
+				trip:{id:'',   nodes:[]}
+			}
+        },
+		matrixList:[],
+        rules: {
+          title:[{required:true, message:'请输入标题'}],
+          content:[{required:true, message:'请输入简介'}],
+          publishStatus:[{required:true, message:'请输入选择分类'}],
+          publishTime:[{required:true, message:'请输入发布时间'}],
+          postType:[{required:true, message:'请选择分类'}]
+        }
+      }
+    },
+	components:{BImage,Inode},
+    created(){
+      this.id = +this.$route.query.id;
+      if( this.id ){
+        this.loadData( )
+      }
+    },
+    methods:{
+      loadData( ){
+        let id = this.id;
+        getPaper({id}).then(res => {
+           if (res.code == 200) {
+			  this.info = JSON.parse( res.data.text );
+			  console.log("info", this.info);
+			  this.title = res.data.title;
+			  console.log("info", this.info);
+           }
+         })
+      },
+	  onFinish(url, index){
+		console.log("finish", index, url);
+		this.info.slider[index] = url;  
+	  },
+	  selectMatrix(matrix){
+		this.show = 3;
+		
+	  },
+	  saveSubmit(){
+		let param = Object.assign( {}, this.info);
+		this.onSubmit( param );
+	  },
+	  newSubmit(){
+		let param = Object.assign( {}, this.info);
+		param.postId = 0;
+		this.onSubmit( param ); 
+	  },
+      onSubmit( param ){
+        this.$refs["elForm"].validate((valid) => {
+			if (!valid) return;
+			addPaper( param ).then(res=>{
+              if( res.code == 200){
+                this.$message.successMsg("提交成功", 2);
+              }
+            })
+        })
+      }
+    }
+  }
+</script>
+
+<style>
+	@import url("../../style/paper.css");
+  .ipt-select{
+    width: 500px;
+  }
+</style>

+ 146 - 0
src/view/weixin/paper.vue

@@ -0,0 +1,146 @@
+<template>
+  <div>
+    <div class="button-box clearflex">
+      <el-button @click="gotoDetail({})" type="primary">添加考察团</el-button>
+    </div>
+
+    <div class="search-term">
+      <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
+		
+      </el-form>
+    </div>
+    
+
+    <el-table :data="tableData"  border stripe>
+      <el-table-column label="序号" width="80" prop="paperId" align="center">
+		  
+	  </el-table-column>
+      <el-table-column label="标题"  prop="title" min-width="120">
+      </el-table-column>
+	  
+	  <el-table-column label="导航栏图片"  prop="logo" align="center" width="110">
+		<template slot-scope="{ row }">
+		  <el-button v-if="!row.edit" @click="row.edit=true" type="text"> 查看图片 </el-button>
+		  <vue-viewer v-else class="preview" width="100" height="60" :thumb="row.slider.split(',')" :full="row.slider.split(',')" style="margin:0 auto">
+		  </vue-viewer>
+		</template>
+	  </el-table-column>
+	  
+      <el-table-column
+        align="center"
+        width="160px"
+        label="操作"
+        class-name="small-padding fixed-width"
+      >
+        <template slot-scope="{row, $index}">
+			<el-button
+			  v-if="row.edit"
+			  type="primary"
+			  size="small"
+			  icon="el-icon-cancel"
+			  @click="row.edit=false"
+			>收回</el-button>
+          <el-button
+			v-if="!row.edit"
+            type="primary"
+            size="small"
+            icon="el-icon-edit"
+            @click="gotoDetail(row, $index)"
+          >编辑</el-button>
+		  <el-button
+			v-if="!row.edit"
+		    type="danger"
+		    size="small"
+		    icon="el-icon-delete"
+		    @click="deletePost(row, $index)"
+		  >删除</el-button>
+		  
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      :current-page="page"
+      :page-size="size"
+      :page-sizes="[10, 30, 50, 100]"
+      :style="{float:'right',padding:'20px'}"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+      layout="total, sizes, prev, pager, next, jumper"
+    ></el-pagination>
+
+   
+  </div>
+</template>
+
+<script>
+import {getPaperList, delPaper} from "@/api/paper";
+import infoList from "@/mixins/infoList";
+import PreviewImg from "@/components/customPic/previewImg.vue";
+
+export default {
+  name: "Api",
+  data() {
+    return {
+	  listApi: getPaperList,
+	  searchInfo:{
+		publishStatus:'publish',
+		postTypeMap:''
+	  }
+    };
+  },
+  components:{PreviewImg},
+  watch:{
+  	searchInfo:{
+  		handler(new_value,old_value){
+  			this.page = 1;
+  			this.getTableData();
+  	    },
+  		deep: true,
+  	}
+  },
+  
+  mixins: [infoList],
+  inited(viewer) {
+  	this.$viewer = viewer
+  },
+  methods: {
+    //条件搜索前端看此方法
+    onSubmit() {
+      this.page = 1;
+      this.pageSize = 10;
+      this.getTableData();
+    },
+    gotoDetail(row, index) {
+      let id = row.paperId||0
+	  this.$router.push({name:'weixin_paper_info', query:{id}})
+    },
+	deletePost( row, index){
+		let id = row.paperId||0
+		delPaper( {id}).then( res=>{
+			if( res.code == 200){
+				this.$message.successMsg("删除成功", 2);
+				this.getTableData();
+			}
+		})
+	}
+  },
+  created() {
+    this.getTableData();
+  }
+};
+</script>
+<style scoped lang="scss">
+.button-box {
+  padding: 10px 20px;
+  .el-button {
+    float: right;
+  }
+}
+.el-tag--mini {
+  margin-left: 5px;
+}
+.warning {
+  color: #dc143c;
+}
+</style>