ArticleDetail.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <template>
  2. <div class="createPost-container">
  3. <el-form ref="postForm" :model="postForm" :rules="rules" class="form-container">
  4. <div class="createPost-main-container">
  5. <el-row>
  6. <Warning />
  7. <el-col :span="24">
  8. <el-form-item style="margin-bottom: 40px;" prop="title">
  9. <MDinput v-model="postForm.title" :maxlength="50" name="name" required>
  10. 文章标题
  11. </MDinput>
  12. </el-form-item>
  13. <div class="postInfo-container">
  14. <div style="margin-bottom: 10px;">封面图</div>
  15. <el-form-item prop="cover_img" style="margin-bottom: 30px;" label="">
  16. <Upload v-model="postForm.cover_img" />
  17. </el-form-item>
  18. </div>
  19. </el-col>
  20. </el-row>
  21. <el-form-item prop="content" style="margin-bottom: 30px;">
  22. <Tinymce ref="editor" v-model="postForm.content" :height="400" />
  23. </el-form-item>
  24. <el-row>
  25. <el-button v-if="!isEdit" v-loading="loading" type="success" @click="submitForm">
  26. 提交
  27. </el-button>
  28. <el-button v-if="isEdit" v-loading="loading" type="success" @click="updateArticle">
  29. 修改
  30. </el-button>
  31. </el-row>
  32. </div>
  33. </el-form>
  34. </div>
  35. </template>
  36. <script>
  37. import Tinymce from '@/components/Tinymce'
  38. import Upload from '@/components/Upload/SingleImage3'
  39. import MDinput from '@/components/MDinput'
  40. // import Sticky from '@/components/Sticky' // 粘性header组件
  41. // import { validURL } from '@/utils/validate'
  42. import { fetchArticle, createArticle, updateArticle } from '@/api/article'
  43. import { searchUser } from '@/api/remote-search'
  44. import Warning from './Warning'
  45. // import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
  46. const defaultForm = {
  47. status: 'draft',
  48. title: '', // 文章题目
  49. content: '', // 文章内容
  50. content_short: '', // 文章摘要
  51. video_url: '', // 文章外链
  52. cover_img: '', // 文章图片
  53. display_time: undefined, // 前台展示时间
  54. id: undefined,
  55. platforms: ['a-platform'],
  56. comment_disabled: false,
  57. importance: 0
  58. }
  59. export default {
  60. name: 'ArticleDetail',
  61. components: { Tinymce, MDinput, Warning, Upload },
  62. props: {
  63. isEdit: {
  64. type: Boolean,
  65. default: false
  66. }
  67. },
  68. data() {
  69. const validateRequire = (rule, value, callback) => {
  70. if (value === '') {
  71. this.$message({
  72. message: rule.field + '为必传项',
  73. type: 'error'
  74. })
  75. callback(new Error(rule.field + '为必传项'))
  76. } else {
  77. callback()
  78. }
  79. }
  80. return {
  81. postForm: Object.assign({}, defaultForm),
  82. loading: false,
  83. userListOptions: [],
  84. rules: {
  85. cover_img: [{ message: '封面图不为空', validator: validateRequire }],
  86. title: [{ message: '标题不为空', validator: validateRequire }],
  87. content: [{ message: '内容不为空', validator: validateRequire }]
  88. },
  89. tempRoute: {}
  90. }
  91. },
  92. computed: {
  93. contentShortLength() {
  94. return this.postForm.content_short.length
  95. },
  96. displayTime: {
  97. // set and get is useful when the data
  98. // returned by the back end api is different from the front end
  99. // back end return => "2013-06-25 06:59:25"
  100. // front end need timestamp => 1372114765000
  101. get() {
  102. return (+new Date(this.postForm.display_time))
  103. },
  104. set(val) {
  105. this.postForm.display_time = new Date(val)
  106. }
  107. }
  108. },
  109. created() {
  110. if (this.isEdit) {
  111. const id = this.$route.params && this.$route.params.id
  112. this.fetchData(id)
  113. }
  114. // Why need to make a copy of this.$route here?
  115. // 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
  116. // https://github.com/PanJiaChen/vue-element-admin/issues/1221
  117. this.tempRoute = Object.assign({}, this.$route)
  118. },
  119. methods: {
  120. fetchData(id) {
  121. fetchArticle(id).then(response => {
  122. this.postForm = response.data.info
  123. // set tags view title
  124. // this.setTagsViewTitle()
  125. // set page title
  126. // this.setPageTitle()
  127. }).catch(err => {
  128. console.log(err)
  129. })
  130. },
  131. setPageTitle() {
  132. const title = 'Edit Article'
  133. document.title = `${title} - ${this.postForm.id}`
  134. },
  135. submitForm() {
  136. this.$refs.postForm.validate(valid => {
  137. if (valid) {
  138. this.loading = true
  139. console.log(this.postForm)
  140. createArticle(this.postForm).then(response => {
  141. this.$notify({
  142. title: '成功',
  143. message: '发布文章成功',
  144. type: 'success',
  145. duration: 2000
  146. })
  147. this.postForm.status = 'published'
  148. this.loading = false
  149. this.listLoading = false
  150. this.$router.push(`/article/list`)
  151. })
  152. } else {
  153. console.log('error submit!!')
  154. return false
  155. }
  156. })
  157. },
  158. updateArticle() {
  159. console.log(this.postForm)
  160. updateArticle(this.postForm).then(response => {
  161. this.$notify({
  162. title: '修改',
  163. message: '修改文章成功',
  164. type: 'success',
  165. duration: 2000
  166. })
  167. this.postForm.status = 'published'
  168. this.loading = false
  169. this.listLoading = false
  170. this.$router.push(`/article/list`)
  171. })
  172. },
  173. draftForm() {
  174. if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
  175. this.$message({
  176. message: '请填写必要的标题和内容',
  177. type: 'warning'
  178. })
  179. return
  180. }
  181. this.$message({
  182. message: '保存成功',
  183. type: 'success',
  184. showClose: true,
  185. duration: 1000
  186. })
  187. this.postForm.status = 'draft'
  188. },
  189. getRemoteUserList(query) {
  190. searchUser(query).then(response => {
  191. if (!response.data.items) return
  192. this.userListOptions = response.data.items.map(v => v.name)
  193. })
  194. }
  195. }
  196. }
  197. </script>
  198. <style lang="scss" scoped>
  199. @import "~@/styles/mixin.scss";
  200. .createPost-container {
  201. position: relative;
  202. .createPost-main-container {
  203. padding: 40px 45px 20px 50px;
  204. .postInfo-container {
  205. position: relative;
  206. @include clearfix;
  207. margin-bottom: 10px;
  208. .postInfo-container-item {
  209. float: left;
  210. }
  211. }
  212. }
  213. .word-counter {
  214. width: 40px;
  215. position: absolute;
  216. right: 10px;
  217. top: 0px;
  218. }
  219. }
  220. .article-textarea ::v-deep {
  221. textarea {
  222. padding-right: 40px;
  223. resize: none;
  224. border: none;
  225. border-radius: 0px;
  226. border-bottom: 1px solid #bfcbd9;
  227. }
  228. }
  229. </style>