Bladeren bron

[Feature] 在线留言 V0.1

caiaa 1 jaar geleden
bovenliggende
commit
9892f6de73

+ 17 - 0
src/api/comment.js

@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+export function fetchCommentList(data) {
+  return request({
+    url: 'comment/search',
+    method: 'post',
+    data: data
+  })
+}
+
+export function pushCommentAdd(data) {
+  return request({
+    url: 'comment/add',
+    method: 'post',
+    data: data
+  })
+}

+ 10 - 1
src/layout/components/AppMain.vue

@@ -11,6 +11,8 @@
     <section>
       <!-- <div class="">在线留言</div> -->
       <information ref="Information" />
+      <float-button ref="floatBtn" @addComment="addComment" />
+      <comment ref="commentAdd" />
     </section>
   </section>
 </template>
@@ -20,13 +22,17 @@ import { fetchRealCount } from '@/api/message'
 import { isNull } from '@/utils/convert'
 
 import Information from '@/views/home/Information'
+import FloatButton from './FloatButton'
+import Comment from '@/views/comment'
 
 let sseClient
 
 export default {
   name: 'AppMain',
   components: {
-    Information
+    Information,
+    FloatButton,
+    Comment
   },
   computed: {
     cachedViews() {
@@ -61,6 +67,9 @@ export default {
         })
       })
     },
+    addComment() {
+      this.$refs['commentAdd'].open()
+    },
     connect() {
       sseClient = this.$sse.create({
         url: process.env.VUE_APP_BASE_API + '/subscribe/' + this.$store.getters.idCard,

+ 89 - 255
src/layout/components/FloatButton/index.vue

@@ -1,225 +1,110 @@
 <template>
   <div
-    :class="{ 'float__wrapper': true, zIndexTop: moveFlags }"
-    @mouseup.stop.prevent="moveEnd"
+    ref="floatBtn"
+    class="popover-content__trigger floatBtn"
+    :style="{
+      transition: !moveFlags ? 'all 300ms ease' : 'unset',
+      transform: `translate(${transform.right}px,${transform.top}px)`,
+    }"
+    @mousedown.stop.prevent="moveStart"
+    @mouseover.stop.prevent="showButton"
+    @mouseleave.stop.prevent="hideButton"
+    @click.stop.prevent="toggleMenu"
   >
-    <div
-      ref="floatBtn"
-      class="popover-content__trigger floatBtn"
-      :style="{
-        transition: !moveFlags ? 'all 300ms ease' : 'unset',
-        transform: `translate3d(${transform.left}px,${transform.top}px,0)`,
-      }"
-      @mousedown.stop.prevent="moveStart"
-      @mouseover.stop.prevent="showButton"
-      @click.stop.prevent="toggleMenu"
-    >
-      <span
-        :style="{
-          left: transform.left < 50 ? '-50px' : 0,
-          width: moveFlags ? '50px' : '100px',
-        }"
-        class="hover-area"
-        @mouseleave.stop.prevent="hideButton"
-      />
-      <transition name="floating-popover-fade-in-out">
-        <div
-          v-if="popoverShow"
-          ref="popoverContent"
-          class="floating-popover"
-          :style="menuPosition"
-        >
-          <slot>
-            <div class="popover-content">
-              <div
-                class="popover-content__item el-button"
-                @click.stop.prevent="
-                  handleClickMenuAction();
-                  closeMenuAndFloating();
-                "
-              >
-                <!-- <img src="../assets/float-icon.png" />自动标准化 -->
-                <i class="iconfont iconnut icon" />自动标准化
-              </div>
-            </div>
-          </slot>
-        </div>
-      </transition>
-      <i :style="{ fontSize: `${form.fontSize}px` }" class="iconfont iconnut icon" />
+    <div class="btn-content">
+      <svg-icon icon-class="liaotian" style="width:20px;height:18px;margin-bottom:5px;" />
+      <div>在线</div>
+      <div>留言</div>
     </div>
   </div>
 </template>
 <script>
+import variables from '@/styles/variables.scss'
+
 export default {
   name: 'FloatButton',
   data() {
     return {
-      form: {
-        themeColor: {
-          hsl: { h: 200, s: 0, l: 0, a: 1 },
-          hex: '#000000',
-          hex8: '#000000FF',
-          rgba: { r: 0, g: 0, b: 0, a: 1 },
-          hsv: { h: 200, s: 0, v: 0, a: 1 },
-          oldHue: 200,
-          source: 'hex',
-          a: 1
-        },
-        fontSize: 28
-      },
       moveFlags: false,
-      clickFlag: false,
       hoverFlag: false,
-      // 初始的位置记录
-      movePosition: { x: 0, y: 0 },
-      nx: '',
-      ny: '',
-      dx: '',
       dy: '',
-      xPum: '',
-      yPum: '',
-      popoverShow: false,
       // 浮窗的位置
       transform: {
-        top: document.body.offsetHeight - 300,
-        left: document.body.offsetWidth - 25
+        top: document.body.offsetHeight / 2 - 43,
+        right: 20
       },
       lastMoveIndex: 0, //  拖拽计数
-      curMoveIndex: 0, //  历史计数
-      menuPosition: {
-        top: 0,
-        left: 0
-      }
+      curMoveIndex: 0 //  历史计数
     }
   },
-  created() {
-    document.addEventListener('mouseup', (e) => {
-      if (
-        e.clientY > window.innerHeight ||
-        e.clientY < 60 ||
-        e.clientX < 0 ||
-        e.clientX > window.innerWidth
-      ) {
-        this.moveEnd()
-      }
-    })
-  },
   mounted() {
     window.addEventListener('resize', () => {
-      this.$set(this.transform, 'top', document.body.offsetHeight / 2 - 20)
-      this.$set(this.transform, 'left', document.body.offsetWidth - 20)
-    })
-    const floatBtn = this.$refs.floatBtn
-    document.addEventListener('click', (event) => {
-      if (!floatBtn) return
-      var tDom = event.target
-      if (floatBtn !== tDom && !floatBtn.contains(tDom)) {
-        this.closeMenuAndFloating()
+      // console.log('resize')
+      const initHeight = document.body.offsetHeight / 2 - 43
+      let top = initHeight
+      if (initHeight < variables.headerHeight) {
+        top = variables.headerHeight
       }
+      this.$set(this.transform, 'top', top)
+      this.$set(this.transform, 'right', 20)
     })
   },
   methods: {
-    handleClickMenuAction() {
-      this.$alert('点击菜单了', '标题名称', {
-        confirmButtonText: '确定'
-      })
-      return
-    },
     closeMenuAndFloating() {
-      console.log('closeMenuAndFloating')
-      this.popoverShow = false
+      // console.log('closeMenuAndFloating')
       this.hoverFlag = false
       this.moveFlags = false
       this.resetFloatBtnLocation()
     },
     async toggleMenu() {
+      // console.log('clickkk')
       //  如果上一次down事件到下一次click事件中 相同即为点击事件
       if (this.lastMoveIndex === this.curMoveIndex) {
-        console.log(this.lastMoveIndex - this.curMoveIndex)
-        console.warn('点击')
-        this.popoverShow = !this.popoverShow
-        await this.$nextTick()
-        if (this.popoverShow) {
-          document.onmousemove = null
-          const { top, left } = this.transform
-          if (top >= 60) {
-            this.menuPosition.top = `-${this.$refs.popoverContent.offsetHeight +
-              10}px`
-          } else {
-            this.menuPosition.top = '60px'
-          }
-          if (left > 200) {
-            this.menuPosition.left = '-132px'
-          } else {
-            this.menuPosition.left = 0
-          }
-
-          console.log(`top:${top},left:${left}`)
-        }
+        // console.log(this.lastMoveIndex - this.curMoveIndex)
+        // console.warn('点击')
+        this.$emit('addComment')
       }
       this.curMoveIndex = this.lastMoveIndex
     },
+    showButton() {
+      // console.log('mouse-over')
+      if (this.moveFlags) return (this.hoverFlag = false)
+      this.hoverFlag = true
+      const { top } = this.transform
+      this.generateTransform({ top: top, right: 0 })
+    },
     hideButton() {
-      console.log('mouse-leave')
-      if (this.popoverShow) return
+      // console.log('mouse-leave')
       this.hoverFlag = false
       // 移动过程中不复位 按钮;
       if (this.moveFlags) return
       this.resetFloatBtnLocation()
     },
-    showButton() {
-      console.log('mouse-over')
-      if (this.moveFlags) return (this.hoverFlag = false)
-      this.hoverFlag = true
-      const { left, top } = this.transform
-      if (left > 0 && left < -25) return
-      const bodyWidth = document.body.clientWidth
-      if (left < bodyWidth / 2) {
-        this.generateTransform({ top: top, left: 20 })
-      } else {
-        this.generateTransform({ top: top, left: bodyWidth - 70 })
-      }
-    },
     moveStart(e) {
-      console.log('moveStart')
-      if (event.button === 2) return
-      if (this.popoverShow) {
-        this.moveFlags = false
-        return
-      }
-      this.clickFlag = true
-      const floatBtn = this.$refs.floatBtn // 获取目标元素
-
-      this.movePosition.x = e.clientX
-      this.movePosition.y = e.clientY
+      // console.log('moveStart')
+      if (e.button === 2) return
 
       // 计算鼠标相对元素的位置
-      const { left, top } = this.transform
-      this.dx = e.clientX - left
+      const { right, top } = this.transform
       this.dy = e.clientY - top
 
       this.moveFlags = true
-
       document.onmousemove = async(e) => {
-        this.clickFlag = false
         this.moveFlags = true
-        console.log('onmousemove')
-        const bodyWidth = document.body.clientWidth
+        // console.log('onmousemove')
         const bodyHeight = document.body.clientHeight
-        const moveMaxHeight = bodyHeight - 30
-        const moveMaxWidth = bodyWidth - floatBtn.offsetWidth / 2 + this.dx
+        const moveMaxHeight = bodyHeight - 86
+        const moveMinHeight = variables.headerHeight
 
-        this.nx = e.clientX
-        this.ny = e.clientY
-        this.xPum = (this.nx > moveMaxWidth ? moveMaxWidth : this.nx) - this.dx
-        this.yPum =
-          (this.ny > moveMaxHeight ? moveMaxHeight : this.ny) - this.dy
+        let moveTop = e.clientY - this.dy
+        if (moveTop > moveMaxHeight) {
+          moveTop = moveMaxHeight
+        } else if (moveTop < moveMinHeight) {
+          moveTop = moveMinHeight
+        }
         await this.$nextTick()
         this.lastMoveIndex++
-        this.generateTransform({
-          left: this.xPum > -25 ? this.xPum : -25,
-          top: this.yPum > 0 ? this.yPum : 0
-        })
+        this.generateTransform({ top: moveTop, right })
       }
       document.onmouseup = () => {
         document.onmousemove = null
@@ -227,107 +112,56 @@ export default {
         this.moveEnd()
       }
     },
-    generateTransform({ top, left }) {
-      const floatBtn = this.$refs.floatBtn // 获取目标元素
-      if (!floatBtn) return
-      this.$set(this.transform, 'left', left)
-      this.$set(this.transform, 'top', top)
-    },
-    resetFloatBtnLocation() {
-      console.log('------reset')
-      const floatBtn = this.$refs.floatBtn // 获取目标元素
-      if (!floatBtn) return
-      const bodyWidth = document.body.clientWidth
-      const { left, top } = this.transform
-      if (left < bodyWidth / 2) {
-        this.generateTransform({ top, left: `-25` })
-      } else {
-        this.generateTransform({ top, left: bodyWidth - 25 })
-      }
-    },
     moveEnd() {
-      console.log(`moveEnd`)
+      // console.log(`moveEnd`)
       this.moveFlags = false
       if (this.hoverFlag) return
       document.onmousemove = null
       this.resetFloatBtnLocation()
+    },
+    resetFloatBtnLocation() {
+      // console.log('------reset')
+      const floatBtn = this.$refs.floatBtn // 获取目标元素
+      if (!floatBtn) return
+      const { top } = this.transform
+      this.generateTransform({ top, right: 20 })
+    },
+    generateTransform({ top, right }) {
+      const floatBtn = this.$refs.floatBtn // 获取目标元素
+      if (!floatBtn) return
+      this.$set(this.transform, 'top', top)
+      this.$set(this.transform, 'right', right)
     }
   }
 }
 </script>
 <style lang="scss" scoped>
-.zIndexTop {
-  z-index: 1800;
-}
-
-.float__wrapper {
+.floatBtn {
   position: fixed;
   top: 0;
-  left: 0;
-  width: 100vw;
-  height: 100vh;
-  overflow: hidden;
-  pointer-events: none;
-
-  .floatBtn {
-    position: absolute;
-    z-index: 1800;
-    cursor: pointer;
-
-    .icon {
-      color: var(--themeColor);
-      font-size: 24px;
-      -webkit-user-drag: none;
-    }
-
-    ::v-deep .hover-area {
-      position: absolute;
-      width: 100px;
-      height: 100%;
-    }
-
-    span:last-child {
-      z-index: 2;
-    }
-  }
-  .popover-content {
-    width: 100% !important;
-
-    &__trigger {
-      width: 50px;
-      height: 50px;
-      background: #fff;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      border-radius: 40px;
-      box-shadow: 0px 16px 34px 0px rgba(0, 49, 128, 0.2);
-      pointer-events: auto;
-    }
-  }
+  right: 0;
+  width: 40px;
+  height: 86px;
+  z-index: 1800;
+  background: #0056DD;
+  // display: flex;
+  // justify-content: center;
+  // align-items: center;
+  border-radius: 40px;
+  box-shadow: 0px 16px 34px 0px rgba(0, 49, 128, 0.2);
+  pointer-events: auto;
+  cursor: pointer;
 }
-</style>
-<style lang="scss" scoped>
-.floating-popover-fade-in-out {
-  &-enter-active,
-  &-leave-active {
-    transition-timing-function: ease;
-    transition-duration: 300ms;
-    transition-property: opacity, transform;
-  }
 
-  &-enter,
-  &-leave-to {
-    opacity: 0;
-    transform: translate3d(0, -10px, 0);
-  }
-}
-.floating-popover {
-  position: absolute;
-  /* width: 182px; */
-  padding: 0 !important;
-  border: 0 !important;
-  /* border-radius: 40px !important; */
-  /* box-shadow: 0px 16px 34px 0px rgba(0, 49, 128, 0.2); */
+.btn-content {
+  height: 100%;
+  color: #FFFFFF;
+  font-size: 12px;
+  line-height: 16px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  -webkit-user-drag: none;
 }
 </style>

+ 4 - 0
src/styles/index.scss

@@ -248,6 +248,10 @@ aside {
 .main-edit-dialog {
   min-width: 800px;
 
+  .el-dialog__body {
+    padding: 10px 20px;
+  }
+
   .upload-success {
     display: inline-block;
     color: #13ce66;

+ 6 - 2
src/styles/variables.scss

@@ -21,8 +21,10 @@ $subMenuHover: #f0f2f5;
 
 $sideBarWidth: 210px;
 $siderBarCollapseWidth: 64px;
-$headerHeight: 100px;
-$footerHeight: 32px; // must greater than 15px
+$headerHeightNum: 100;
+$headerHeight: $headerHeightNum + 0px;
+$footerHeightNum: 32;
+$footerHeight: $footerHeightNum + 0px; // must greater than 15px
 $tagHeight: 42px; // must greater than 40px
 $mainTopPadding: 10px;
 $layoutHeight: $headerHeight + $footerHeight + $tagHeight + $mainTopPadding;
@@ -39,4 +41,6 @@ $layoutHeight: $headerHeight + $footerHeight + $tagHeight + $mainTopPadding;
   subMenuHover: $subMenuHover;
   sideBarWidth: $sideBarWidth;
   siderBarCollapseWidth: $siderBarCollapseWidth;
+  headerHeight: $headerHeightNum;
+  footerHeight: $footerHeightNum;
 }

+ 196 - 0
src/views/comment/index.vue

@@ -0,0 +1,196 @@
+<template>
+  <div>
+    <el-dialog
+      v-loading="loading"
+      :visible.sync="visible"
+      :close-on-press-escape="true"
+      :close-on-click-modal="false"
+      :show-close="false"
+      custom-class="main-edit-dialog"
+      title="系统管理员留言"
+    >
+      <div class="form-box">
+        <el-form :ref="formName" :model="formData" :rules="rules">
+          <el-form-item prop="comment">
+            <el-input v-model="formData.comment" type="textarea" :rows="5" clearable placeholder="请输入" />
+          </el-form-item>
+          <el-form-item style="text-align: right">
+            <el-button type="primary" @click="saveItem">确定</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div>
+        <el-input
+          v-model="comment"
+          suffix-icon="el-icon-search"
+          placeholder="搜索"
+          style="width:250px; margin-bottom:10px"
+          @change="searchTable"
+        />
+        <div class="list-table">
+          <el-table v-loading="loading" :data="tableData" border stripe height="500" style="width: 100%;">
+            <el-table-column type="index" label="序号" width="50" />
+            <el-table-column prop="comment" label="留言内容" width="100" show-overflow-tooltip />
+            <el-table-column prop="createUser" label="发起人姓名" show-overflow-tooltip />
+            <el-table-column prop="createOrgName" label="发起人所属单位" width="160" show-overflow-tooltip />
+            <el-table-column prop="createTime" label="创建时间" width="160" />
+            <el-table-column label="操作" align="center" width="160" class-name="action-column">
+              <template slot-scope="scope">
+                <el-button type="text">详情回复</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div v-if="total > 0" class="page">
+            <el-pagination
+              layout="total, sizes, prev, pager, next, jumper"
+              :current-page="current"
+              :total="total"
+              :page-sizes="pageSizeAll"
+              :page-size="size"
+              @size-change="handleSizeChange"
+              @current-change="handleCurrentChange"
+            />
+          </div>
+        </div>
+      </div>
+      <div slot="footer">
+        <el-button @click="close">取消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+
+// import { fetchCommentList, pushCommentAdd } from '@/api/comment'
+
+export default {
+  name: 'CommentAdd',
+  data() {
+    return {
+      // dialog
+      visible: false,
+      // form
+      formName: 'editForm',
+      formData: {
+        comment: ''
+      },
+      rules: {
+        comment: [
+          { required: true, message: '请输入留言', trigger: 'blur' }
+        ]
+      },
+      // search
+      comment: '',
+      // table
+      current: 1,
+      size: 20,
+      total: 0,
+      pageSizeAll: [10, 20, 50, 100, 200, 500],
+      tableData: [],
+      multipleSelection: [],
+      // others
+      loading: false
+    }
+  },
+  methods: {
+    // 改变每页显示条数
+    handleSizeChange(val) {
+      this.current = 1
+      this.size = val
+      this.getTablelist()
+    },
+    // 切换第几页
+    handleCurrentChange(val) {
+      this.current = val
+      this.getTablelist()
+    },
+    // 重置搜索项
+    resetForm() {
+      this.$refs[this.formName].resetFields()
+      this.searchTable()
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    // 点击搜索按钮
+    searchTable() {
+      this.current = 1
+      this.getTablelist()
+    },
+    // 获取table数据
+    getTablelist() {
+      this.$message.info('开发中...')
+      // this.loading = true
+      // const params = {
+      //   current: this.current,
+      //   size: this.size,
+      //   orders: [{ column: 'create_time', asc: 0 }],
+      //   delFlag: 0,
+      //   comment: this.comment
+      // }
+      // fetchCommentList(params).then(response => {
+      //   this.loading = false
+      //   if (hasValidRecords(response)) {
+      //     this.tableData = response.data.records
+      //     this.total = response.data.total
+      //   } else {
+      //     this.tableData = []
+      //     this.total = 0
+      //   }
+      // }).catch(error => {
+      //   console.log(error)
+      //   this.loading = false
+      //   this.$message({
+      //     type: 'error',
+      //     duration: 0,
+      //     showClose: true,
+      //     message: '获取留言列表出错: ' + error.message
+      //   })
+      // })
+    },
+    saveItem() {
+      this.$refs[this.formName].validate((valid) => {
+        if (valid) {
+          this.$message.info('开发中...')
+          // this.loading = true
+          // pushCommentAdd(this.formData).then(res => {
+          //   this.loading = false
+          //   this.visible = false
+          //   this.$emit('refreshData')
+          //   this.$message({
+          //     type: 'success',
+          //     message: '保存成功!'
+          //   })
+          // }).catch(error => {
+          //   console.log(error)
+          //   this.loading = false
+          //   this.$message({
+          //     type: 'error',
+          //     duration: 0,
+          //     showClose: true,
+          //     message: '保存出错:' + error.message
+          //   })
+          // })
+        }
+      })
+    },
+    /**
+     * 加载dialog
+     */
+    open() {
+      this.visible = true
+    },
+    close() {
+      this.visible = false
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.form-box {
+  .el-form-item {
+    margin-bottom: 10px !important;
+  }
+}
+</style>

+ 0 - 1
src/views/log/components/LogView.vue

@@ -217,7 +217,6 @@ export default {
     }
 
     .el-dialog__body {
-      padding: 10px 20px !important;
       height: calc(100% - 55px - 71px);
     }
   }