ready
论坛版主
论坛版主
  • UID24
  • 粉丝0
  • 关注0
  • 发帖数452
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:60回复:0

@wangEditor 增加html代码编辑 功能

楼主#
更多 发布于:2026-04-13 17:41
若依、芋道 vue3 & wangEditor @wangEditor 增加html代码编辑 功能:


在 components -- Editor -- src -- 更改editor.vue


<template>
  <div class="border-1 border-solid border-[var(--tags-view-border-color)] z-10">
<div
      class="flex items-center justify-between border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]"
    >
<!-- 工具栏 -->
   <Toolbar
        v-show="!sourceMode"
        :editor="editorRef"
        :editorId="editorId"
        class="border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]"
      />

       <button
        type="button"
        class="px-3 py-1 text-sm border border-gray-300 rounded hover:bg-gray-50"
        @click="toggleSourceMode"
      >
        pw_ sourceMode ? '退出源码' : '源码编辑'
      </button>
</div>


    <div v-show="sourceMode" class="p-3 bg-white">
      <textarea
        v-model="sourceHtml"
        :style="sourceTextareaStyle"
        class="w-full border rounded p-2 font-mono"
      ></textarea>
    </div>



    <!-- 编辑器 -->
    <Editor v-show="!sourceMode" v-model="valueHtml"
      :defaultConfig="editorConfig"
      :editorId="editorId"
      :style="editorStyle"
      @on-change="handleChange"
      @on-created="handleCreated"
    />
  </div>

</template>

<script lang="ts" setup>
import { PropType } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { i18nChangeLanguage, IDomEditor, IEditorConfig } from '@wangeditor/editor'
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
import { ElMessage } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { getRefreshToken, getTenantId } from '@/utils/auth'
import { getUploadUrl } from '@/components/UploadFile/src/useUpload'
import { min } from 'lodash-es'

defineOptions({ name: 'Editor' })

type InsertFnType = (url: string, alt: string, href: string) => void

const localeStore = useLocaleStore()

const currentLocale = computed(() => localeStore.getCurrentLocale)

const sourceMode = ref(false)
const sourceHtml = ref('')

i18nChangeLanguage(unref(currentLocale).lang)

const props = defineProps({
  editorId: propTypes.string.def('wangeEditor-1'),
  height: propTypes.oneOfType([Number, String]).def('500px'),
  editorConfig: {
    type: Object as PropType<Partial<IEditorConfig>>,
    default: () => undefined
  },
  readonly: propTypes.bool.def(false),
  modelValue: propTypes.string.def('')
})

const emit = defineEmits(['change', 'update:modelValue'])

// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()

const valueHtml = ref('')

watch(
  () => props.modelValue,
  (val: string) => {
    if (val === unref(valueHtml)) return
    valueHtml.value = val
  },
  {
    immediate: true
  }
)

// 监听
watch(
  () => valueHtml.value,
  (val: string) => {
    emit('update:modelValue', val)
  }
)

const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor
}

// 编辑器配置
const editorConfig = computed((): IEditorConfig => {
  return Object.assign(
    {
      placeholder: '请输入内容...',
      readOnly: props.readonly,
      customAlert: (s: string, t: string) => {
        switch (t) {
          case 'success':
            ElMessage.success(s)
            break
          case 'info':
            ElMessage.info(s)
            break
          case 'warning':
            ElMessage.warning(s)
            break
          case 'error':
            ElMessage.error(s)
            break
          default:
            ElMessage.info(s)
            break
        }
      },
      autoFocus: false,
      scroll: true,
      MENU_CONF: {
        ['uploadImage']: {
          server: getUploadUrl(),
          // 单个文件的最大体积限制,默认为 2M
          maxFileSize: 5 * 1024 * 1024,
          // 最多可上传几个文件,默认为 100
          maxNumberOfFiles: 10,
          // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
          allowedFileTypes: ['image/*'],

          // 自定义增加 http  header
          headers: {
            Accept: '*',
            Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:Editor 无法方便的刷新访问令牌
            'tenant-id': getTenantId()
          },

          // 超时时间,默认为 10 秒
          timeout: 15 * 1000, // 15 秒

          // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
          fieldName: 'file',

          // 上传之前触发
          onBeforeUpload(file: File) {
            // console.log(file)
            return file
          },
          // 上传进度的回调函数
          onProgress(progress: number) {
            // progress 是 0-100 的数字
            console.log('progress', progress)
          },
          onSuccess(file: File, res: any) {
            console.log('onSuccess', file, res)
          },
          onFailed(file: File, res: any) {
            alert(res.message)
            console.log('onFailed', file, res)
          },
          onError(file: File, err: any, res: any) {
            alert(err.message)
            console.error('onError', file, err, res)
          },
          // 自定义插入图片
          customInsert(res: any, insertFn: InsertFnType) {
            insertFn(res.data, 'image', res.data)
          }
        },
        ['uploadVideo']: {
          server: getUploadUrl(),
          // 单个文件的最大体积限制,默认为 10M
          maxFileSize: 10 * 1024 * 1024,
          // 最多可上传几个文件,默认为 100
          maxNumberOfFiles: 10,
          // 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
          allowedFileTypes: ['video/*'],

          // 自定义增加 http  header
          headers: {
            Accept: '*',
            Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:Editor 无法方便的刷新访问令牌
            'tenant-id': getTenantId()
          },

          // 超时时间,默认为 30 秒
          timeout: 15 * 1000, // 15 秒

          // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
          fieldName: 'file',

          // 上传之前触发
          onBeforeUpload(file: File) {
            // console.log(file)
            return file
          },
          // 上传进度的回调函数
          onProgress(progress: number) {
            // progress 是 0-100 的数字
            console.log('progress', progress)
          },
          onSuccess(file: File, res: any) {
            console.log('onSuccess', file, res)
          },
          onFailed(file: File, res: any) {
            alert(res.message)
            console.log('onFailed', file, res)
          },
          onError(file: File, err: any, res: any) {
            alert(err.message)
            console.error('onError', file, err, res)
          },
          // 自定义插入图片
          customInsert(res: any, insertFn: InsertFnType) {
            insertFn(res.data, 'mp4', res.data)
          }
        }
      },
      uploadImgShowBase64: true, codeSelectLang: {
        HTML: 'HTML',
        CSS: 'CSS',
        JavaScript: 'JavaScript',
        TypeScript: 'TypeScript',
        JSON: 'JSON',
        XML: 'XML',
        SQL: 'SQL',
        Java: 'Java',
        Python: 'Python'
      }
},
    props.editorConfig || {}
  )
})


const sourceTextareaStyle = computed(() => ({
  width: '80%',
  minWidth: `1150px`,
  minHeight: '200px',
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Courier New", monospace'
}))



const editorStyle = computed(() => {
  return {
    height: isNumber(props.height) ? `${props.height}px` : props.height
  }
})


const toggleSourceMode = async () => {
  if (!sourceMode.value) {
    sourceHtml.value = unref(editorRef)?.getHtml() ?? valueHtml.value
    sourceMode.value = true
    return
  }

  sourceMode.value = false
  valueHtml.value = sourceHtml.value

  await nextTick()
  const editor = unref(editorRef)
  if (editor) {
    editor.setHtml(sourceHtml.value)
    editor.focus()
  }
}



// 回调函数
const handleChange = (editor: IDomEditor) => {
  emit('change', editor)
}

// 组件销毁时,及时销毁编辑器
onBeforeUnmount(() => {
  const editor = unref(editorRef.value)

  // 销毁,并移除 editor
  editor?.destroy()
})

const getEditorRef = async (): Promise<IDomEditor> => {
  await nextTick()
  return unref(editorRef.value) as IDomEditor
}

defineExpose({
  getEditorRef
})
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss">
.w-e-text-placeholder {
  top: 7px !important;
}
</style>
游客


返回顶部