Browse Source

[Feature] 常见问题

caiaa 1 year ago
parent
commit
b63355fe60

+ 30 - 0
src/api/faq.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function fetchFaqList(data) {
+  return request({
+    url: 'issue/search',
+    method: 'post',
+    data: data
+  })
+}
+
+export function fetchFaqDetail(id) {
+  return request({
+    url: `issue/info/${id}`
+  })
+}
+
+export function pushSaveFaq(action, data) {
+  return request({
+    url: `issue/${action}`,
+    method: 'post',
+    data: data
+  })
+}
+
+export function pushDeleteFaq(id) {
+  return request({
+    url: `issue/delete/${id}`
+  })
+}
+

+ 5 - 3
src/api/log.js

@@ -1,9 +1,11 @@
 import request from '@/utils/request'
 
-export function addLog(type, id, name) {
+export function addLog(type, id, name, url) {
   return request({
-    url: `${type}/clickIncr/${id}`,
-    headers: { 'sys-number': encodeURIComponent(name) }
+    url: `${type}/clickIncr`,
+    method: 'post',
+    // headers: { 'sys-number': encodeURIComponent(name) },
+    data: { id, name, url }
   })
 }
 

+ 1 - 0
src/styles/index.scss

@@ -20,6 +20,7 @@ body {
   background-color: #f5f8fe;
 }
 
+pre,
 button {
   font-family: Microsoft YaHei, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Arial, sans-serif !important;
 }

+ 1 - 1
src/utils/log.js

@@ -3,7 +3,7 @@ import { Message } from 'element-ui'
 import { addLog } from '@/api/log'
 
 export function jumpTo(type, id, name, url) {
-  addLog(type, id, name).then(res => {
+  addLog(type, id, name, url).then(res => {
   }).catch(error => {
     console.log(error)
     Message({

+ 1 - 1
src/views/application/index.vue

@@ -180,7 +180,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

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

@@ -48,7 +48,7 @@
                     <div class="item-system">{{ item.appName }}</div>
                   </div>
                 </div>
-                <el-button class="item-link" size="small" @click="$jumpTo('business', item.id, item.businessNumber, item.url)">打开</el-button>
+                <el-button class="item-link" size="small" @click="$jumpTo('business', item.id, item.businessName, item.url)">打开</el-button>
               </div>
               <div class="item-footer">{{ item.deptName }}</div>
             </div>
@@ -151,7 +151,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

+ 169 - 0
src/views/faq/FaqEdit.vue

@@ -0,0 +1,169 @@
+<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="title"
+    >
+      <el-form :ref="formName" :model="formData" :rules="isView ? {} : rules" label-width="120px" class="dialog-form">
+        <el-form-item prop="title" label="问题标题:">
+          <el-input v-if="!isView" v-model="formData.title" type="textarea" :rows="2" />
+          <div v-else class="item-title"><pre>{{ formData.title }}</pre></div>
+        </el-form-item>
+        <el-form-item prop="content" label="问题内容:">
+          <el-input v-if="!isView" v-model="formData.content" type="textarea" :rows="5" />
+          <div v-else class="item-content"><pre>{{ formData.content }}</pre></div>
+        </el-form-item>
+        <el-form-item prop="answer" label="问题解答:">
+          <el-input v-if="!isView" v-model="formData.answer" type="textarea" :rows="5" />
+          <div v-else class="item-answer"><pre>{{ formData.answer }}</pre></div>
+        </el-form-item>
+      </el-form>
+      <div slot="footer">
+        <el-button @click="close">取消</el-button>
+        <el-button v-if="!isView" type="primary" @click="save">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { isObject } from '@/utils/convert'
+
+import { pushSaveFaq } from '@/api/faq'
+
+export default {
+  name: 'FaqEdit',
+  data() {
+    return {
+      // dialog
+      visible: false,
+      isView: true,
+      viewType: 'ADD',
+      action: '',
+      title: 'Edit',
+      formName: 'editForm',
+      formData: {
+        id: null,
+        title: '',
+        content: '',
+        answer: ''
+      },
+      rules: {
+        title: [
+          { required: true, message: '请输入问题标题', trigger: 'blur' }
+        ]
+      },
+      // others
+      loading: false
+    }
+  },
+  methods: {
+    // Dialog
+    open(viewType, data) {
+      if (viewType === 'ADD') {
+        this.title = '新增'
+        this.isView = false
+        this.action = 'add'
+        if (this.viewType !== 'ADD') {
+          data = {}
+        }
+      } else if (viewType === 'EDIT') {
+        this.title = '编辑'
+        this.isView = false
+        this.action = 'update'
+      } else {
+        this.title = '详情'
+        this.isView = true
+      }
+      this.viewType = viewType
+      if (isObject(data)) {
+        Object.keys(this.formData).forEach(key => {
+          this.formData[key] = data[key] || ''
+        })
+      }
+      this.visible = true
+      this.$nextTick(() => {
+        if (!this.isView) {
+          this.$refs[this.formName].clearValidate()
+        }
+      })
+    },
+    close() {
+      this.visible = false
+    },
+    save() {
+      this.$refs[this.formName].validate((valid) => {
+        if (valid) {
+          this.loading = true
+          pushSaveFaq(this.action, this.formData).then(res => {
+            this.$refs[this.formName].resetFields()
+            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
+            })
+          })
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.dialog-form {
+  ::v-deep {
+    .el-scrollbar__wrap{
+      overflow-x: hidden;
+    }
+    .el-scrollbar__bar.is-horizontal {
+      display: none;
+    }
+  }
+
+  .el-scrollbar {
+    min-height: 33px;
+  }
+
+  .item-title, .item-content, .item-answer {
+    padding-top: 7px;
+    line-height: 25px;
+    overflow-y: auto;
+
+    &>pre{
+      margin: 0;
+      white-space: pre-wrap;
+      font-size: 14px;
+    }
+  }
+
+  .item-title {
+    max-height: 100px;
+    // ::v-deep .el-scrollbar__wrap {
+    //   max-height: 100px;
+    // }
+  }
+
+  .item-content, .item-answer {
+    max-height: 200px;
+    // ::v-deep .el-scrollbar__wrap {
+    //   max-height: 200px;
+    // }
+  }
+}
+</style>

+ 264 - 57
src/views/faq/index.vue

@@ -1,75 +1,282 @@
 <template>
-  <div class="app-container">
-    <el-table
-      v-loading="listLoading"
-      :data="list"
-      element-loading-text="Loading"
-      border
-      highlight-current-row
-    >
-      <el-table-column align="center" label="ID" width="95">
-        <template slot-scope="scope">
-          {{ scope.$index }}
-        </template>
-      </el-table-column>
-      <el-table-column label="Title">
-        <template slot-scope="scope">
-          {{ scope.row.title }}
-        </template>
-      </el-table-column>
-      <el-table-column label="Author" width="110" align="center">
-        <template slot-scope="scope">
-          <span>{{ scope.row.author }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="Pageviews" width="110" align="center">
-        <template slot-scope="scope">
-          {{ scope.row.pageviews }}
-        </template>
-      </el-table-column>
-      <el-table-column class-name="status-col" label="Status" width="110" align="center">
-        <template slot-scope="scope">
-          <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column align="center" prop="created_at" label="Display_time" width="200">
-        <template slot-scope="scope">
-          <i class="el-icon-time" />
-          <span>{{ scope.row.display_time }}</span>
-        </template>
-      </el-table-column>
-    </el-table>
+  <div class="faq-container">
+    <div class="filter-box">
+      <div class="list-filter">
+        <el-form ref="filterForm" :model="formData" inline>
+          <el-form-item label="问题标题">
+            <el-input v-model="formData.title" class="filter-item" clearable />
+          </el-form-item>
+          <el-form-item label="问题内容">
+            <el-input v-model="formData.content" class="filter-item" clearable />
+          </el-form-item>
+          <el-form-item class="filter-btn">
+            <el-button type="primary" @click="searchTable">查询</el-button>
+            <el-button type="danger" @click="resetForm">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+    <div class="faq-box">
+      <div class="list-button">
+        <el-button type="primary" @click="showEdit('ADD')">新增</el-button>
+      </div>
+      <div v-loading="loading" class="list-box">
+        <el-scrollbar class="list-scrollbar">
+          <div class="list-item-box">
+            <div v-for="item in tableData" :key="item.id" class="list-item">
+              <div class="item-header">
+                {{ item.title }}
+              </div>
+              <div class="item-content">
+                {{ item.content }}
+              </div>
+              <div class="item-footer">
+                <el-button type="text" icon="el-icon-tickets" @click="showEdit('VIEW', item)">详情</el-button>
+                <el-button type="text" icon="el-icon-edit" @click="showEdit('EDIT', item)">编辑</el-button>
+                <el-button type="text" icon="el-icon-delete" @click="deleteItem(item.id)">删除</el-button>
+              </div>
+            </div>
+            <i v-for="num in 3" :key="'padding'+num" class="list-item-padding" />
+          </div>
+        </el-scrollbar>
+        <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>
+    <faq-edit ref="faqEdit" @refreshData="searchTable" />
   </div>
 </template>
 
 <script>
+import { fetchFaqList, pushDeleteFaq } from '@/api/faq'
+
+import { hasValidRecords } from '@/utils/convert'
+
+import FaqEdit from './FaqEdit'
 
 export default {
-  filters: {
-    statusFilter(status) {
-      const statusMap = {
-        published: 'success',
-        draft: 'gray',
-        deleted: 'danger'
-      }
-      return statusMap[status]
-    }
-  },
+  name: 'Faq',
+  components: { FaqEdit },
   data() {
     return {
-      list: null,
-      listLoading: true
+      // table
+      current: 1,
+      size: 16,
+      total: 0,
+      pageSizeAll: [10, 16, 20, 50, 100, 200, 500],
+      tableData: [],
+      // filter
+      formData: {
+        title: '',
+        content: ''
+      },
+      // others
+      loading: false
     }
   },
   created() {
-    this.fetchData()
+    this.searchTable()
   },
   methods: {
-    fetchData() {
-      this.listLoading = true
-      this.list = []
-      this.listLoading = false
+    // 改变每页显示条数
+    handleSizeChange(val) {
+      this.current = 1
+      this.size = val
+      this.getTablelist()
+    },
+    // 切换第几页
+    handleCurrentChange(val) {
+      this.current = val
+      this.getTablelist()
+    },
+    // 重置搜索项
+    resetForm(formName) {
+      this.$refs[formName].resetFields()
+      this.searchTable()
+    },
+    // 点击搜索按钮
+    searchTable() {
+      this.current = 1
+      this.getTablelist()
+    },
+    // 获取table数据
+    getTablelist() {
+      this.loading = true
+      const params = {
+        page: this.current,
+        size: this.size,
+        order: '',
+        params: {
+          delFlag: 0,
+          title: this.formData.title,
+          content: this.formData.content
+        }
+      }
+      fetchFaqList(params).then(response => {
+        if (hasValidRecords(response)) {
+          this.tableData = response.data.records
+          this.total = response.data.total
+        } else {
+          this.tableData = []
+          this.total = 0
+        }
+        this.loading = false
+      }).catch(error => {
+        console.log(error)
+        this.loading = false
+        this.$message({
+          type: 'error',
+          duration: 0,
+          showClose: true,
+          message: '获取列表出错: ' + error.message
+        })
+      })
+    },
+    showEdit(viewType, data) {
+      this.$refs['faqEdit'].open(viewType, data)
+    },
+    deleteItem(id) {
+      this.loading = true
+      pushDeleteFaq(id).then(res => {
+        this.$message.success('删除成功!')
+        this.getTablelist()
+      }).catch(error => {
+        console.log(error)
+        this.loading = false
+        this.$message({
+          type: 'error',
+          duration: 0,
+          showClose: true,
+          message: '删除出错: ' + error.message
+        })
+      })
     }
   }
 }
 </script>
+
+<style lang="scss" scoped>
+.faq-container {
+  min-width: 900px;
+
+  .filter-box, .faq-box {
+    background-color: #fff;
+    padding: 10px 0 10px 20px;
+  }
+
+  .filter-box {
+    margin-bottom: 16px;
+  }
+
+  .list-filter {
+    height: 40px;
+  }
+
+  .faq-box {
+    height: calc(100% - 76px);
+
+    .page {
+      margin-right: 5px;
+      text-align: right;
+    }
+
+    ::v-deep {
+      .el-scrollbar__wrap{
+        overflow-x: hidden;
+      }
+
+      .el-scrollbar__bar.is-horizontal {
+        display: none;
+      }
+    }
+  }
+
+  .list-button {
+    height: 50px;
+  }
+
+  .list-box {
+    height: calc(100% - 50px);
+  }
+
+  .list-scrollbar {
+    height: calc(100% - 32px);
+  }
+
+  .list-item-box {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    margin-right: 10px;
+  }
+
+  .list-item, .list-item-padding {
+    width: 420px;
+  }
+
+  .list-item-padding {
+    height: 0;
+    display: block;
+  }
+
+  .list-item {
+    height: 200px;
+    border: 1px solid rgba(0,0,0,0.15);
+    border-radius: 4px;
+    margin-right: 5px;
+    margin-bottom: 16px;
+    position: relative;
+
+    .item-header, .item-content {
+      margin: 0 10px;
+    }
+
+    .item-header {
+      height: 50px;
+      line-height: 50px;
+      font-size: 16px;
+      font-weight: bold;
+      color: rgba(0,0,0,0.85);
+      border-bottom: 1px solid rgba(0,0,0,0.09);
+      text-overflow: ellipsis;
+      overflow: hidden;
+      white-space: nowrap;
+    }
+
+     .item-content {
+      overflow: hidden;
+      padding: 5px 0;
+      font-size: 14px;
+      line-height: 23px;
+      height: 100px;
+    }
+
+    .item-footer {
+      width: 100%;
+      height: 50px;
+      line-height: 50px;
+      text-align: center;
+      font-size: 14px;
+      background: rgba(0,0,0,0.04);
+
+      .el-button {
+        width: calc(100% /3 - 20px / 3);
+        color: rgba(0,0,0,0.65);
+      }
+      .el-button+.el-button {
+        border-left: 1px solid rgba(0,0,0,0.10);
+      }
+    }
+  }
+}
+</style>
+

+ 2 - 2
src/views/home/Business.vue

@@ -11,12 +11,12 @@
           <el-tab-pane label="所有" name="all">
             <div v-for="bizType in bizTypeData" :key="bizType.id" class="type-box">
               <div class="type-title">{{ bizType.label }}</div>
-              <el-button v-for="item in bizData[bizType.id]" :key="item.id" plain @click="$jumpTo('business', item.id, item.businessNumber, item.url)">{{ item.businessName }}</el-button>
+              <el-button v-for="item in bizData[bizType.id]" :key="item.id" plain @click="$jumpTo('business', item.id, item.businessName, item.url)">{{ item.businessName }}</el-button>
             </div>
           </el-tab-pane>
           <el-tab-pane v-for="bizType in bizTypeData" :key="bizType.id" :label="bizType.label" :name="bizType.type + bizType.id">
             <div class="type-box">
-              <el-button v-for="item in bizData[bizType.id]" :key="item.id" plain @click="$jumpTo('business', item.id, item.businessNumber, item.url)">{{ item.businessName }}</el-button>
+              <el-button v-for="item in bizData[bizType.id]" :key="item.id" plain @click="$jumpTo('business', item.id, item.businessName, item.url)">{{ item.businessName }}</el-button>
             </div>
           </el-tab-pane>
         </el-tabs>

+ 1 - 1
src/views/home/System.vue

@@ -8,7 +8,7 @@
       <el-carousel v-loading="loading" class="system-content" :autoplay="false" arrow="never" trigger="click">
         <el-carousel-item v-for="(page, index) in carouselData" :key="'carousel_' + index">
           <div class="system-box">
-            <div v-for="item in page" :key="item.id" class="system-item-box" @click="$jumpTo('app', item.id, item.systemNumber, item.url)">
+            <div v-for="item in page" :key="item.id" class="system-item-box" @click="$jumpTo('app', item.id, item.systemName, item.url)">
               <el-avatar :size="56" fit="fill" :src="item.icon | formatFileUrl" />
               <div class="system-title">{{ item.systemName }}</div>
             </div>

+ 2 - 2
src/views/home/components/BusinessEdit.vue

@@ -42,7 +42,7 @@
               :key="element.id"
               class="drag-item"
               :class="{'filtered': element.isFavorite}"
-              @click="$jumpTo('business', element.id, element.businessNumber, element.url)"
+              @click="$jumpTo('business', element.id, element.businessName, element.url)"
             >
               <i class="el-icon-plus handle-icon" @click.stop="clickAddItem(index)" />
               <el-avatar :size="56" :src="element.icon | formatFileUrl" />
@@ -144,7 +144,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getAllBizList()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

+ 1 - 1
src/views/home/components/LinkList.vue

@@ -54,7 +54,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

+ 1 - 1
src/views/home/components/MessageList.vue

@@ -131,7 +131,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

+ 2 - 2
src/views/home/components/SystemEdit.vue

@@ -34,7 +34,7 @@
               :key="element.id"
               class="drag-item"
               :class="{'filtered': element.isFavorite}"
-              @click="$jumpTo('app', element.id, element.systemNumber, element.url)"
+              @click="$jumpTo('app', element.id, element.systemName, element.url)"
             >
               <i class="el-icon-plus handle-icon" @click.stop="clickAddItem(index)" />
               <el-avatar :size="56" :src="element.icon | formatFileUrl" />
@@ -141,7 +141,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getAllListData()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

+ 1 - 1
src/views/info/components/DeptUser.vue

@@ -170,7 +170,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {

+ 1 - 1
src/views/info/index.vue

@@ -165,7 +165,7 @@ export default {
     resetForm() {
       this.$refs[this.formName].resetFields()
       this.$refs['deptTreeSelect'].handleClear()
-      this.getTablelist()
+      this.searchTable()
     },
     handleSelectionChange(val) {
       this.multipleSelection = val

+ 13 - 5
src/views/log/components/LogView.vue

@@ -60,7 +60,7 @@
           <el-table-column prop="systemName" label="应用名称" width="120" show-overflow-tooltip />
           <el-table-column label="URL地址" show-overflow-tooltip>
             <template slot-scope="scope">
-              <a @click="$jumpTo('app', scope.row.systemId, scope.row.systemNumber, scope.row.systemUrl)">{{ scope.row.systemUrl }}</a>
+              <a @click="$jumpTo('app', scope.row.systemId, scope.row.systemName, scope.row.systemUrl)">{{ scope.row.systemUrl }}</a>
             </template>
           </el-table-column>
           <el-table-column prop="createTime" label="访问时间" width="160" show-overflow-tooltip />
@@ -84,7 +84,7 @@
   </div>
 </template>
 <script>
-import { hasValidRecords } from '@/utils/convert'
+import { hasValidRecords, isNull } from '@/utils/convert'
 import { fetchLogDetail, fetchTableList } from '@/api/log'
 
 export default {
@@ -104,7 +104,7 @@ export default {
       // others
       loading: false,
       tableLoading: false,
-      appModuleType: '3005',
+      appModuleType: '3006',
       idCard: ''
     }
   },
@@ -123,7 +123,7 @@ export default {
     // 重置搜索项
     resetForm() {
       this.$refs[this.formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     handleSelectionChange(val) {
       this.multipleSelection = val
@@ -147,8 +147,16 @@ export default {
       fetchTableList(params).then(response => {
         this.tableLoading = false
         if (hasValidRecords(response)) {
+          let params
+          let paramsObj
           response.data.records.forEach(item => {
-            // Object.assign(item, ...item.params)
+            params = item.params
+            if (!isNull(params)) {
+              paramsObj = JSON.parse(params.replace('POST-PARAM:', ''))
+              item.systemId = paramsObj.id
+              item.systemName = paramsObj.name
+              item.systemUrl = paramsObj.url
+            }
           })
           this.tableData = response.data.records
           console.log(this.tableData[0].params)

+ 1 - 1
src/views/log/index.vue

@@ -130,7 +130,7 @@ export default {
     // 重置搜索项
     resetForm() {
       this.$refs[this.formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     handleSelectionChange(val) {
       this.multipleSelection = val

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

@@ -45,7 +45,7 @@
                   <el-avatar :size="56" :src="item.icon | formatFileUrl" />
                   <span class="item-name">{{ item.systemName }}</span>
                 </div>
-                <el-button class="item-link" size="small" @click="$jumpTo('app', item.id, item.systemNumber, item.url)">打开</el-button>
+                <el-button class="item-link" size="small" @click="$jumpTo('app', item.id, item.systemName, item.url)">打开</el-button>
               </div>
               <div class="item-footer">{{ item.deptName }}</div>
             </div>
@@ -148,7 +148,7 @@ export default {
     // 重置搜索项
     resetForm(formName) {
       this.$refs[formName].resetFields()
-      this.getTablelist()
+      this.searchTable()
     },
     // 点击搜索按钮
     searchTable() {