diff --git a/components/animate-ui/components/code-tabs.tsx b/components/animate-ui/components/code-tabs.tsx index 70f990b..a80bcbe 100644 --- a/components/animate-ui/components/code-tabs.tsx +++ b/components/animate-ui/components/code-tabs.tsx @@ -3,20 +3,18 @@ import * as React from 'react'; import { useTheme } from 'next-themes'; -import { cn } from '@/lib/utils'; -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, - TabsContents, - type TabsProps, -} from '@/components/animate-ui/components/tabs'; +import { cn, replaceTabIndex } from '@/lib/utils'; +import { Tabs, TabsContent, TabsList, TabsTrigger, TabsContents, type TabsProps } from '@/components/animate-ui/components/tabs'; import { CopyButton } from '@/components/animate-ui/buttons/copy'; -type CodeTabsProps = { - codes: Record; +type CodeItem = { + name: string; lang?: string; + code: string; +}; + +type CodeTabsProps = { + codes: CodeItem[]; themes?: { light: string; dark: string; @@ -25,12 +23,16 @@ type CodeTabsProps = { onCopy?: (content: string) => void; } & Omit; +/** + * Note: 在 MDX 文档中使用该组件时需要包裹一层 Wrapper,从内部传入 Props,以确保正确渲染代码块中的缩进。 + * + * Refs: #99 + */ function CodeTabs({ codes, - lang = 'bash', themes = { light: 'github-light', - dark: 'github-dark', + dark: 'github-dark' }, className, defaultValue, @@ -42,13 +44,8 @@ function CodeTabs({ }: CodeTabsProps) { const { resolvedTheme } = useTheme(); - const [highlightedCodes, setHighlightedCodes] = React.useState | null>(null); - const [selectedCode, setSelectedCode] = React.useState( - value ?? defaultValue ?? Object.keys(codes)[0] ?? '', - ); + const [highlightedCodes, setHighlightedCodes] = React.useState | null>(null); + const [selectedCode, setSelectedCode] = React.useState(value ?? defaultValue ?? codes[0]?.name ?? ''); React.useEffect(() => { async function loadHighlightedCode() { @@ -56,35 +53,37 @@ function CodeTabs({ const { codeToHtml } = await import('shiki'); const newHighlightedCodes: Record = {}; - for (const [command, val] of Object.entries(codes)) { - const highlighted = await codeToHtml(val, { - lang, + for (const codeItem of codes) { + const highlighted = await codeToHtml(codeItem.code, { + lang: codeItem.lang || codeItem.name.toLowerCase(), themes: { light: themes.light, - dark: themes.dark, + dark: themes.dark }, - defaultColor: resolvedTheme === 'dark' ? 'dark' : 'light', + defaultColor: resolvedTheme === 'dark' ? 'dark' : 'light' }); - newHighlightedCodes[command] = highlighted; + newHighlightedCodes[codeItem.name] = replaceTabIndex(highlighted); } setHighlightedCodes(newHighlightedCodes); } catch (error) { console.error('Error highlighting codes', error); - setHighlightedCodes(codes); + // 降级处理:创建简单的文本映射 + const fallbackCodes: Record = {}; + codes.forEach((item) => { + fallbackCodes[item.name] = item.code; + }); + setHighlightedCodes(fallbackCodes); } } loadHighlightedCode(); - }, [resolvedTheme, lang, themes.light, themes.dark, codes]); + }, [resolvedTheme, themes.light, themes.dark, codes]); return ( { @@ -100,39 +99,21 @@ function CodeTabs({
{highlightedCodes && Object.keys(highlightedCodes).map((code) => ( - + {code} ))}
{copyButton && highlightedCodes && ( - + item.name === selectedCode)?.code || ''} size="sm" variant="ghost" className="-me-2 bg-transparent hover:bg-black/5 dark:hover:bg-white/10" onCopy={onCopy} /> )} {highlightedCodes && Object.entries(highlightedCodes).map(([code, val]) => ( - -
+ +
))} @@ -140,4 +121,4 @@ function CodeTabs({ ); } -export { CodeTabs, type CodeTabsProps }; +export { CodeTabs, type CodeTabsProps, type CodeItem }; diff --git a/content/AI/Fuclaude/Fuclaude.mdx b/content/AI/Fuclaude/Fuclaude.mdx index cf40233..7258bfe 100644 --- a/content/AI/Fuclaude/Fuclaude.mdx +++ b/content/AI/Fuclaude/Fuclaude.mdx @@ -43,92 +43,116 @@ import { CodeTabs } from '@/components/animate-ui/components/code-tabs'

- + +## 部署使用 + +### 手动部署 + +前往 【Fuclaude】- Github 查看最新版本的 Fuclaude。 + +在仓库的 Release 页面下载最新版本的 Fuclaude,解压后即可使用。 + +### Docker-compose 部署 + +

+ + + +export const CodeTabsBlocks = { + OAuth: () => ( + response.json()) -.then(data => { + .then((response) => response.json()) + .then((data) => { const loginUrl = data.login_url; // 你可以在这里处理 loginUrl console.log(loginUrl); -}) -.catch(error => { + }) + .catch((error) => { console.error('Error:', error); -});` - }} -/> - -## 部署使用 - -### 手动部署 - -前往 【Fuclaude】- Github 查看最新版本的 Fuclaude。 - -在仓库的 Release 页面下载最新版本的 Fuclaude,解压后即可使用。 - -### Docker-compose 部署 - -

- - + ), + Compose: () => ( + \ No newline at end of file + image: pengzhile/fuclaude + ports: + - '127.0.0.1:8181:8181' + environment: + - TZ=Asia/Shanghai # 时区(不需要改动) + - FUCLAUDE_BIND=0.0.0.0:8181 # 绑定的端口号(不需要改动)(改动需要把映射也一起改动) + - FUCLAUDE_TIMEOUT=600 # 超时时间(不需要改动) + - FUCLAUDE_PROXY_URL= # 代理URL socks5://username:password@ip:port(http也一样格式) + - FUCLAUDE_REAL_LOGOUT=false # 是否执行真实的登出操作(true/false)(不需要改动) + - FUCLAUDE_SITE_PASSWORD= # 访问站点的密码(如果需要) + - FUCLAUDE_COOKIE_SECRET=1234567890abcdefghijklmnopqrstuv # Cookie加密的密钥(不需要改动) + - FUCLAUDE_OPENAI_BASE_URL=https://api.openai.com/v1 # 内容审核,使用OAI的基础URL + - FUCLAUDE_OPENAI_API_KEY=sk-xxx # 内容审核,使用OAI的密钥 + - FUCLAUDE_MODERATION_ENABLED=false # 启用或禁用内容审核(true/false) + - FUCLAUDE_SIGNUP_ENABLED=false # 启用或禁用用户注册(true/false) + - FUCLAUDE_SHOW_SESSION_KEY=false # 显示或隐藏会话密钥(true/false) + restart: unless-stopped` + } + ]} + /> + ) +}; diff --git a/content/AI/OAIFree/AccessToken.mdx b/content/AI/OAIFree/AccessToken.mdx index c5dda45..22e0a52 100644 --- a/content/AI/OAIFree/AccessToken.mdx +++ b/content/AI/OAIFree/AccessToken.mdx @@ -41,35 +41,7 @@ import { CodeTabs } from '@/components/animate-ui/components/code-tabs'

- response.json()) -.then(data => { - const accessToken = data.access_token; - console.log(accessToken); -}) -.catch(error => console.error('Error:', error));` - }} -/> +

@@ -79,3 +51,50 @@ fetch('https://token.oaifree.com/api/auth/refresh', { href='/AI/OAIFree/ShareToken#通过-access-token-获取' arrow /> + +export function CodeTabsBlock() { + return ( + response.json()) + .then((data) => { + const accessToken = data.access_token; + console.log(accessToken); + }) + .catch((error) => console.error('Error:', error)); +` + } + ]} + /> + ); +} diff --git a/content/AI/OAIFree/Chat2APIOAIFree.mdx b/content/AI/OAIFree/Chat2APIOAIFree.mdx index 4ef36c2..f931b3f 100644 --- a/content/AI/OAIFree/Chat2APIOAIFree.mdx +++ b/content/AI/OAIFree/Chat2APIOAIFree.mdx @@ -31,37 +31,52 @@ API 调用方式与 OpenAI 官方完全一致,只需将 base_url 修改为 OAI

-' \\ # 替换为你的 ACCESS TOKEN - -d '{ - "model": "gpt-4o-mini", - "messages": [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "What is a LLM?"} - ] - }'`, - Python: `from openai import OpenAI + + +export function CodeTabsBlock() { + return ( + ' \\ # 替换为你的 ACCESS TOKEN + -d '{ + "model": "gpt-4o-mini", + "messages": [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "What is a LLM?"} + ] + }'` + }, + { + name: 'Python', + lang: 'python', + code: `from openai import OpenAI client = OpenAI( - api_key='', # 替换为你的 ACCESS TOKEN - base_url='https://api.oaifree.com/v1' + api_key="", # 替换为你的 ACCESS TOKEN + base_url="https://api.oaifree.com/v1", ) response = client.chat.completions.create( - model='gpt-4o-mini', - messages=[ - {'role': 'system', 'content': 'You are a helpful assistant.'}, - {'role': 'user', 'content': 'What is a LLM?'} - ] -)`, - Javascript: `const response = await fetch('https://api.oaifree.com/v1', { + model="gpt-4o-mini", + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "What is a LLM?"}, + ], +)` + }, + { + name: 'JavaScript', + lang: 'javascript', + code: `const response = await fetch('https://api.oaifree.com/v1', { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' // 替换为你的 ACCESS TOKEN + 'Authorization': 'Bearer ' // 替换为你的 ACCESS TOKEN }, body: JSON.stringify({ model: 'gpt-4o-mini', @@ -71,5 +86,8 @@ response = client.chat.completions.create( ] }) });` - }} -/> + } + ]} + /> + ); +} diff --git a/content/AI/OAIFree/NewOAIFree.mdx b/content/AI/OAIFree/NewOAIFree.mdx index 4787bb6..2f9b63b 100644 --- a/content/AI/OAIFree/NewOAIFree.mdx +++ b/content/AI/OAIFree/NewOAIFree.mdx @@ -47,76 +47,98 @@ import { CodeTabs } from '@/components/animate-ui/components/code-tabs'

- + +## 反代镜像服务 + +

+ + + +export const CodeTabsBlocks = { + OAuth: () => ( + response.json()) -.then(data => { + .then((response) => response.json()) + .then((data) => { const loginUrl = data.login_url; // 这里可以进一步处理 loginUrl -}) -.catch(error => { + }) + .catch((error) => { // 处理错误 -});` - }} -/> - -## 反代镜像服务 - -

- - + ), + Proxy: () => ( + +};` + }, + { + name: 'Nginx', + lang: 'nginx', + code: `location / { + proxy_pass https://new.oaifree.com; + proxy_ssl_server_name on; +}` + } + ]} + /> + ) +}; diff --git a/content/AI/OAIFree/ShareOAIFree.mdx b/content/AI/OAIFree/ShareOAIFree.mdx index f5d9445..4c5a1e8 100644 --- a/content/AI/OAIFree/ShareOAIFree.mdx +++ b/content/AI/OAIFree/ShareOAIFree.mdx @@ -29,33 +29,41 @@ import { CodeTabs } from '@/components/animate-ui/components/code-tabs'

- + +export function CodeTabsBlock() { + return ( + + } + ]} + /> + ); +} diff --git a/content/AI/OAIFree/ShareToken.mdx b/content/AI/OAIFree/ShareToken.mdx index 2813e48..f69e9d9 100644 --- a/content/AI/OAIFree/ShareToken.mdx +++ b/content/AI/OAIFree/ShareToken.mdx @@ -39,88 +39,116 @@ Share Token 起源于始皇的旧版镜像 Pandora,它的作用是映射一个

- + +- 返回字段 + +

+ + + +export const CodeTabsBlocks = { + Token: () => ( + response.json()) -.then(data => { + .then((response) => response.json()) + .then((data) => { const token_key = data.token_key; console.log(token_key); -}) -.catch(error => console.error('Error:', error));` - }} -/> - -- 返回字段 - -

- - console.error('Error:', error)); ` -}} -/> + } + ]} + /> + ), + Response: () => ( + + ) +}; diff --git a/content/Community/LinuxDoConnect.mdx b/content/Community/LinuxDoConnect.mdx index a393cda..a5bc877 100644 --- a/content/Community/LinuxDoConnect.mdx +++ b/content/Community/LinuxDoConnect.mdx @@ -3,7 +3,7 @@ import Image from 'next/image' import Link from 'next/link' import { CodeTabs } from '@/components/animate-ui/components/code-tabs' - + # Linux DO Connect OAuth(Open Authorization)是一个开放的网络授权标准,目前最新版本为 OAuth 2.0。我们日常使用的第三方登录(如 Google 账号登录)就采用了该标准。OAuth 允许用户授权第三方应用访问存储在其他服务提供商(如 Google)上的信息,无需在不同平台上重复填写注册信息。用户授权后,平台可以直接访问用户的账户信息进行身份验证,而用户无需向第三方应用提供密码。 @@ -65,23 +65,48 @@ OAuth(Open Authorization)是一个开放的网络授权标准,目前最新

- + +## 使用说明 + +### 授权流程 + +1. 用户点击应用中的'使用 Linux Do 登录'按钮 +2. 系统将用户重定向至 Linux Do 的授权页面 +3. 用户完成授权后,系统自动重定向回应用并携带授权码 +4. 应用使用授权码获取访问令牌 +5. 使用访问令牌获取用户信息 + +### 安全建议 + +- 切勿在前端代码中暴露 Client Secret +- 对所有用户输入数据进行严格验证 +- 确保使用 HTTPS 协议传输数据 +- 定期更新并妥善保管 Client Secret + +export function CodeTabsBlock() { + return ( + { + // 本例中使用终端输入来模拟流程,仅供本地测试 + // 请在实际应用中替换为真实的处理逻辑 + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); + rl.question('从回调 URL 中提取出 code,粘贴到此处并按回车:', (answer) => { + rl.close(); + resolve(answer.trim()); + }); + }); +} + +// 第三步:使用 code 参数获取访问令牌 async function getAccessToken(code) { try { - const response = await axios.post(TOKEN_URL, { + const form = new URLSearchParams({ client_id: CLIENT_ID, client_secret: CLIENT_SECRET, code: code, redirect_uri: REDIRECT_URI, grant_type: 'authorization_code' + }).toString(); + + const response = await axios.post(TOKEN_URL, form, { + // 提醒:需正确配置请求头,否则无法正常获取访问令牌 + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json' + } }); - + return response.data; } catch (error) { - console.error('获取访问令牌失败:', error.response ? error.response.data : error.message); + console.error(\`获取访问令牌失败:\${error.response ? JSON.stringify(error.response.data) : error.message}\`); throw error; } } -// 第三步:使用访问令牌获取用户信息 +// 第四步:使用访问令牌获取用户信息 async function getUserInfo(accessToken) { try { const response = await axios.get(USER_INFO_URL, { headers: { - Authorization: 'Bearer ' + accessToken + Authorization: \`Bearer \${accessToken}\` } }); - + return response.data; } catch (error) { - console.error('获取用户信息失败:', error.response ? error.response.data : error.message); + console.error(\`获取用户信息失败:\${error.response ? JSON.stringify(error.response.data) : error.message}\`); throw error; } } -// 使用示例 +// 主流程 async function main() { - // 1. 首先生成授权URL并让用户访问 + // 1. 生成授权 URL,前端引导用户访问授权页 const authUrl = getAuthUrl(); - console.log('请访问此URL授权: ' + authUrl); - - // 2. 用户授权后,从回调URL获取code参数 - const code = '用户授权后回调URL中的code参数'; - + console.log(\`请访问此 URL 授权:\${authUrl}\n\`); + + // 2. 用户授权后,从回调 URL 获取 code 参数 + const code = await getCode(); + try { - // 3. 使用code获取访问令牌 + // 3. 使用 code 参数获取访问令牌 const tokenData = await getAccessToken(code); const accessToken = tokenData.access_token; - + // 4. 使用访问令牌获取用户信息 if (accessToken) { const userInfo = await getUserInfo(accessToken); - console.log(JSON.stringify(userInfo, null, 2)); + console.log(\`\n获取用户信息成功:\${JSON.stringify(userInfo, null, 2)}\`); } else { - console.log('获取访问令牌失败:', tokenData); + console.log(\`\n获取访问令牌失败:\${JSON.stringify(tokenData)}\`); } } catch (error) { - console.error('发生错误:', error); + console.error('发生错误:', error); } } -main();`, - Python: `# 安装所需库 -pip install requests +main();` + }, + { + name: 'Python', + lang: 'python', + code: `# 安装第三方请求库,本例中使用 requests +# pip install requests -# 使用 OAuth2 获取 Linux Do 用户信息 +# 通过 OAuth2 获取 Linux Do 用户信息的参考流程 import requests import json -# 配置信息 -CLIENT_ID = '你的Client ID' -CLIENT_SECRET = '你的Client Secret' +# 配置信息(建议通过环境变量配置,避免使用硬编码) +CLIENT_ID = '你的 Client ID' +CLIENT_SECRET = '你的 Client Secret' REDIRECT_URI = '你的回调地址' AUTH_URL = 'https://connect.linux.do/oauth2/authorize' TOKEN_URL = 'https://connect.linux.do/oauth2/token' -USER_INFO_URL = 'https://connect.linux.do/oauth2/userinfo' +USER_INFO_URL = 'https://connect.linux.do/api/user' -# 第一步:生成授权链接 +# 第一步:生成授权 URL def get_auth_url(): params = { 'client_id': CLIENT_ID, @@ -177,59 +227,90 @@ def get_auth_url(): 'response_type': 'code', 'scope': 'user' } - auth_url = f'{AUTH_URL}?{'&'.join(f'{k}={v}' for k, v in params.items())}' + auth_url = f"{AUTH_URL}?{'&'.join(f'{k}={v}' for k, v in params.items())}" return auth_url -# 第二步:使用授权码获取访问令牌 -def get_access_token(code): - data = { - 'client_id': CLIENT_ID, - 'client_secret': CLIENT_SECRET, - 'code': code, - 'redirect_uri': REDIRECT_URI, - 'grant_type': 'authorization_code' - } - response = requests.post(TOKEN_URL, data=data) - return response.json() +# 第二步:获取 code 参数 +def get_code(): + # 本例中使用终端输入来模拟流程,仅供本地测试 + # 请在实际应用中替换为真实的处理逻辑 + return input('从回调 URL 中提取出 code,粘贴到此处并按回车:').strip() -# 第三步:使用访问令牌获取用户信息 +# 第三步:使用 code 参数获取访问令牌 +def get_access_token(code): + try: + data = { + 'client_id': CLIENT_ID, + 'client_secret': CLIENT_SECRET, + 'code': code, + 'redirect_uri': REDIRECT_URI, + 'grant_type': 'authorization_code' + } + # 提醒:需正确配置请求头,否则无法正常获取访问令牌 + headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json' + } + response = requests.post(TOKEN_URL, data=data, headers=headers) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + print(f"获取访问令牌失败:{e}") + return None + +# 第四步:使用访问令牌获取用户信息 def get_user_info(access_token): - headers = { - 'Authorization': f'Bearer {access_token}' - } - response = requests.get(USER_INFO_URL, headers=headers) - return response.json() - -# 使用示例 -# 1. 首先生成授权URL并让用户访问 -auth_url = get_auth_url() -print(f'请访问此URL授权: {auth_url}') - -# 2. 用户授权后,从回调URL获取code参数 -code = '用户授权后回调URL中的code参数' - -# 3. 使用code获取访问令牌 -token_data = get_access_token(code) -access_token = token_data.get('access_token') - -# 4. 使用访问令牌获取用户信息 -if access_token: - user_info = get_user_info(access_token) - print(json.dumps(user_info, indent=2)) -else: - print('获取访问令牌失败:', token_data)`, - - PHP: `// 使用 OAuth2 获取 Linux Do 用户信息 + try: + headers = { + 'Authorization': f'Bearer {access_token}' + } + response = requests.get(USER_INFO_URL, headers=headers) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + print(f"获取用户信息失败:{e}") + return None + +# 主流程 +if __name__ == '__main__': + # 1. 生成授权 URL,前端引导用户访问授权页 + auth_url = get_auth_url() + print(f'请访问此 URL 授权:{auth_url}\n') + + # 2. 用户授权后,从回调 URL 获取 code 参数 + code = get_code() + + # 3. 使用 code 参数获取访问令牌 + token_data = get_access_token(code) + if token_data: + access_token = token_data.get('access_token') + + # 4. 使用访问令牌获取用户信息 + if access_token: + user_info = get_user_info(access_token) + if user_info: + print(f"\n获取用户信息成功:{json.dumps(user_info, indent=2)}") + else: + print("\n获取用户信息失败") + else: + print(f"\n获取访问令牌失败:{json.dumps(token_data, indent=2)}") + else: + print("\n获取访问令牌失败")` + }, + { + name: 'PHP', + lang: 'php', + code: `// 通过 OAuth2 获取 Linux Do 用户信息的参考流程 // 配置信息 -$CLIENT_ID = '你的Client ID'; -$CLIENT_SECRET = '你的Client Secret'; +$CLIENT_ID = '你的 Client ID'; +$CLIENT_SECRET = '你的 Client Secret'; $REDIRECT_URI = '你的回调地址'; $AUTH_URL = 'https://connect.linux.do/oauth2/authorize'; $TOKEN_URL = 'https://connect.linux.do/oauth2/token'; -$USER_INFO_URL = 'https://connect.linux.do/oauth2/userinfo'; +$USER_INFO_URL = 'https://connect.linux.do/api/user'; -// 生成授权链接 +// 生成授权 URL function getAuthUrl($clientId, $redirectUri) { global $AUTH_URL; return $AUTH_URL . '?' . http_build_query([ @@ -240,10 +321,10 @@ function getAuthUrl($clientId, $redirectUri) { ]); } -// 使用授权码获取用户信息 (合并获取令牌和用户信息步骤) +// 使用 code 参数获取用户信息(合并获取令牌和获取用户信息的步骤) function getUserInfoWithCode($code, $clientId, $clientSecret, $redirectUri) { global $TOKEN_URL, $USER_INFO_URL; - + // 1. 获取访问令牌 $ch = curl_init($TOKEN_URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @@ -255,42 +336,46 @@ function getUserInfoWithCode($code, $clientId, $clientSecret, $redirectUri) { 'redirect_uri' => $redirectUri, 'grant_type' => 'authorization_code' ])); - + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/x-www-form-urlencoded', + 'Accept: application/json' + ]); + $tokenResponse = curl_exec($ch); curl_close($ch); - + $tokenData = json_decode($tokenResponse, true); if (!isset($tokenData['access_token'])) { return ['error' => '获取访问令牌失败', 'details' => $tokenData]; } - + // 2. 获取用户信息 $ch = curl_init($USER_INFO_URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $tokenData['access_token'] ]); - + $userResponse = curl_exec($ch); curl_close($ch); - + return json_decode($userResponse, true); } -// 使用示例 -// 1. 生成授权链接 +// 主流程 +// 1. 生成授权 URL $authUrl = getAuthUrl($CLIENT_ID, $REDIRECT_URI); echo "使用 Linux Do 登录"; // 2. 处理回调并获取用户信息 if (isset($_GET['code'])) { $userInfo = getUserInfoWithCode( - $_GET['code'], - $CLIENT_ID, - $CLIENT_SECRET, + $_GET['code'], + $CLIENT_ID, + $CLIENT_SECRET, $REDIRECT_URI ); - + if (isset($userInfo['error'])) { echo '错误: ' . $userInfo['error']; } else { @@ -298,22 +383,8 @@ if (isset($_GET['code'])) { // 处理用户登录逻辑... } }` - }} -/> - -## 使用说明 - -### 授权流程 - -1. 用户点击应用中的'使用 Linux Do 登录'按钮 -2. 系统将用户重定向至 Linux Do 的授权页面 -3. 用户完成授权后,系统自动重定向回应用并携带授权码 -4. 应用使用授权码获取访问令牌 -5. 使用访问令牌获取用户信息 - -### 安全建议 - -- 切勿在前端代码中暴露 Client Secret -- 对所有用户输入数据进行严格验证 -- 确保使用 HTTPS 协议传输数据 -- 定期更新并妥善保管 Client Secret + } + ]} + /> + ); +} diff --git a/content/Community/LinuxDoLottery.mdx b/content/Community/LinuxDoLottery.mdx index e9503ea..d56fbf5 100644 --- a/content/Community/LinuxDoLottery.mdx +++ b/content/Community/LinuxDoLottery.mdx @@ -93,9 +93,20 @@ import { CodeTabs } from '@/components/animate-ui/components/code-tabs'

- + +请注意,关于抽奖活动的所有规则及其执行,最终解释权归管理团队所有。我们保留随时修改或补充抽奖规则的权利,以应对任何突发情况或保证活动的公正性。任何规则的变动将及时公布。 + +如有任何疑问或在使用新功能时遇到困难,请随时联系管理团队。我们感谢您的配合与支持,期待通过这些更新为大家带来更加公平、有序的抽奖体验。 + +export function CodeTabsBlock() { + return ( + - -请注意,关于抽奖活动的所有规则及其执行,最终解释权归管理团队所有。我们保留随时修改或补充抽奖规则的权利,以应对任何突发情况或保证活动的公正性。任何规则的变动将及时公布。 - -如有任何疑问或在使用新功能时遇到困难,请随时联系管理团队。我们感谢您的配合与支持,期待通过这些更新为大家带来更加公平、有序的抽奖体验。 \ No newline at end of file + } + ]} + /> + ); +} diff --git a/lib/utils.ts b/lib/utils.ts index 237b693..6a923cf 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,6 +1,11 @@ -import {clsx, type ClassValue} from 'clsx'; -import {twMerge} from 'tailwind-merge'; +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); -} \ No newline at end of file +} + +// Workaround for Shiki's tabindex issue #97 +export function replaceTabIndex(html: string): string { + return html.replace(/tabindex="0"/g, 'tabindex="-1"'); +}