当前位置: 首页 > 工具软件 > react-cursor > 使用案例 >

React中:富文本编辑器(react-quill),自定义上传图片到阿里云

巴英韶
2023-12-01
import React, { useState, useEffect, useRef, useMemo } from 'react';
import ReactQuill from 'react-quill';
import { message } from 'antd';
import 'react-quill/dist/quill.snow.css';
import { getTokenApi } from '@/services/user/login';
import { getAliOss } from '@/services/public/api';
import { randomWord } from '@/utils/index';
import { request } from 'umi';
import OSS from 'ali-oss';

const Index: React.FC<any> = (props) => {
  const { value, width, height, handleParams } = props;
  let refs: any = useRef(null);
  const [valueText, setValue] = useState('');
  const [widthText, setWidth] = useState('1010px');
  const [heightText, setHeight] = useState('300px');

  const modules: any = useMemo(
    // useMemo: 解决自定义失焦问题
    () => ({
      toolbar: {
        container: [
          ['bold', 'italic', 'underline', 'strike'], // 加粗,斜体,下划线,删除线
          ['blockquote', 'code-block'], // 引用,代码块
          ['link', 'image' /**'video' */], // 上传链接、图片、上传视频
          [{ header: 1 }, { header: 2 }], // 标题,键值对的形式;1、2表示字体大小
          [{ list: 'ordered' }, { list: 'bullet' }], // 列表
          [{ script: 'sub' }, { script: 'super' }], // 上下标
          [{ indent: '-1' }, { indent: '+1' }], // 缩进
          [{ direction: 'rtl' }], // 文本方向
          [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
          [{ header: [1, 2, 3, 4, 5, 6, false] }], // 几级标题
          [{ color: [] }, { background: [] }], // 字体颜色,字体背景颜色
          [{ font: [] }], // 字体
          [{ align: [] }], // 对齐方式
          ['clean'], // 清除字体样式
        ],
        handlers: {
          image: () => {
            imageHandler.call(this, props);
          },
        },
      },
    }),
    [],
  );
  // 自定义上传图片
  const imageHandler = (action) => {
    const input: any = document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('accept', 'image/*');
    input.click();
    input.onchange = async () => {
      /*****************************************************ali-oss*****************************************************/
      // const client = new OSS({
      //   region: 'oss-cn-hangzhou',
      //   accessKeyId: 'LTxxxxxxxxxxxxxxxxxxx',
      //   accessKeySecret: 'XYxxxxxxxxxxxxxx',
      //   // stsToken: data.SecurityToken,
      //   bucket: 'bucketuploadfiles',
      // });
      const { data } = await getAliOss({});
      const client = new OSS({
        region: 'oss-cn-shanghai',
        accessKeyId: data.AccessKeyId,
        accessKeySecret: data.AccessKeySecret,
        stsToken: data.SecurityToken,
        refreshSTSToken: async () => {
          // 向您搭建的STS服务获取临时访问凭证。
          const info = await getAliOss({});
          return {
            accessKeyId: info.data.AccessKeyId,
            accessKeySecret: info.data.AccessKeySecret,
            stsToken: info.data.SecurityToken,
          };
        },
        expiration: data.Expiration,
        // 刷新临时访问凭证的时间间隔,单位为毫秒。
        refreshSTSTokenInterval: 300000,
        // 填写Bucket名称。
        bucket: 'upload-files',
      });
      try {
        const file = input.files[0];
        const hide = message.loading('上传中...', 0);
        // const fileName = 'ali-oss/upload/images/' + randomWord(false, 50, 50);
        const fileName = 'images/' + randomWord(false, 50, 50);
        const { name, res, url } = await client.put(fileName, file);
        // console.log('上传结果', name, res, url);
        if (res.status === 200) {
          let quill = refs?.current?.getEditor(); //获取到编辑器本身
          const cursorPosition = quill.getSelection().index; //获取当前光标位置
          const link = 'httpxxxxxxxxxxxxx.com/' + name; // 图片链接
          quill.insertEmbed(cursorPosition, 'image', link); //插入图片
          quill.setSelection(cursorPosition + 1); //光标位置加1
          hide();
        }
      } catch (error) {}
      /*****************************************************ali-oss*****************************************************/
      /****************************************七牛云 (https://xxxxxx)****************************************/
      // const { data } = await getTokenApi({});
      // const file = input.files[0];
      // const formData = new FormData();
      // formData.append('key', randomWord(false, 40, 50));
      // formData.append('token', data.uploadToken);
      // formData.append('file', file);
      // const hide = message.loading('上传中...', 0);
      // request('https://xxxxxxxxxxxx', {
      //   method: 'POST',
      //   data: formData,
      //   headers: { 'Content-Type': 'application/json' },
      // }).then(async (res) => {
      //   try {
      //     // console.log('上传结果', res);
      //     const url = 'https://xxxxxxxxxx.com/' + res.key; // 预览,获取url
      //     let quill = refs?.current?.getEditor(); //获取到编辑器本身
      //     const cursorPosition = quill.getSelection().index; //获取当前光标位置
      //     quill.insertEmbed(cursorPosition, 'image', url); //插入图片
      //     quill.setSelection(cursorPosition + 1); //光标位置加1
      //     hide();
      //   } catch (error) {}
      // });
      /****************************************七牛云 (https://xxxxxxxx)****************************************/
    };
  };
  const handleHtml = (e) => {
    setValue(e);
    handleParams(e);
  };
  const options: any = {
    placeholder: '请输入内容...',
    theme: 'snow',
    readOnly: false, // 是否只读
    className: 'ql-editor', //组件要加上(className=“ql-editor”)样式类名,否则空格不回显
    onChange: handleHtml,
    value: valueText,
    modules: modules,
    ref: refs,
    style: {
      width: widthText,
      height: heightText,
      overflow: 'hidden',
      borderBottom: '1px solid #ccc',
    },
  };
  useEffect(() => {
    setWidth(width ? width : '1010px');
    setHeight(height ? height : '300px');
  }, []);
  useEffect(() => {
    setValue(value ? value : '');
  }, [value]);
  return (
    <div>
      <ReactQuill {...options} />
    </div>
  );
};

export default Index;

 类似资料: