跳到主要内容

代码高亮组件

template:

const content =
'/**\n * Axios 请求封装\n * 提供统一的请求拦截、响应拦截和错误处理\n */\n\nimport axios, {\n type AxiosInstance,\n type AxiosRequestConfig,\n type AxiosResponse,\n type InternalAxiosRequestConfig,\n} from "axios";\nimport { message } from "antd";\nimport { envConfig, isPrivate } from "@/config/env";\nimport type { ApiResponse, RequestConfig } from "@/types/api";\n// import { StatusCode } from "./statusCode.ts";\n\n// 扩展 AxiosRequestConfig,添加自定义配置\ndeclare module "axios" {\n export interface AxiosRequestConfig extends RequestConfig {}\n}\n\n// 需要添加loginType的API模块\nconst API_MODULES = ["/api/saas/"];\n\n// 从URL地址栏获取loginType\nexport const getLoginTypeFromURL = () => {\n const urlParams = new URLSearchParams(window.location.search);\n return urlParams.get("loginType");\n};\n\n/**\n * 创建 axios 实例\n */\nconst service: AxiosInstance = axios.create({\n baseURL: envConfig.API_URL,\n timeout: 30000, // 30秒超时\n headers: {\n "Content-Type": "application/json;charset=UTF-8",\n },\n});\n\n/**\n * 请求拦截器\n * 在发送请求之前做些什么\n */\nservice.interceptors.request.use(\n (config: InternalAxiosRequestConfig) => {\n const url = config.url || "";\n\n // 0. 处理自定义 baseURL\n // 如果配置中指定了 baseURL,使用指定的 baseURL\n // 如果 URL 是完整 URL(以 http:// 或 https:// 开头),则忽略 baseURL\n if (config.baseURL) {\n // 使用配置中的 baseURL\n // axios 会自动处理\n } else {\n // 如果 URL 是完整 URL,清除 baseURL,让 axios 使用完整 URL\n if (url.startsWith("http://") || url.startsWith("https://")) {\n config.baseURL = "";\n }\n }\n\n // 1. 添加其他通用请求头\n config.headers = config.headers || {};\n // 可以添加时间戳防止缓存\n // config.headers[\'X-Timestamp\'] = Date.now().toString()\n\n // 如果请求已经存在loginType,跳过\n if (config.headers.loginType) {\n return config;\n }\n // 检查是否为目标API模块\n const isTargetAPI = API_MODULES.some((module) => url.includes(module));\n\n if (isTargetAPI) {\n // 优先从地址栏获取loginType\n let loginType = getLoginTypeFromURL();\n\n if (!loginType && isPrivate) {\n loginType =\n localStorage.getItem("loginTypePrivate") || envConfig.LOGIN_TYPE;\n } else {\n // 如果sessionStorage也不存在,使用默认值\n if (!loginType) {\n loginType = envConfig.LOGIN_TYPE;\n }\n }\n\n // 添加到headers\n config.headers.loginType = loginType;\n }\n\n // 3. 处理请求参数(如果需要)\n // 例如:序列化数组参数、添加公共参数等\n\n // 4. 打印请求信息(开发环境)\n if (envConfig.DEBUG) {\n console.log("🚀 请求发送:", {\n url: config.url,\n method: config.method,\n params: config.params,\n data: config.data,\n });\n }\n\n return config;\n },\n (error) => {\n // 请求错误处理\n console.error("❌ 请求错误:", error);\n return Promise.reject(error);\n },\n);\n\n/**\n * 响应拦截器\n * 对响应数据做点什么\n */\nservice.interceptors.response.use(\n (response: AxiosResponse<ApiResponse>) => {\n const { data, config } = response;\n\n // 如果配置了跳过响应拦截器,直接返回原始响应\n if ((config as RequestConfig).skipResponseInterceptor) {\n return response;\n }\n\n // 根据后端返回的数据结构处理\n // 假设后端返回格式为: { code: 0, data: {...}, msg: \'...\' }\n if (data.code === 0 || data.code === 200 || data.success === true) {\n // 请求成功\n if (envConfig.DEBUG) {\n console.log("✅ 请求成功:", {\n url: config.url,\n data: data.data,\n });\n }\n\n // 直接返回 data,这样在业务代码中可以直接使用 response.data\n return data.data;\n } else {\n // 业务错误(code 不为 0)\n const errorMessage = data.msg || data.message || "请求失败";\n\n if (envConfig.DEBUG) {\n console.error("❌ 业务错误:", {\n url: config.url,\n code: data.code,\n message: errorMessage,\n });\n }\n\n // 处理特殊错误码\n // handleErrorCode(data.code, errorMessage);\n\n return Promise.reject(new Error(errorMessage));\n }\n },\n (error) => {\n // HTTP 错误处理\n const { response, config } = error;\n\n if (envConfig.DEBUG) {\n console.error("❌ HTTP 错误:", {\n url: config?.url,\n status: response?.status,\n message: error.message,\n });\n }\n\n if (response) {\n // 服务器返回了错误状态码\n const { status, data } = response;\n let errorMessage = "请求失败";\n\n switch (status) {\n case 400:\n errorMessage = data?.msg || data?.message || "请求参数错误";\n break;\n case 401:\n errorMessage = "未授权,请重新登录";\n // 清除 token,跳转到登录页\n clearToken();\n // 可以在这里添加跳转登录的逻辑\n // window.location.href = \'/login\'\n break;\n case 403:\n errorMessage = "拒绝访问";\n break;\n case 404:\n errorMessage = "请求的资源不存在";\n break;\n case 500:\n errorMessage = "服务器内部错误";\n break;\n case 502:\n errorMessage = "网关错误";\n break;\n case 503:\n errorMessage = "服务不可用";\n break;\n case 504:\n errorMessage = "网关超时";\n break;\n default:\n errorMessage = data?.msg || data?.message || `请求失败 (${status})`;\n }\n\n // 显示错误提示\n if ((config as RequestConfig)?.showError !== false) {\n message.error((config as RequestConfig)?.errorMessage || errorMessage);\n }\n\n return Promise.reject(new Error(errorMessage));\n } else if (error.request) {\n // 请求已发出,但没有收到响应\n const errorMessage = "网络错误,请检查网络连接";\n if ((config as RequestConfig)?.showError !== false) {\n message.error(errorMessage);\n }\n return Promise.reject(new Error(errorMessage));\n } else {\n // 在设置请求时发生了一些事情,触发了错误\n return Promise.reject(error);\n }\n },\n);\n\n\n/**\n * 清除 token\n */\nfunction clearToken(): void {\n localStorage.removeItem("token");\n sessionStorage.removeItem("token");\n}\n\n/**\n * 处理错误码\n * 根据业务需求处理特定的错误码\n */\n// function handleErrorCode(code: number): void {\n// switch (code) {\n// case 401:\n// // 未授权,清除 token 并跳转登录\n// // clearToken();\n// // window.location.href = \'/login\'\n// break;\n// case 403:\n// // 无权限\n// break;\n// // 可以根据业务需求添加更多错误码处理\n// default:\n// break;\n// }\n// }\n\n/**\n * 封装请求方法\n */\nconst request = {\n /**\n * GET 请求\n */\n get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {\n return service.get<ApiResponse<T>, T>(url, config);\n },\n\n /**\n * POST 请求\n */\n post<T = any>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig,\n ): Promise<T> {\n return service.post<ApiResponse<T>, T>(url, data, config);\n },\n\n /**\n * PUT 请求\n */\n put<T = any>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig,\n ): Promise<T> {\n return service.put<ApiResponse<T>, T>(url, data, config);\n },\n\n /**\n * DELETE 请求\n */\n delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {\n return service.delete<ApiResponse<T>, T>(url, config);\n },\n\n /**\n * PATCH 请求\n */\n patch<T = any>(\n url: string,\n data?: any,\n config?: AxiosRequestConfig,\n ): Promise<T> {\n return service.patch<ApiResponse<T>, T>(url, data, config);\n },\n};\n\n// 导出 axios 实例(如果需要直接使用)\nexport { service as axiosInstance };\n\n// 导出请求方法\nexport default request;\n';

prism-react-renderer

// PrismReactRender.tsx
import { Highlight, themes } from 'prism-react-renderer';

const AdvancedCode = ({ code, language = 'javascript' }) => {
const handleCopy = () => {
navigator.clipboard.writeText(code);
alert('代码已复制!');
};

return (
<div style={{ position: 'relative' }}>
{/* 复制按钮 */}
<button
onClick={handleCopy}
style={{
position: 'absolute',
top: '10px',
right: '10px',
zIndex: 1,
padding: '5px 10px',
cursor: 'pointer',
}}
>
Copy
</button>

<Highlight
theme={themes.dracula}
code={code.trim()}
language={language}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre
className={className}
style={{ ...style, padding: '20px', overflowX: 'auto' }}
>
{tokens.map((line, i) => (
<div
key={i}
{...getLineProps({ line })}
style={{ display: 'flex', lineHeight: 1.4 }}
>
{/* 行号 */}
<span
style={{
userSelect: 'none',
opacity: 0.5,
paddingRight: '15px',
textAlign: 'right',
minWidth: '30px',
}}
>
{i + 1}
</span>

{/* 代码内容 */}
<span style={{ flex: 1 }}>
{line.map((token, key) => (
<span
key={key}
{...getTokenProps({ token })}
/>
))}
</span>
</div>
))}
</pre>
)}
</Highlight>
</div>
);
};

export default AdvancedCode;

react-syntax-highlighter

// CodeHighlighter.tsx
import SyntaxHighlighter from 'react-syntax-highlighter';
import { a11yLight } from 'react-syntax-highlighter/dist/esm/styles/hljs';

/**
* 添加行号的代码显示组件(使用 react-syntax-highlighter 实现语法高亮)
* @param content 文件内容
* @param language 语言类型
*/
const CodeHighlighter: React.FC<{ code: string; language: string }> = ({ code, language }) => {
return (
<SyntaxHighlighter
language={language}
style={a11yLight}
showLineNumbers={true}
lineNumberStyle={{
minWidth: '50px',
paddingRight: '12px',
color: '#6a737d',
userSelect: 'none',
}}
customStyle={{
margin: 0,
background: 'transparent',
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", monospace',
fontSize: '14px',
lineHeight: '1.5',
height: '100%',
}}
>
{code}
</SyntaxHighlighter>
);
};

export default CodeHighlighter;