Procházet zdrojové kódy

更新 views/blog 模块

reghao před 3 měsíci
rodič
revize
1566a87731

+ 2 - 1
package.json

@@ -11,7 +11,6 @@
     "@amap/amap-jsapi-loader": "^1.0.1",
     "@fingerprintjs/fingerprintjs": "^4.6.2",
     "@liripeng/vue-audio-player": "^1.5.0",
-    "@tinymce/tinymce-vue": "^3.0.1",
     "ali-oss": "^6.21.0",
     "axios": "^0.19.2",
     "babel-plugin-prismjs": "^2.0.1",
@@ -24,6 +23,7 @@
     "hls.js": "^1.1.2",
     "js-cookie": "2.2.0",
     "jsencrypt": "^3.2.1",
+    "mavon-editor": "^2.10.4",
     "nprogress": "^0.2.0",
     "ol": "^6.13.0",
     "prismjs": "^1.25.0",
@@ -37,6 +37,7 @@
     "vue-amap": "^0.5.10",
     "vue-clipboard2": "^0.3.3",
     "vue-cookies": "^1.7.0",
+    "vue-markdown": "^2.2.4",
     "vue-meta": "^2.4.0",
     "vue-router": "^3.4.5",
     "vue-simple-uploader": "^0.7.6",

+ 22 - 7
src/api/blog.js

@@ -7,7 +7,6 @@ const blogApi = {
   getArchive: '/api/blog/archive',
   getAbout: '/api/blog/about',
   getSearchList: '/api/blog/search',
-  getBlogTag: '/api/blog/v2/tag',
   getBlogCategory: '/api/blog/v2/category',
   getBlogPost: '/api/blog/v2/post',
   getBlogQuestion: '/api/blog/v2/question'
@@ -38,12 +37,8 @@ export function getAbout() {
 }
 
 // blog 后台接口
-export function getBlogTagList() {
-  return get(blogApi.getBlogTag + '/list')
-}
-
-export function getBlogCategoryList() {
-  return get(blogApi.getBlogCategory + '/list')
+export function getBlogCategoryList(queryInfo) {
+  return get(blogApi.getBlogCategory + '/list', queryInfo)
 }
 
 export function addBlogCategory(formData) {
@@ -58,6 +53,26 @@ export function getBlogPostList(queryInfo) {
   return get(blogApi.getBlogPost + '/list', queryInfo)
 }
 
+export function editBlogPost(formData) {
+  return postForm(blogApi.getBlogPost + '/edit', formData)
+}
+
+export function getBlogEditPost(queryInfo) {
+  return get(blogApi.getBlogPost + '/edit', queryInfo)
+}
+
+export function deleteBlogPost(formData) {
+  return postForm(blogApi.getBlogPost + '/delete', formData)
+}
+
 export function getBlogQuestionList(queryInfo) {
   return get(blogApi.getBlogQuestion + '/list', queryInfo)
 }
+
+export function addBlogQuestionWeight(formData) {
+  return postForm(blogApi.getBlogQuestion + '/weight/add', formData)
+}
+
+export function minusBlogQuestionWeight(formData) {
+  return postForm(blogApi.getBlogQuestion + '/weight/minus', formData)
+}

+ 0 - 7
src/router/background_blog.js

@@ -1,6 +1,5 @@
 const Background = () => import('views/admin/Background')
 const BlogCategory = () => import('views/blog/BlogCategory')
-const BlogTag = () => import('views/blog/BlogCategory')
 const BlogPost = () => import('views/blog/BlogPost')
 const BlogQuestion = () => import('views/blog/BlogQuestion')
 
@@ -17,12 +16,6 @@ export default {
       component: BlogCategory,
       meta: { needAuth: true }
     },
-    {
-      path: '/background/blog/tag',
-      name: 'BlogTag',
-      component: BlogTag,
-      meta: { needAuth: true }
-    },
     {
       path: '/background/blog/post',
       name: 'BlogPost',

+ 0 - 5
src/views/admin/LeftAside.vue

@@ -201,11 +201,6 @@ export default {
               title: '分类管理',
               icon: 'el-icon-files'
             },
-            {
-              url: '/background/blog/tag',
-              title: '标签管理',
-              icon: 'el-icon-files'
-            },
             {
               url: '/background/blog/post',
               title: '文章管理',

+ 4 - 10
src/views/blog/ArticlePage.vue

@@ -14,7 +14,7 @@
           </div>
           <div class="text item">
             <el-row>
-              <span v-html="article.content" />
+              <markdown :source="article.content"></markdown>
             </el-row>
             <el-divider />
             <el-row>
@@ -41,18 +41,12 @@
 </template>
 
 <script>
-// import { getArticle } from '@/api/article'
-// import { getUserInfo } from '@/api/user'
-import { getPost, getNewsDetail } from '@/api/blog'
+import Markdown from 'vue-markdown'
+import { getPost } from '@/api/blog'
 
 export default {
   name: 'ArticlePage',
-  metaInfo: {
-    meta: [
-      { name: 'referrer', content: 'no-referrer' }
-    ]
-  },
-  components: {},
+  components: { Markdown },
   filters: {
     ellipsis(value) {
       if (!value) return ''

+ 44 - 29
src/views/blog/BlogCategory.vue

@@ -4,7 +4,7 @@
       <h3>文章分类</h3>
       <el-row style="margin-top: 10px">
         <el-select
-          v-model="dataType"
+          v-model="queryInfo.type"
           style="margin-left: 5px"
           @change="onSelectChange"
         >
@@ -68,7 +68,7 @@
         <template>
           <el-form :model="addForm" label-width="80px">
             <el-form-item label="分类">
-              <el-input v-model="addForm.category" style="width: 70%; padding-right: 2px" />
+              <el-input v-model="addForm.name" style="width: 70%; padding-right: 2px" />
             </el-form-item>
             <el-form-item>
               <el-button type="primary" @click="onAdd">确定</el-button>
@@ -81,26 +81,34 @@
 </template>
 
 <script>
-import { getBlogCategoryList, getBlogTagList } from '@/api/blog'
+import { addBlogCategory, deleteBlogCategory, getBlogCategoryList } from '@/api/blog'
 
 export default {
   name: 'BlogCategory',
   data() {
     return {
-      dataType: 'category',
+      queryInfo: {
+        type: 'category'
+      },
       dataList: [],
       addDialog: false,
       addForm: {
+        name: null
       }
     }
   },
   created() {
+    const type = this.$route.query.type
+    if (type !== undefined && type !== null) {
+      this.queryInfo.type = type
+    }
+
     document.title = '文章分类'
     this.getData()
   },
   methods: {
     getData() {
-      getBlogCategoryList().then(resp => {
+      getBlogCategoryList(this.queryInfo).then(resp => {
         if (resp.code === 0) {
           this.dataList = resp.data
         } else {
@@ -115,36 +123,43 @@ export default {
     },
     onAdd() {
       this.addDialog = false
-      this.$message.info('add')
+      const formData = new FormData()
+      formData.append('name', this.addForm.name)
+      addBlogCategory(formData).then(resp => {
+        this.addDialog = false
+        this.$message.info(resp.msg)
+        this.getData()
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
     },
     handleDelete(index, row) {
-      this.$message.info('delete -> ' + row.name)
-    },
-    onSelectChange() {
-      this.dataList = []
-      if (this.dataType === 'category') {
-        getBlogCategoryList().then(resp => {
-          if (resp.code === 0) {
-            this.dataList = resp.data
-          } else {
-            this.$message.error(resp.msg)
-          }
+      this.$confirm('确定要删除 ' + row.name + '?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        const formData = new FormData()
+        formData.append('id', row.id)
+        deleteBlogCategory(formData).then(resp => {
+          this.$message.info(resp.msg)
+          this.getData()
         }).catch(error => {
           this.$message.error(error.message)
         })
-      } else if (this.dataType === 'tag') {
-        getBlogTagList().then(resp => {
-          if (resp.code === 0) {
-            this.dataList = resp.data
-          } else {
-            this.$message.error(resp.msg)
-          }
-        }).catch(error => {
-          this.$message.error(error.message)
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消'
         })
-      } else {
-        this.$message.error('dataType error')
-      }
+      })
+    },
+    onSelectChange() {
+      this.$router.push({
+        path: '/background/blog/category',
+        query: this.queryInfo
+      })
+      this.getData()
     }
   }
 }

+ 202 - 23
src/views/blog/BlogPost.vue

@@ -4,12 +4,17 @@
       <h3>文章列表</h3>
       <el-row style="margin-top: 10px">
         <el-select
-          v-model="dataType"
+          v-model="queryInfo.categoryId"
+          clearable
           style="margin-left: 5px"
           @change="onSelectChange"
         >
-          <el-option label="category" value="category" />
-          <el-option label="tag" value="tag" />
+          <el-option
+            v-for="(item, index) in categoryList"
+            :key="index"
+            :label="item.name"
+            :value="item.id"
+          />
         </el-select>
         <el-button type="success" icon="el-icon-plus" style="margin-left: 5px" @click="handleAdd">添加</el-button>
       </el-row>
@@ -56,6 +61,15 @@
             </el-tag>
           </template>
         </el-table-column>
+        <el-table-column
+          prop="editor"
+          label="编辑器"
+        >
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.editor === 'markdown'" type="info"><span>{{ scope.row.editor }}</span></el-tag>
+            <el-tag v-else type="info"><span>{{ scope.row.editor }}</span></el-tag>
+          </template>
+        </el-table-column>
         <el-table-column
           prop="published"
           label="是否发布"
@@ -78,9 +92,9 @@
             <el-button
               style="margin-top: 5px; margin-left: 5px"
               size="mini"
-              type="danger"
-              @click="handleDetail(scope.$index, scope.row)"
-            >查看</el-button>
+              type="warning"
+              @click="handleEdit(scope.$index, scope.row)"
+            >修改</el-button>
             <el-button
               style="margin-top: 5px; margin-left: 5px"
               size="mini"
@@ -103,21 +117,67 @@
       />
 
       <el-dialog
-        title="添加分类"
+        title="编辑文章"
         append-to-body
         :visible.sync="addDialog"
-        width="30%"
+        width="100%"
         center
       >
         <template>
-          <el-form :model="addForm" label-width="80px">
+          <div id="editor">
+            <mavon-editor ref="md" style="height: 100%" :ishljs="true" :value="addForm.content" @change="onEditorChange" />
+          </div>
+          <el-form :model="addForm" label-width="80px" style="margin: 5px">
+            <el-form-item label="标题">
+              <el-input v-model="addForm.title" style="width: 30%; padding-right: 1px" />
+            </el-form-item>
             <el-form-item label="分类">
-              <el-input v-model="addForm.category" style="width: 70%; padding-right: 2px" />
+              <el-select
+                v-model="addForm.categoryId"
+                style="padding-right: 1px"
+              >
+                <el-option
+                  v-for="(item, index) in categoryList"
+                  :key="index"
+                  :label="item.name"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="标签">
+              <el-select
+                v-model="addForm.tags"
+                style="padding-right: 1px"
+                placeholder="输入标签,用回车添加"
+                clearable
+                multiple
+                filterable
+                allow-create
+                default-first-option
+              >
+                <el-option v-for="item in addForm.tags" :key="item" :label="item" :value="item" />
+              </el-select>
             </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="onAdd">确定</el-button>
+            <el-form-item label="是否发布">
+              <el-select
+                v-model="addForm.published"
+                style="padding-right: 1px"
+              >
+                <el-option label="发布" value="1" />
+                <el-option label="草稿" value="0" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="文章类型">
+              <el-select
+                v-model="addForm.type"
+                style="padding-right: 1px"
+              >
+                <el-option label="文章" value="1" />
+                <el-option label="问题" value="2" />
+              </el-select>
             </el-form-item>
           </el-form>
+          <el-button type="success" style="margin: 5px" @click="onAdd">确定</el-button>
         </template>
       </el-dialog>
     </el-main>
@@ -125,17 +185,36 @@
 </template>
 
 <script>
-import { getBlogPostList } from '@/api/blog'
+import mavonEditor from 'mavon-editor'
+import 'mavon-editor/dist/css/index.css'
+import {
+  editBlogPost,
+  deleteBlogPost,
+  getBlogCategoryList,
+  getBlogEditPost,
+  getBlogPostList,
+  updateBlogPost
+} from '@/api/blog'
 
 export default {
-  name: 'BlogCategory',
+  name: 'BlogPost',
+  components: {
+    'mavon-editor': mavonEditor.mavonEditor
+  },
+  props: {
+    mdData: {
+      type: String,
+      default: ''
+    }
+  },
   data() {
     return {
+      categoryList: [],
       queryInfo: {
         pn: 1,
-        categoryId: 0,
-        published: 0,
-        title: ''
+        categoryId: null,
+        title: '',
+        published: 0
       },
       // 屏幕宽度, 为了控制分页条的大小
       screenWidth: document.body.clientWidth,
@@ -145,10 +224,41 @@ export default {
       dataList: [],
       addDialog: false,
       addForm: {
+        articleId: null,
+        editor: 'markdown',
+        title: null,
+        content: '',
+        categoryId: '',
+        tags: [],
+        published: '1',
+        type: '1'
       }
     }
   },
   created() {
+    const pageNumber = this.$route.query.pn
+    if (pageNumber !== undefined && pageNumber !== null) {
+      this.currentPage = parseInt(pageNumber)
+      this.queryInfo.pn = parseInt(pageNumber)
+    }
+    const categoryId = this.$route.query.categoryId
+    if (categoryId !== undefined && categoryId !== null) {
+      this.queryInfo.categoryId = parseInt(categoryId)
+    }
+    const title = this.$route.query.title
+    if (title !== undefined && title !== null) {
+      this.queryInfo.title = title
+    }
+    const published = this.$route.query.published
+    if (published !== undefined && published !== null) {
+      this.queryInfo.published = published
+    }
+    getBlogCategoryList().then(resp => {
+      if (resp.code === 0) {
+        this.categoryList = resp.data
+      }
+    })
+
     document.title = '文章列表'
     this.getData()
   },
@@ -179,21 +289,90 @@ export default {
     handleAdd() {
       this.addDialog = true
     },
-    onAdd() {
-      this.addDialog = false
-      this.$message.info('add')
+    handleEdit(index, row) {
+      const queryInfo = {}
+      queryInfo.articleId = row.articleId
+      getBlogEditPost(queryInfo).then(resp => {
+        if (resp.code === 0) {
+          this.addForm = resp.data
+          this.addDialog = true
+        } else {
+          this.$message.error(resp.msg)
+        }
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
     },
-    handleDetail(index, row) {
-      this.$message.info('detail -> ' + row.articleId)
+    onAdd() {
+      const formData = new FormData()
+      formData.append('articleId', this.addForm.articleId)
+      formData.append('editor', this.addForm.editor)
+      formData.append('title', this.addForm.title)
+      formData.append('content', this.addForm.content)
+      formData.append('categoryId', this.addForm.categoryId)
+      formData.append('tags', this.addForm.tags)
+      formData.append('published', this.addForm.published)
+      formData.append('type', this.addForm.published)
+      editBlogPost(formData).then(resp => {
+        this.addDialog = false
+        this.$message.info(resp.msg)
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
     },
     handleDelete(index, row) {
-      this.$message.info('delete -> ' + row.title)
+      this.$confirm('确定要删除 ' + row.title + '?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        const formData = new FormData()
+        formData.append('articleId', row.articleId)
+        deleteBlogPost(formData).then(resp => {
+          this.$message.info(resp.msg)
+          this.getData()
+        }).catch(error => {
+          this.$message.error(error.message)
+        })
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消'
+        })
+      })
     },
     onSelectChange() {
+      this.currentPage = 1
+      this.queryInfo.pn = 1
+      this.$router.push({
+        path: '/background/blog/post',
+        query: this.queryInfo
+      })
+      this.getData()
+    },
+    onEditorChange() { // 也可以接收 value 和 render参数 获取内容
+      // this.$emit('update:mdData', this.$refs.md.d_value)
+      // 带有标签的内容
+      // console.log(this.$refs.md.d_render)
+      // markdown文本格式
+      this.addForm.content = this.$refs.md.d_value
+    },
+    onEditorChange1() {
+      this.addForm.content = this.$refs.md1.d_value
     }
   }
 }
 </script>
 
 <style scoped>
+#editor {
+  margin: auto;
+  width: 100%;
+  height: 480px;
+}
+#editor1 {
+  margin: auto;
+  width: 100%;
+  height: 480px;
+}
 </style>

+ 80 - 33
src/views/blog/BlogQuestion.vue

@@ -5,13 +5,17 @@
       <el-row style="margin-top: 10px">
         <el-select
           v-model="queryInfo.categoryId"
+          clearable
           style="margin-left: 5px"
           @change="onSelectChange"
         >
-          <el-option label="category" value="category" />
-          <el-option label="tag" value="tag" />
+          <el-option
+            v-for="(item, index) in categoryList"
+            :key="index"
+            :label="item.name"
+            :value="item.id"
+          />
         </el-select>
-        <el-button type="success" icon="el-icon-plus" style="margin-left: 5px" @click="handleAdd">添加</el-button>
       </el-row>
     </el-header>
     <el-main>
@@ -59,15 +63,21 @@
             <el-button
               style="margin-top: 5px; margin-left: 5px"
               size="mini"
-              type="danger"
+              type="info"
               @click="handleDetail(scope.$index, scope.row)"
             >详情</el-button>
             <el-button
               style="margin-top: 5px; margin-left: 5px"
               size="mini"
-              type="danger"
-              @click="handleDelete(scope.$index, scope.row)"
-            >删除</el-button>
+              type="success"
+              @click="handleAddWeight(scope.$index, scope.row)"
+            >加</el-button>
+            <el-button
+              style="margin-top: 5px; margin-left: 5px"
+              size="mini"
+              type="warning"
+              @click="handleMinusWeight(scope.$index, scope.row)"
+            >减</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -84,21 +94,13 @@
       />
 
       <el-dialog
-        title="添加分类"
+        title="详情"
         append-to-body
         :visible.sync="addDialog"
-        width="30%"
         center
       >
         <template>
-          <el-form :model="addForm" label-width="80px">
-            <el-form-item label="分类">
-              <el-input v-model="addForm.category" style="width: 70%; padding-right: 2px" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="onAdd">确定</el-button>
-            </el-form-item>
-          </el-form>
+          <markdown :source="addForm.content"></markdown>
         </template>
       </el-dialog>
     </el-main>
@@ -106,30 +108,55 @@
 </template>
 
 <script>
-import { getBlogQuestionList } from '@/api/blog'
+import Markdown from 'vue-markdown'
+import {
+  getBlogCategoryList,
+  getBlogQuestionList,
+  addBlogQuestionWeight,
+  minusBlogQuestionWeight
+} from '@/api/blog'
 
 export default {
-  name: 'BlogCategory',
+  name: 'BlogQuestion',
+  components: { Markdown },
   data() {
     return {
+      categoryList: [],
       queryInfo: {
         pn: 1,
-        categoryId: 0,
-        published: 0,
-        title: ''
+        categoryId: null
       },
       // 屏幕宽度, 为了控制分页条的大小
       screenWidth: document.body.clientWidth,
       currentPage: 1,
-      pageSize: 10,
+      pageSize: 100,
       totalSize: 0,
       dataList: [],
       addDialog: false,
       addForm: {
+        content: ''
       }
     }
   },
   created() {
+    const pageNumber = this.$route.query.pn
+    if (pageNumber !== undefined && pageNumber !== null) {
+      this.currentPage = parseInt(pageNumber)
+      this.queryInfo.pn = parseInt(pageNumber)
+    }
+    const categoryId = this.$route.query.categoryId
+    if (categoryId !== undefined && categoryId !== null) {
+      this.queryInfo.categoryId = parseInt(categoryId)
+    }
+
+    const queryInfo = {}
+    queryInfo.type = 'category'
+    getBlogCategoryList(queryInfo).then(resp => {
+      if (resp.code === 0) {
+        this.categoryList = resp.data
+      }
+    })
+
     document.title = '面试题列表'
     this.getData()
   },
@@ -137,7 +164,7 @@ export default {
     handleCurrentChange(pageNumber) {
       this.queryInfo.pn = pageNumber
       this.$router.push({
-        path: '/background/blog/post',
+        path: '/background/blog/question',
         query: this.queryInfo
       })
       this.getData()
@@ -157,20 +184,40 @@ export default {
         this.$message.error(error.message)
       })
     },
-    handleAdd() {
+    handleDetail(index, row) {
+      this.addForm.content = row.content
       this.addDialog = true
     },
-    onAdd() {
-      this.addDialog = false
-      this.$message.info('add')
-    },
-    handleDetail(index, row) {
-      this.$message.info('detail -> ' + row.articleId)
+    handleAddWeight(index, row) {
+      const formData = new FormData()
+      formData.append('questionId', row.questionId)
+      addBlogQuestionWeight(formData).then(resp => {
+        this.addDialog = false
+        this.$message.info(resp.msg)
+        this.getData()
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
     },
-    handleDelete(index, row) {
-      this.$message.info('delete -> ' + row.title)
+    handleMinusWeight(index, row) {
+      const formData = new FormData()
+      formData.append('questionId', row.questionId)
+      minusBlogQuestionWeight(formData).then(resp => {
+        this.addDialog = false
+        this.$message.info(resp.msg)
+        this.getData()
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
     },
     onSelectChange() {
+      this.currentPage = 1
+      this.queryInfo.pn = 1
+      this.$router.push({
+        path: '/background/blog/question',
+        query: this.queryInfo
+      })
+      this.getData()
     }
   }
 }