浏览代码

feat✨ 文件上传

zhangwenjian 4 年之前
父节点
当前提交
973d4ea115

+ 4 - 4
src/api/file.js

@@ -2,7 +2,7 @@ import request from '@/utils/request'
 import { data } from 'autoprefixer'
 
 export const sysfiledirList = data => request({
-  url: '/api/v1/sysfiledirList',
+  url: '/api/v1/sysfiledir',
   method: 'GET',
   data
 })
@@ -14,7 +14,7 @@ export const sysfiledirAcionAdd = data => request({
 })
 
 export const sysfiledirAcionEdit = data => request({
-  url: '/api/v1/sysfiledir',
+  url: '/api/v1/sysfiledir/' + data.ID,
   method: 'PUT',
   data
 })
@@ -25,7 +25,7 @@ export const sysfiledirAcionDel = data => request({
 })
 
 export const sysfileinfoList = data => request({
-  url: `/api/v1/sysfileinfoList?pId=${data.pId}&pageSize=${data.pageSize}&pageIndex=${data.pageIndex}`,
+  url: `/api/v1/sysfileinfo?pId=${data.pId}&pageSize=${data.pageSize}&pageIndex=${data.pageIndex}`,
   method: 'GET',
   data
 })
@@ -42,7 +42,7 @@ export const sysfileinfoAdd = data => request({
 })
 
 export const sysfileinfoEdit = data => request({
-  url: '/api/v1/sysfileinfo',
+  url: '/api/v1/sysfileinfo/' + data.ID,
   method: 'put',
   data
 })

+ 14 - 13
src/components/FileChoose/index.vue

@@ -14,7 +14,7 @@
           v-model="value"
           :options="options"
           clearable
-          :props="{ expandTrigger: 'hover', checkStrictly: true, value: 'id' }"
+          :props="{ expandTrigger: 'hover', checkStrictly: true, value: 'ID' }"
           @change="handleChange"
         />
       </div>
@@ -24,7 +24,7 @@
             <div class="file-footer-inner">
               <div
                 v-for="(item,index) in fileList"
-                :key="item.id"
+                :key="item.ID"
                 class="file-footer-item"
                 :class=" item.open ? 'file-active' : '' "
                 @click="handleChoose(item,index)"
@@ -204,9 +204,9 @@ export default {
         }
       })
     },
-    getFileInfo(id) {
+    getFileInfo(ID) {
       sysfileinfoList({
-        pId: id,
+        pId: ID,
         pageIndex: this.pageNo,
         pageSize: this.pageSize
       }).then(ret => {
@@ -226,24 +226,25 @@ export default {
       this.handleCancel()
     },
     handleChange() {
-      const id = this.value[this.value.length - 1]
+      const ID = this.value[this.value.length - 1]
       this.total = 0
       this.pageNo = 1
       this.fileList.length = 0
-      if (id) {
-        this.getFileInfo(id)
+      if (ID) {
+        this.getFileInfo(ID)
       }
     },
     handlePage(e) {
       this.pageNo = e
-      const id = this.value[this.value.length - 1]
-      if (id) {
-        this.getFileInfo(id)
+      debugger
+      const ID = this.value[this.value.length - 1]
+      if (ID) {
+        this.getFileInfo(ID)
       }
     },
     handleChoose(e, index) {
       if (this.multiple) {
-        const fileIndex = this.resultList.findIndex(item => item.id === e.id)
+        const fileIndex = this.resultList.findIndex(item => item.ID === e.ID)
         if (e.open) {
           if (fileIndex < 0) {
             return false
@@ -271,7 +272,7 @@ export default {
         for (let i = 0; i < this.fileList.length; i++) {
           this.fileList[i].open = false
           for (let j = 0; j < this.resultList.length; j++) {
-            if (this.resultList[j].id === this.fileList[i].id) {
+            if (this.resultList[j].ID === this.fileList[i].ID) {
               this.fileList[i].open = true
             }
             continue
@@ -279,7 +280,7 @@ export default {
         }
       } else {
         for (let i = 0; i < this.fileList.length; i++) {
-          if (this.resultList.every(e => e.id === this.fileList[i].id)) {
+          if (this.resultList.every(e => e.ID === this.fileList[i].ID)) {
             this.fileList[i].open = true
           } else {
             this.fileList[i].open = false

+ 7 - 7
src/components/FileManage/Left.vue

@@ -21,7 +21,7 @@
                 v-show="node.childNodes.length > 0"
                 :class="node.expanded ? 'el-icon-folder-opened icon' : 'el-icon-folder icon'"
               />
-              <span v-if="rename.status && rename.node.id === data.id">
+              <span v-if="rename.status && rename.node.ID === data.ID">
                 <input
                   ref="nodeInput"
                   v-focus="rename.status"
@@ -142,7 +142,7 @@ export default {
   },
   methods: {
     handleNodeClick(e) {
-      const result = this.treeFindPath(this.data, node => node.id === e.id)
+      const result = this.treeFindPath(this.data, node => node.ID === e.ID)
       eventBus.$emit('treeNodeClick', {
         treeNodePath: result,
         currentNode: e
@@ -198,12 +198,12 @@ export default {
       d.label = this.$refs.nodeInput.value
       console.log(d)
       sysfiledirAcionEdit({
-        id: d.id,
+        ID: d.ID,
         label: d.label,
         pId: d.pId
       }).then(ret => {
         if (ret.code === 200) {
-          this.$refs.tree.updateKeyChildren(n.id, d)
+          this.$refs.tree.updateKeyChildren(n.ID, d)
         }
       })
     },
@@ -225,10 +225,10 @@ export default {
         case 1:
           sysfiledirAcionAdd({
             label: '新建文件夹',
-            pId: this.rightData.currentData.id
+            pId: this.rightData.currentData.ID
           }).then(ret => {
             if (ret.code === 200) {
-              this.$refs.tree.append(ret.data, this.rightData.currentData.id)
+              this.$refs.tree.append(ret.data, this.rightData.currentData.ID)
               this.getDirList()
             }
           })
@@ -244,7 +244,7 @@ export default {
           console.log(this.rename)
           break
         case 4:
-          sysfiledirAcionDel(this.rightData.currentData.id).then(ret => {
+          sysfiledirAcionDel(this.rightData.currentData.ID).then(ret => {
             if (ret.code === 200) {
               this.$refs.tree.remove(this.rightData.currentNode)
             }

+ 7 - 6
src/components/FileManage/Right.vue

@@ -7,7 +7,7 @@
             <el-breadcrumb separator-class="el-icon-arrow-right" class="dir">
               <el-breadcrumb-item
                 v-for="item in treePath.treeNodePath"
-                :key="item.id"
+                :key="item.ID"
               >{{ item.label }}</el-breadcrumb-item>
             </el-breadcrumb>
           </el-col>
@@ -90,7 +90,7 @@
               <template slot-scope="scope">
                 <span
                   v-if="!scope.row.open"
-                  v-text="parseTime(scope.row.createdAt)"
+                  v-text="parseTime(scope.row.CreatedAt)"
                 />
               </template>
             </el-table-column>
@@ -339,7 +339,7 @@ export default {
       this.getList()
     },
     getList() {
-      const pId = this.treePath.currentNode.id
+      const pId = this.treePath.currentNode.ID
       if (pId) {
         sysfileinfoList({
           pId,
@@ -374,7 +374,7 @@ export default {
           size: `${item.size}`,
           url: item.path,
           fullUrl: item.full_path,
-          pId: this.treePath.currentNode.id
+          pId: this.treePath.currentNode.ID
         })
       })
       return Promise.all(path)
@@ -395,13 +395,14 @@ export default {
           break
         case 2:
           this.tableData.forEach((item, index) => {
-            if (item.id === this.rightData.currentData.id) {
+            debugger
+            if (item.ID === this.rightData.currentData.ID) {
               this.tableData[index].open = true
             }
           })
           break
         case 3:
-          sysfileinfoDelete(this.rightData.currentData.id).then(ret => {
+          sysfileinfoDelete(this.rightData.currentData.ID).then(ret => {
             if (ret.code === 200) {
               this.getList()
             }

+ 2 - 0
src/components/Tinymce/components/EditorImage.vue

@@ -31,6 +31,7 @@ export default {
   },
   methods: {
     checkAllSuccess() {
+      debugger
       return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
     },
     handleFile() {
@@ -42,6 +43,7 @@ export default {
     handleFileConfirm(e) {
       this.dialogVisible = false
       console.log(e)
+      this.$emit('successCBK', e)
     }
   }
 }

+ 3 - 1
src/components/Tinymce/index.vue

@@ -201,9 +201,11 @@ export default {
       window.tinymce.get(this.tinymceId).getContent()
     },
     imageSuccessCBK(arr) {
+      debugger
       const _this = this
       arr.forEach(v => {
-        window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
+        console.log(v)
+        window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" width="100%" src="${v.fullUrl}" >`)
       })
     }
   }

+ 12 - 12
src/components/Upload/SingleImage.vue

@@ -26,7 +26,7 @@
 </template>
 
 <script>
-import { getToken } from '@/api/qiniu'
+// import { getToken } from '@/api/qiniu'
 
 export default {
   name: 'SingleImageUpload',
@@ -60,17 +60,17 @@ export default {
     beforeUpload() {
       const _self = this
       return new Promise((resolve, reject) => {
-        getToken().then(response => {
-          const key = response.data.qiniu_key
-          const token = response.data.qiniu_token
-          _self._data.dataObj.token = token
-          _self._data.dataObj.key = key
-          this.tempUrl = response.data.qiniu_url
-          resolve(true)
-        }).catch(err => {
-          console.log(err)
-          reject(false)
-        })
+        // getToken().then(response => {
+        //   const key = response.data.qiniu_key
+        //   const token = response.data.qiniu_token
+        //   _self._data.dataObj.token = token
+        //   _self._data.dataObj.key = key
+        //   this.tempUrl = response.data.qiniu_url
+        //   resolve(true)
+        // }).catch(err => {
+        //   console.log(err)
+        //   reject(false)
+        // })
       })
     }
   }

+ 11 - 11
src/components/Upload/SingleImage2.vue

@@ -26,7 +26,7 @@
 </template>
 
 <script>
-import { getToken } from '@/api/qiniu'
+// import { getToken } from '@/api/qiniu'
 
 export default {
   name: 'SingleImageUpload2',
@@ -60,16 +60,16 @@ export default {
     beforeUpload() {
       const _self = this
       return new Promise((resolve, reject) => {
-        getToken().then(response => {
-          const key = response.data.qiniu_key
-          const token = response.data.qiniu_token
-          _self._data.dataObj.token = token
-          _self._data.dataObj.key = key
-          this.tempUrl = response.data.qiniu_url
-          resolve(true)
-        }).catch(() => {
-          reject(false)
-        })
+        // getToken().then(response => {
+        //   const key = response.data.qiniu_key
+        //   const token = response.data.qiniu_token
+        //   _self._data.dataObj.token = token
+        //   _self._data.dataObj.key = key
+        //   this.tempUrl = response.data.qiniu_url
+        //   resolve(true)
+        // }).catch(() => {
+        //   reject(false)
+        // })
       })
     }
   }

+ 14 - 14
src/components/Upload/SingleImage3.vue

@@ -34,7 +34,7 @@
 </template>
 
 <script>
-import { getToken } from '@/api/qiniu'
+// import { getToken } from '@/api/qiniu'
 
 export default {
   name: 'SingleImageUpload3',
@@ -67,19 +67,19 @@ export default {
     },
     beforeUpload() {
       const _self = this
-      return new Promise((resolve, reject) => {
-        getToken().then(response => {
-          const key = response.data.qiniu_key
-          const token = response.data.qiniu_token
-          _self._data.dataObj.token = token
-          _self._data.dataObj.key = key
-          this.tempUrl = response.data.qiniu_url
-          resolve(true)
-        }).catch(err => {
-          console.log(err)
-          reject(false)
-        })
-      })
+      // return new Promise((resolve, reject) => {
+      //   getToken().then(response => {
+      //     const key = response.data.qiniu_key
+      //     const token = response.data.qiniu_token
+      //     _self._data.dataObj.token = token
+      //     _self._data.dataObj.key = key
+      //     this.tempUrl = response.data.qiniu_url
+      //     resolve(true)
+      //   }).catch(err => {
+      //     console.log(err)
+      //     reject(false)
+      //   })
+      // })
     }
   }
 }

+ 4 - 2
src/components/UploadDialog/form.vue

@@ -5,8 +5,8 @@
         <el-radio-group v-model="form.dataSource">
           <el-radio-button label="1">本地</el-radio-button>
           <el-radio-button label="2">阿里云OSS</el-radio-button>
-          <el-radio-button label="3">七牛云</el-radio-button>
-          <el-radio-button label="4">腾讯云COS</el-radio-button>
+          <!-- <el-radio-button label="3">七牛云</el-radio-button>
+          <el-radio-button label="4">腾讯云COS</el-radio-button> -->
         </el-radio-group>
       </el-form-item>
     </el-form>
@@ -75,10 +75,12 @@ export default {
       if (this.activeTab === '2') {
         this.formData = new FormData()
         this.formData.append('file', this.form.base64)
+        this.formData.append('source', this.form.dataSource)
         this.formData.append('type', '3')
       } else {
         this.formData = new FormData()
         this.$refs.upload.submit()
+        this.formData.append('source', this.form.dataSource)
         this.formData.append('type', '2')
       }
       request.post(this.url, this.formData, {

+ 277 - 0
src/views/syscontent/components/ArticleDetail.vue

@@ -0,0 +1,277 @@
+<template>
+  <div class="createPost-container">
+    <el-form ref="postForm" :model="postForm" :rules="rules" class="form-container">
+
+      <sticky :z-index="10" :class-name="'sub-navbar '+postForm.status">
+        <CommentDropdown v-model="postForm.comment_disabled" />
+        <PlatformDropdown v-model="postForm.platforms" />
+        <SourceUrlDropdown v-model="postForm.source_uri" />
+        <el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm">
+          Publish
+        </el-button>
+        <el-button v-loading="loading" type="warning" @click="draftForm">
+          Draft
+        </el-button>
+      </sticky>
+
+      <div class="createPost-main-container">
+        <el-row>
+          <Warning />
+
+          <el-col :span="24">
+            <el-form-item style="margin-bottom: 40px;" prop="title">
+              <MDinput v-model="postForm.title" :maxlength="100" name="name" required>
+                Title
+              </MDinput>
+            </el-form-item>
+
+            <div class="postInfo-container">
+              <el-row>
+                <el-col :span="8">
+                  <el-form-item label-width="60px" label="Author:" class="postInfo-container-item">
+                    <el-select v-model="postForm.author" :remote-method="getRemoteUserList" filterable default-first-option remote placeholder="Search user">
+                      <el-option v-for="(item,index) in userListOptions" :key="item+index" :label="item" :value="item" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="10">
+                  <el-form-item label-width="120px" label="Publish Time:" class="postInfo-container-item">
+                    <el-date-picker v-model="displayTime" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="Select date and time" />
+                  </el-form-item>
+                </el-col>
+
+                <el-col :span="6">
+                  <el-form-item label-width="90px" label="Importance:" class="postInfo-container-item">
+                    <el-rate
+                      v-model="postForm.importance"
+                      :max="3"
+                      :colors="['#99A9BF', '#F7BA2A', '#FF9900']"
+                      :low-threshold="1"
+                      :high-threshold="3"
+                      style="display:inline-block"
+                    />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+            </div>
+          </el-col>
+        </el-row>
+
+        <el-form-item style="margin-bottom: 40px;" label-width="70px" label="Summary:">
+          <el-input v-model="postForm.content_short" :rows="1" type="textarea" class="article-textarea" autosize placeholder="Please enter the content" />
+          <span v-show="contentShortLength" class="word-counter">{{ contentShortLength }}words</span>
+        </el-form-item>
+
+        <el-form-item prop="content" style="margin-bottom: 30px;">
+          <Tinymce ref="editor" v-model="postForm.content" :height="400" />
+        </el-form-item>
+
+        <el-form-item prop="image_uri" style="margin-bottom: 30px;">
+          <Upload v-model="postForm.image_uri" />
+        </el-form-item>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import Tinymce from '@/components/Tinymce'
+import Upload from '@/components/Upload/SingleImage3'
+import MDinput from '@/components/MDinput'
+import Sticky from '@/components/Sticky' // 粘性header组件
+import { validURL } from '@/utils/validate'
+// import { fetchArticle } from '@/api/article'
+import { searchUser } from '@/api/remote-search'
+import Warning from './Warning'
+import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
+const defaultForm = {
+  status: 'draft',
+  title: '', // 文章题目
+  content: '', // 文章内容
+  content_short: '', // 文章摘要
+  source_uri: '', // 文章外链
+  image_uri: '', // 文章图片
+  display_time: undefined, // 前台展示时间
+  id: undefined,
+  platforms: ['a-platform'],
+  comment_disabled: false,
+  importance: 0
+}
+export default {
+  name: 'ArticleDetail',
+  components: { Tinymce, MDinput, Upload, Sticky, Warning, CommentDropdown, PlatformDropdown, SourceUrlDropdown },
+  props: {
+    isEdit: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    const validateRequire = (rule, value, callback) => {
+      if (value === '') {
+        this.$message({
+          message: rule.field + '为必传项',
+          type: 'error'
+        })
+        callback(new Error(rule.field + '为必传项'))
+      } else {
+        callback()
+      }
+    }
+    const validateSourceUri = (rule, value, callback) => {
+      if (value) {
+        if (validURL(value)) {
+          callback()
+        } else {
+          this.$message({
+            message: '外链url填写不正确',
+            type: 'error'
+          })
+          callback(new Error('外链url填写不正确'))
+        }
+      } else {
+        callback()
+      }
+    }
+    return {
+      postForm: Object.assign({}, defaultForm),
+      loading: false,
+      userListOptions: [],
+      rules: {
+        image_uri: [{ validator: validateRequire }],
+        title: [{ validator: validateRequire }],
+        content: [{ validator: validateRequire }],
+        source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
+      },
+      tempRoute: {}
+    }
+  },
+  computed: {
+    contentShortLength() {
+      return this.postForm.content_short.length
+    },
+    displayTime: {
+      // set and get is useful when the data
+      // returned by the back end api is different from the front end
+      // back end return => "2013-06-25 06:59:25"
+      // front end need timestamp => 1372114765000
+      get() {
+        return (+new Date(this.postForm.display_time))
+      },
+      set(val) {
+        this.postForm.display_time = new Date(val)
+      }
+    }
+  },
+  created() {
+    if (this.isEdit) {
+      const id = this.$route.params && this.$route.params.id
+      this.fetchData(id)
+    }
+    // Why need to make a copy of this.$route here?
+    // Because if you enter this page and quickly switch tag, may be in the execution of the setTagsViewTitle function, this.$route is no longer pointing to the current page
+    // https://github.com/PanJiaChen/vue-element-admin/issues/1221
+    this.tempRoute = Object.assign({}, this.$route)
+  },
+  methods: {
+    fetchData(id) {
+    //   fetchArticle(id).then(response => {
+    //     this.postForm = response.data
+    //     // just for test
+    //     this.postForm.title += `   Article Id:${this.postForm.id}`
+    //     this.postForm.content_short += `   Article Id:${this.postForm.id}`
+    //     // set tagsview title
+    //     this.setTagsViewTitle()
+    //     // set page title
+    //     this.setPageTitle()
+    //   }).catch(err => {
+    //     console.log(err)
+    //   })
+    },
+    setTagsViewTitle() {
+      const title = 'Edit Article'
+      const route = Object.assign({}, this.tempRoute, { title: `${title}-${this.postForm.id}` })
+      this.$store.dispatch('tagsView/updateVisitedView', route)
+    },
+    setPageTitle() {
+      const title = 'Edit Article'
+      document.title = `${title} - ${this.postForm.id}`
+    },
+    submitForm() {
+      console.log(this.postForm)
+      this.$refs.postForm.validate(valid => {
+        if (valid) {
+          this.loading = true
+          this.$notify({
+            title: '成功',
+            message: '发布文章成功',
+            type: 'success',
+            duration: 2000
+          })
+          this.postForm.status = 'published'
+          this.loading = false
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    draftForm() {
+      if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
+        this.$message({
+          message: '请填写必要的标题和内容',
+          type: 'warning'
+        })
+        return
+      }
+      this.$message({
+        message: '保存成功',
+        type: 'success',
+        showClose: true,
+        duration: 1000
+      })
+      this.postForm.status = 'draft'
+    },
+    getRemoteUserList(query) {
+      searchUser(query).then(response => {
+        if (!response.data.items) return
+        this.userListOptions = response.data.items.map(v => v.name)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "~@/styles/mixin.scss";
+.createPost-container {
+  position: relative;
+  .createPost-main-container {
+    padding: 40px 45px 20px 50px;
+    .postInfo-container {
+      position: relative;
+      @include clearfix;
+      margin-bottom: 10px;
+      .postInfo-container-item {
+        float: left;
+      }
+    }
+  }
+  .word-counter {
+    width: 40px;
+    position: absolute;
+    right: 10px;
+    top: 0px;
+  }
+}
+.article-textarea ::v-deep {
+  textarea {
+    padding-right: 40px;
+    resize: none;
+    border: none;
+    border-radius: 0px;
+    border-bottom: 1px solid #bfcbd9;
+  }
+}
+</style>

+ 41 - 0
src/views/syscontent/components/Dropdown/Comment.vue

@@ -0,0 +1,41 @@
+<template>
+  <el-dropdown :show-timeout="100" trigger="click">
+    <el-button plain>
+      {{ !comment_disabled?'Comment: opened':'Comment: closed' }}
+      <i class="el-icon-caret-bottom el-icon--right" />
+    </el-button>
+    <el-dropdown-menu slot="dropdown" class="no-padding">
+      <el-dropdown-item>
+        <el-radio-group v-model="comment_disabled" style="padding: 10px;">
+          <el-radio :label="true">
+            Close comment
+          </el-radio>
+          <el-radio :label="false">
+            Open comment
+          </el-radio>
+        </el-radio-group>
+      </el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  props: {
+    value: {
+      type: Boolean,
+      default: false
+    }
+  },
+  computed: {
+    comment_disabled: {
+      get() {
+        return this.value
+      },
+      set(val) {
+        this.$emit('input', val)
+      }
+    }
+  }
+}
+</script>

+ 46 - 0
src/views/syscontent/components/Dropdown/Platform.vue

@@ -0,0 +1,46 @@
+<template>
+  <el-dropdown :hide-on-click="false" :show-timeout="100" trigger="click">
+    <el-button plain>
+      Platfroms({{ platforms.length }})
+      <i class="el-icon-caret-bottom el-icon--right" />
+    </el-button>
+    <el-dropdown-menu slot="dropdown" class="no-border">
+      <el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
+        <el-checkbox v-for="item in platformsOptions" :key="item.key" :label="item.key">
+          {{ item.name }}
+        </el-checkbox>
+      </el-checkbox-group>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  props: {
+    value: {
+      required: true,
+      default: () => [],
+      type: Array
+    }
+  },
+  data() {
+    return {
+      platformsOptions: [
+        { key: 'a-platform', name: 'a-platform' },
+        { key: 'b-platform', name: 'b-platform' },
+        { key: 'c-platform', name: 'c-platform' }
+      ]
+    }
+  },
+  computed: {
+    platforms: {
+      get() {
+        return this.value
+      },
+      set(val) {
+        this.$emit('input', val)
+      }
+    }
+  }
+}
+</script>

+ 38 - 0
src/views/syscontent/components/Dropdown/SourceUrl.vue

@@ -0,0 +1,38 @@
+<template>
+  <el-dropdown :show-timeout="100" trigger="click">
+    <el-button plain>
+      Link
+      <i class="el-icon-caret-bottom el-icon--right" />
+    </el-button>
+    <el-dropdown-menu slot="dropdown" class="no-padding no-border" style="width:400px">
+      <el-form-item label-width="0px" style="margin-bottom: 0px" prop="source_uri">
+        <el-input v-model="source_uri" placeholder="Please enter the content">
+          <template slot="prepend">
+            URL
+          </template>
+        </el-input>
+      </el-form-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  props: {
+    value: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    source_uri: {
+      get() {
+        return this.value
+      },
+      set(val) {
+        this.$emit('input', val)
+      }
+    }
+  }
+}
+</script>

+ 3 - 0
src/views/syscontent/components/Dropdown/index.js

@@ -0,0 +1,3 @@
+export { default as CommentDropdown } from './Comment'
+export { default as PlatformDropdown } from './Platform'
+export { default as SourceUrlDropdown } from './SourceUrl'

+ 12 - 0
src/views/syscontent/components/Warning.vue

@@ -0,0 +1,12 @@
+<template>
+  <aside>
+    Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support
+    caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching
+    effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all
+    pages directly. See details
+    <a
+      href="https://panjiachen.github.io/vue-element-admin-site/guide/essentials/tags-view.html"
+      target="_blank"
+    >Document</a>
+  </aside>
+</template>

+ 132 - 0
src/views/syscontent/create.vue

@@ -0,0 +1,132 @@
+<template>
+  <BasicLayout>
+    <template #wrapper>
+      <el-card class="box-card">
+        <el-form ref="form" :model="form" label-width="80px" class="form-container">
+          <el-form-item label="分类" prop="cateId">
+            <el-select
+              v-model="form.cateId"
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="dict in cateIdOptions"
+                :key="dict.key"
+                :label="dict.value"
+                :value="dict.key"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="名称" prop="name">
+            <el-input
+              v-model="form.name"
+              placeholder="名称"
+            />
+          </el-form-item>
+          <el-form-item label="状态" prop="status">
+            <el-select
+              v-model="form.status"
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="dict in statusOptions"
+                :key="dict.dictValue"
+                :label="dict.dictLabel"
+                :value="dict.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="内容" prop="content">
+            <!-- <el-input
+                v-model="form.content"
+                type="textarea"
+                :rows="2"
+                placeholder="请输入内容"
+              /> -->
+            <Tinymce ref="editor" v-model="form.content" :height="400" />
+            <!-- <rict-text v-model="form.content" :height="400" /> -->
+          </el-form-item>
+          <el-form-item label="备注" prop="remark">
+            <el-input
+              v-model="form.remark"
+              placeholder="备注"
+            />
+          </el-form-item>
+          <el-form-item label="排序" prop="sort">
+            <el-input
+              v-model="form.sort"
+              placeholder="排序"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm">
+              Publish
+            </el-button>
+            <el-button v-loading="loading" type="warning" @click="draftForm">
+              Draft
+            </el-button>
+          </el-form-item>
+        </el-form>
+        <!-- <div slot="footer">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div> -->
+      </el-card>
+    </template>
+  </BasicLayout>
+</template>
+
+<script>
+// import { addSysContent, delSysContent, getSysContent, listSysContent, updateSysContent } from '@/api/syscontent'
+import { listSysCategory } from '@/api/syscategory'
+
+// import FileChoose from '@/components/FileChoose'
+import Tinymce from '@/components/Tinymce'
+// import RictText from '@/components/richtext'
+const defaultForm = {
+  status: 'draft'
+}
+export default {
+  name: 'CreateArticle',
+  components: {
+    // FileChoose,
+    Tinymce
+  },
+  data() {
+    return {
+      loading: false,
+      postForm: Object.assign({}, defaultForm),
+      // 表单参数
+      form: {},
+      statusOptions: [],
+      // 关系表类型
+      cateIdOptions: [],
+      // 表单校验
+      rules: {
+        cateId: [{ required: true, message: '分类id不能为空', trigger: 'blur' }],
+        name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
+        status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
+      }
+    }
+  },
+  created() {
+    this.getSysCategoryItems()
+    this.getDicts('sys_content_status').then(response => {
+      this.statusOptions = response.data
+    })
+  },
+  methods: {
+    // 关系
+    getSysCategoryItems() {
+      this.getItems(listSysCategory, undefined).then(res => {
+        this.cateIdOptions = this.setItems(res, 'ID', 'name')
+      })
+    },
+    draftForm() {
+
+    },
+    submitForm() {
+
+    }
+  }
+}
+</script>

+ 5 - 4
src/views/syscontent/index.vue

@@ -338,10 +338,11 @@ export default {
     },
     /** 新增按钮操作 */
     handleAdd() {
-      this.reset()
-      this.open = true
-      this.title = '添加内容管理'
-      this.isEdit = false
+      this.$router.push({ name: 'SysContentCreate' })
+      // this.reset()
+      // this.open = true
+      // this.title = '添加内容管理'
+      // this.isEdit = false
     },
     // 多选框选中数据
     handleSelectionChange(selection) {