sql语句:格式化+代码高亮+复制代码

873 阅读1分钟

引用包

npm install react-copy-to-clipboard sql-formatter react-highlight
// js 格式化用:json-stringify-pretty-compact

自定义组件

import React from "react";
import { format } from 'sql-formatter'
import { CopyToClipboard } from 'react-copy-to-clipboard';
import Highlight from 'react-highlight'
import styles from './CustomCodeBlock.module.scss'
import 'highlight.js/styles/zenburn.css'
import { message } from "antd";

export default function CustomCodeBlock({ code }) {

  const handleCopy = (text, result) => {
    result ?  message.success('复制代码成功', 1) : message.error('复制代码失败', 1)
  }
  return (
    <div className={styles.container}>
      <Highlight className={styles.code}>{format(code)}</Highlight>

      <CopyToClipboard
        text={code}
        onCopy={(text, result) => handleCopy(text, result)}
      >
        <button className={styles.copyBtn}>复制代码</button>
      </CopyToClipboard>
    </div>
  );
}
.container {
    position: relative;
    
    .code {
        display: block;
        border-radius: 5px;
        padding: 20px;
        line-height: 18px;
    }
    .copyBtn {
        position: absolute;
        top: 0;
        right: 0;
        filter: brightness(0.5);
        border-radius: 5px;
        &:hover {
            cursor: pointer;
            filter: brightness(0.8);
        }
    } 
}

或者使用原生的 JS API

不使用 react-copy-to-clipboard

import React from "react";
import { format } from 'sql-formatter'
import Highlight from 'react-highlight'
import styles from './CustomCodeBlock.module.scss'
import 'highlight.js/styles/zenburn.css'
import { message } from "antd";

export default function CustomCodeBlock({ code }) {
 
  function copyToClipboard(textToCopy) {
    // navigator clipboard 需要在https等安全上下文下才能使用
    if (navigator.clipboard && window.isSecureContext) {
        // navigator clipboard 向剪贴板写文本
        return navigator.clipboard.writeText(textToCopy);
    } else {
        // 创建text area
        let textArea = document.createElement("textarea");
        textArea.value = textToCopy;
        // 使text area不在viewport,同时设置不可见
        textArea.style.position = "absolute";
        textArea.style.opacity = 0;
        textArea.style.left = "-999999px";
        textArea.style.top = "-999999px";
        document.body.appendChild(textArea);
        // 获取焦点和选中
        textArea.focus();
        textArea.select();
        return new Promise((res, rej) => {
            // 执行复制命令并移除文本框
            document.execCommand('copy') ? res() : rej();
            textArea.remove();
        });
    }
}



  const onCopy = () => {
     copyToClipboard(code)
      .then((res) => {
        message.success('复制代码成功', 1) 
      })
      .catch((err) => {
        message.error(err ? err.toString() : '复制代码失败', 1)
      });
  }

  
  return (
    <div className={styles.container}>
      <Highlight className={styles.code}>{format(code)}</Highlight>
      <button className={styles.copyBtn} onClick={() => onCopy(code)}>复制代码</button>
    </div>

  );
}

使用组件

import React, { Component } from 'react';
import CustomCodeBlock from './CustomCodeBlock/CustomCodeBlock';

export defualt function Demo(props) {
    const sql = "SELECT FROM_UNIXTIME(add_time,'%Y-%m-%d') as dt ,business_id as bsid, 'ka' as supplier ,sum(if(is_show_human=1,1,0)) as row_cnt, sum(if(is_show_human=1,1,0)) as cnt, count(1) as aichk_cnt, '' as hour , '' as platform, 'audio' as content_type FROM audio_audit_list_202304 WHERE FROM_UNIXTIME(add_time,'%Y-%m-%d') >='2023-04-01' and FROM_UNIXTIME(add_time,'%Y-%m-%d') <='2023-04-30' AND sec_human_result in (1,2) GROUP BY dt, bsid"

    return(
       <CustomCodeBlock code={sql}/> : <span></span>
    ) 
}

效果: image.png