引用包
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>
)
}
效果: