【ant design vue】 使用wangeditor 做文章编辑 如何填充内容到编辑器中

问题描述

【ant design vue】 使用wangeditor 做文章编辑 如何填充内容到编辑器中

问题出现的环境背景及自己尝试过哪些方法

最近才是vue,不是很熟悉,我百度了相关问题都没有一个合适的解决方法,希望大神指教一下。

相关代码

组件

<template>
  <div :class="prefixCls">
    <div ref="editor" class="editor-wrapper"></div>
  </div>
</template>

<script>
import WEditor from 'wangeditor'

export default {
  name: 'WangEditor',
  props: {
    prefixCls: {
      type: String,
      default: 'ant-editor-wang'
    },
    // eslint-disable-next-line
    value: {
      type: String
    }
  },
  data () {
    return {
      editor: null,
      editorContent: null
    }
  },
  watch: {
    value (val) {
      this.editorContent = val
      this.editor.txt.html(val)
    }
  },
  mounted () {
    this.initEditor()
  },
  methods: {
    initEditor () {
      this.editor = new WEditor(this.$refs.editor)
      // this.editor.onchangeTimeout = 200
      this.editor.customConfig.onchange = (html) => {
        this.editorContent = html
        this.$emit('change', this.editorContent)
      }
      this.editor.create()
    }
  }
}
</script>

<style lang="less" scoped>
.ant-editor-wang {
  .editor-wrapper {
    text-align: left;
  }
}
</style>

编辑页面调用

<template>
  <a-card :bordered="false">
    <a-tabs type="card">
      <a-tab-pane key="1" tab="基本信息">
        <a-form @submit="handleSubmit" :form="form">
          <a-row class="form-row" :gutter="16">
            <a-col :lg="6" :md="12" :sm="24">
              <a-form-item label="书名">
                <a-input
                  allowClear
                  placeholder="请输入书名"
                  v-decorator="[
                    'books.title',
                    {initialValue: books.title},
                    {rules: [{ required: true, message: '请输入书名', whitespace: true}]}
                  ]" />
              </a-form-item>
            </a-col>
            <a-col :xl="{span: 7, offset: 1}" :lg="{span: 8}" :md="{span: 12}" :sm="24">
              <a-form-item
                label="作者">
                <a-input
                  allowClear
                  placeholder="请输入作者名称"
                  v-decorator="[
                    'books.author',
                    {initialValue: books.author},
                    {rules: [{ required: true, message: '请输入作者名称', whitespace: true}]}
                  ]" />
              </a-form-item>
            </a-col>
            <a-col :xl="{span: 9, offset: 1}" :lg="{span: 10}" :md="{span: 24}" :sm="24">
              <a-form-item
                label="类型">
                <a-select mode="multiple" allowClear placeholder="请选择类型" v-decorator="[ 'books.class_tree_id',{initialValue: parseInt(books.class_tree_id)}, {rules: [{ required: true, message: '请选择类型' }]} ]">
                  <a-select-option v-for="i in this.classtree" :key="i.id">{{ i.name }}</a-select-option>
                </a-select>
              </a-form-item>
            </a-col>
          </a-row>
          <a-row class="form-row" :gutter="16">
            <a-col :lg="6" :md="12" :sm="24">
              <a-form-item
                label="标签">
                <a-select allowClear mode="tags" placeholder="按Enter或Tab选中标签" v-decorator="[ 'books.tags', {initialValue: books.tags} ]">
                </a-select>
              </a-form-item>
            </a-col>
            <a-col :xl="{span: 7, offset: 1}" :lg="{span: 8}" :md="{span: 12}" :sm="24">
              <a-form-item
                label="简介">
                <a-input
                  type="textarea"
                  :rows="3"
                  placeholder="不填写自动获取第一页前100个字..."
                  v-decorator="[
                    'books.desc'
                  ]" />
              </a-form-item>
            </a-col>
            <a-col :xl="{span: 9, offset: 1}" :lg="{span: 10}" :md="{span: 24}" :sm="24">
              <a-form-item>
                <a-upload
                  name="file"
                  list-type="picture-card"
                  style="height: 102px;width: 102px;"
                  :show-upload-list="false"
                  :customRequest="customRequest"
                  :beforeUpload="beforeUpload"
                  @change="handleChange"
                >
                  <img v-if="imageUrl" :src="imageUrl" alt="avatar" style="width: 86px;height: 86px;" />
                  <div v-else>
                    <a-icon :type="loading ? 'loading' : 'plus'" />
                    <div class="ant-upload-text">
                      上传封面
                    </div>
                  </div>
                </a-upload>
              </a-form-item>
            </a-col>
          </a-row>
          <a-form-item
            v-for="(domain, index) in dynamicValidateForm.domains"
            :key="index"
            :props="'domains.' + index + '.value'"
          >
            <a-form-item
              label="页标题"
            >
              <a-input
                allowClear
                style="width: 50%;margin-right: 8px"
                v-decorator="[
                  `chapter.title[${index}]`,
                  {initialValue: domain.title},
                  { rules: [{ required: true, message: '请输入页标题' }] },
                ]"
                placeholder="页标题"
              />
              <a-input
                :disabled="true"
                style="width: 10%;margin-right: 8px;"
                v-decorator="[
                  `chapter.words[${index}]`,
                  {initialValue: domain.words}
                ]"
                placeholder="字数"
                suffix="个"
              />
              <a-tooltip placement="top">
                <template slot="title">
                  <span>移除</span>
                </template>
                <a-icon
                  v-if="dynamicValidateForm.domains.length > 1"
                  class="dynamic-delete-button"
                  type="minus-circle-o"
                  :disabled="dynamicValidateForm.domains.length === 1"
                  @click="removeDomain(domain)"
                />
              </a-tooltip>
            </a-form-item>
            <a-form-item
              label="页内容"
            >
              <wangeditor
                ref="editor"
                @change="changeEditor($event, index)"
                v-model="domain.content"
              >
              </wangeditor>
            </a-form-item>
          </a-form-item>
          <a-form-item>
            <a-button type="dashed" style="width: 100%" @click="addDomain">
              <a-icon type="plus" /> 添加页
            </a-button>
          </a-form-item>
          <a-form-item>
            <a-button type="primary" htmlType="submit" style="margin-right: 8px;">
              提交
            </a-button>
            <a-button @click="handleGo">
              返回
            </a-button>
          </a-form-item>
        </a-form>
      </a-tab-pane>
      <!-- <a-tab-pane key="2" tab="其他信息">
        Content of Tab Pane 2
      </a-tab-pane> -->
    </a-tabs>
  </a-card>
</template>

<script>
import Wangeditor from '@/components/Editor/WangEditor'
import { getClassTreeList } from '@/api/classtree'
import { upload, read, update } from '@/api/books'
import { refreshMenus } from '@/utils/util'

export default {
  name: 'BooksEdit',
  components: {
    Wangeditor
  },
  data () {
    return {
      id: this.$route.query.id,
      form: this.$form.createForm(this),
      loading: false,
      imageUrl: '',
      dynamicValidateForm: {
        domains: []
      },
      classtree: [],
      books: {
        cover: ''
      },
      chapter: {
        words: []
      },
      content: [],
      words: [],
      words_obj: {}
    }
  },
  created () {
    // 获取书籍分类列表
    this.getTypeList()
    // 获取图书信息
    this.getBookInfo(this.id)
  },
  methods: {
    // 提交
    handleSubmit (e) {
      e.preventDefault()
      const { form: { validateFields } } = this
      validateFields((errors, values) => {
        if (!errors) {
          values['content'] = this.content
          values['books']['cover'] = this.books.cover
          update(this.id, values).then((res) => {
            this.refresh(res.msg)
            refreshMenus()
          }).catch(err => this.failed(err))
        }
      })
    },
    // 成功
    refresh (message) {
      this.$notification['success']({
        message: message,
        duration: 4
      })
      this.handleGo()
    },
    // 失败
    failed (errors) {
      this.$notification['error']({
        message: errors.message,
        duration: 4
      })
    },
    // 返回上一页
    handleGo () {
      this.$router.go(-1) // 返回上一层
    },
    // 重置
    handleReset () {
      this.form.resetFields()
    },
    // 点击上传图片
    handleChange (info) {
      if (info.file.status === 'uploading') {
        this.loading = true
        return
      }
      if (info.file.status === 'done') {
        this.$message.success(`${info.file.name} 上传成功`)
      }
      if (info.file.status === 'error') {
        this.$message.error(`${info.file.name} 上传失败`)
      }
    },
    // 上传前回调
    beforeUpload (file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
      if (!isJpgOrPng) {
        this.$message.error('你只能上传JPG或PNG文件!')
      }
      const isLt2M = file.size / 1024 / 1024 < 2
      if (!isLt2M) {
        this.$message.error('图像必须小于2MB!')
      }
      return isJpgOrPng && isLt2M
    },
    customRequest (file) { // 上传提交
      const formData = new FormData()
      formData.append('file', file.file)
      formData.append('token', 'token')
      this.saveFile(formData)
    },
    // 回调
    saveFile (formData) {
      upload(formData).then((res) => {
        if (res) {
          this.books.cover = res.data
          this.imageUrl = process.env.VUE_APP_API_URL + res.data
          this.loading = false
        }
      }).catch((err) => {
        this.loading = false
        this.$message.error(err)
      })
    },
    // 添加页
    addDomain () {
      this.dynamicValidateForm.domains.push({
        words: '',
        title: '',
        content: ''
      })
    },
    // 移除页
    removeDomain (item) {
      const index = this.dynamicValidateForm.domains.indexOf(item)
      if (index !== -1) {
        this.dynamicValidateForm.domains.splice(index, 1)
        this.content.splice(index, 1)
      }
    },
    // 获取分类列表
    getTypeList () {
      getClassTreeList().then(res => {
        this.classtree = res.data
      })
    },
    // 获取图书信息
    getBookInfo ($id) {
      read($id).then(res => {
        this.books = res.data
        // 封面
        this.imageUrl = process.env.VUE_APP_API_URL + res.data.cover
        this.dynamicValidateForm.domains = res.data.chapter_content
      })
    },
    // 正文内容
    changeEditor (val, index) {
      this.content[index] = val
      // 字数
      this.chapter.words[index] = this.$refs.editor[index].$refs.editor.innerText.length
      // 设置表单字段值
      this.$set(this.words_obj, 'chapter.words[' + index + ']', this.chapter.words[index])
      const { form: { setFieldsValue } } = this
      this.$nextTick(() => {
        setFieldsValue(this.words_obj)
      })
    }
  }
}
</script>
<style lang="less" scoped>
  .dynamic-delete-button {
    cursor: pointer;
    position: relative;
    top: 4px;
    font-size: 24px;
    color: #999;
    transition: all 0.3s;
  }
  .dynamic-delete-button:hover {
    color: #777;
  }
  .dynamic-delete-button[disabled] {
    cursor: not-allowed;
    opacity: 0.5;
  }
  .ant-upload-text {
    margin-top: 8px;
    color: #666;
  }
</style>
阅读 2.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏