<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TENG YUAN - 个人主页</title>
<meta name="description" content="藤原的个人主页,分享技术、生活和创意">
<meta name="keywords" content="藤原,个人主页,前端开发,技术博客">
<!-- 网站图标 -->
<link rel="icon" href="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01FU7InI1kKcib7hRbf_!!2214968904665.jpg_.webp" type="image/webp">
<link rel="shortcut icon" href="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01FU7InI1kKcib7hRbf_!!2214968904665.jpg_.webp" type="image/webp">
<link rel="apple-touch-icon" href="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01FU7InI1kKcib7hRbf_!!2214968904665.jpg_.webp">
<!-- 预连接优化 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<!-- 字体加载 -->
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300..700&display=swap" rel="stylesheet">
<!-- 图标库 -->
<link href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.min.css" rel="stylesheet">
<!-- JavaScript 库 -->
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
<!-- 预加载关键资源 -->
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css" as="style">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.min.css" as="style">
<!-- 主题颜色 -->
<meta name="theme-color" content="#799fb4">
<!-- 苹果全屏模式 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- 微软磁贴颜色 -->
<meta name="msapplication-TileColor" content="#799fb4">
<!-- 其他图标配置 -->
<link rel="manifest" href="site.webmanifest">
<style>
/****************************************
* 重置样式
*****************************************/
* {
margin: 0;
padding: 0;
border: 0;
outline: none;
font-size: 100%;
vertical-align: baseline;
box-sizing: border-box;
transition: all ease 0.25s;
-moz-transition: all ease 0.25s;
}
*:focus, button, textarea, .forminput {
outline: none !important;
border: unset;
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
display: block;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after {
content: "";
}
/* 隐藏损坏的链接和图片 */
img[src="<i>No Information</i>"],
img[src=""],
a[href="<i>No Information</i>"],
a[href=""]:not([name]):not([onclick]) {
display: none !important;
}
/* 调整表情符号大小 */
a[href*="javascript:emoticon"] img,
div.postcolor img[alt*="https"],
td[class*="post"] img[alt*="https"],
a[href*="javascript:add_smilie"] img,
#ucpcontent img[alt*="https"],
div.box img[alt*="https"] {
height: 30px;
}
/****************************************
* 默认样式
*****************************************/
body, html {
margin: 0px;
padding: 0px;
scroll-behavior: smooth;
font: 500 16px/150% var(--fontBody);
color: var(--dark);
}
body {
background: linear-gradient(
360deg,
RGBA(var(--accentRGB), 0.35) 0%,
RGBA(var(--lighterRGB), 1) 70%
),
linear-gradient(
135deg,
RGBA(var(--supportRGB), 0.35) 10%,
RGBA(var(--supportRGB), 0) 80%
),
linear-gradient(
225deg,
RGBA(var(--featureRGB), 0.35) 10%,
RGBA(var(--featureRGB), 0) 80%
),
linear-gradient(
315deg,
RGBA(var(--supportRGB), 0.35) 100%,
RGBA(var(--supportRGB), 0) 70%
);
background-attachment: fixed;
background-size: cover;
}
a {
text-decoration: none;
cursor: crosshair;
}
/****************************************
* CSS变量定义
*****************************************/
:root {
.bannerImage {
border-radius: 0 20px 20px 0;
}
.bannerImage video {
border-radius: inherit;
}
--headerHeight: 605px;
--settingImage: url(https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01x1Sp471kKciYVOjv5_!!2214968904665.jpg_.webp);
--fontBody: Quicksand;
--fontTitle: MontgroveItalic;
/* 默认主题色 */
--accent: #799fb4;
--accentRGB: 121, 159, 180;
--support: #99ccff;
--supportRGB: 186, 132, 130;
--feature: #a6b0b4;
--featureRGB: 166, 176, 180;
--dark: #1c1a1a;
--darkRGB: 28, 26, 26;
--darker: #101010;
--darkerRGB: 16, 16, 16;
--lighter: #e2e2e2;
--lighterRGB: 226, 226, 226;
--light: #d2d2d2;
--lightRGB: 210, 210, 210;
/* 这些颜色不会随主题切换变化 */
--lightest: #ffffff;
--lightestRGB: 225, 225, 225;
--darkest: #101010;
--darkestRGB: 16, 16, 16;
/* 终端相关变量 */
--editor-bg: RGBA(var(--accentRGB), 0.1);
--editor-secondary-bg: RGBA(var(--supportRGB), 0.1);
--line-color: var(--accent);
--text-color: var(--dark);
--keyword-color: var(--support);
--string-color: var(--feature);
--comment-color: RGBA(var(--accentRGB), 0.7);
--number-color: var(--accent);
--function-color: var(--support);
--font-family: 'JetBrains Mono', 'Consolas', 'Monaco', monospace;
--header-bg: RGBA(var(--accentRGB), 0.2);
--window-btn-close: #ff5f56;
--window-btn-min: #ffbd2e;
--window-btn-max: #27c93f;
--ai-output-color: var(--dark);
--user-input-color: var(--support);
--video-bg: #000000;
--terminal-accent-color: var(--support);
--terminal-accent-hover: var(--feature);
--box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
--border-radius: 15px;
--success-color: #4caf50;
--warning-color: #ff9800;
--error-color: #f44336;
--tool-header-height: 40px;
--tool-padding: 16px;
--terminal-border: 1px solid RGBA(var(--accentRGB), 0.3);
}
/* 深色主题变量 */
[data-theme="dark"] {
--dark: #e2e2e2;
--darkRGB: 226, 226, 226;
--darker: #d2d2d2;
--darkerRGB: 210, 210, 210;
--lighter: #2a2828;
--lighterRGB: 42, 40, 40;
--light: #101010;
--lightRGB: 16, 16, 16;
/* 终端深色主题调整 */
--editor-bg: RGBA(var(--accentRGB), 0.05);
--editor-secondary-bg: RGBA(var(--supportRGB), 0.05);
--line-color: var(--accent);
--text-color: var(--light);
--keyword-color: var(--support);
--string-color: var(--feature);
--comment-color: RGBA(var(--accentRGB), 0.5);
--header-bg: RGBA(var(--accentRGB), 0.1);
--terminal-accent-color: var(--support);
--terminal-accent-hover: var(--feature);
}
/* 主题切换按钮样式 */
.theme-switch {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
background-color: var(--lighter);
padding: 5px 10px;
font-weight: 800;
color: var(--dark);
border-radius: 20px;
box-shadow: 0px 0px 50px -10px RGBA(000, 000, 000, 0.25);
cursor: pointer;
}
.theme-switch input[type="checkbox"] {
display: none;
}
/* 默认显示浅色图标,隐藏深色图标 */
.light-icon {
display: flex;
font-size: 20px;
color: var(--dark);
}
.dark-icon {
display: none;
font-size: 20px;
color: var(--dark);
}
/* 深色主题下显示深色图标,隐藏浅色图标 */
[data-theme="dark"] .light-icon {
display: none;
}
[data-theme="dark"] .dark-icon {
display: flex;
}
.theme-switch:hover i {
color: var(--accent);
}
/****************************************
* 字体定义
*****************************************/
@font-face {
font-family: "MontgroveItalic";
src: url("https://files.jcink.net/uploads2/killingfloor/fonts/Montgrove_Italic.woff")
format("woff");
font-display: swap;
}
/****************************************
* 主容器样式
*****************************************/
#headerWave {
position: fixed;
z-index: -1;
}
#boardWrapper {
position: relative;
display: flex;
flex-direction: column;
gap: 15px;
width: clamp(450px, 100%, 1200px);
background: var(--light);
padding: 45px 30px 30px;
min-height: 100vh;
margin: auto;
box-shadow: 0px 0px 50px -10px RGBA(000, 000, 000, 0.25);
overflow: clip;
}
/****************************************
* 顶部导航栏样式
*****************************************/
#topbar {
position: sticky;
top: 40px;
z-index: 9990;
width: calc(100% - 60px);
margin: 10px 30px -10px;
}
//#boardWrapper {// position: relative;// display: flex;// width: 100%;//}
.topbarlinks {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 30px;
}
.topbarlinks .quickLinks {
display: flex;
gap: 15px;
}
.topbarlinks .quickLinks a,
.topbarlinks .quickLinks label {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
background-color: var(--lighter);
padding: 5px 5px 5px 6px;
font-weight: 800;
color: var(--dark);
width: 35px;
height: 35px;
border-radius: 50%;
box-shadow: 0px 0px 50px -10px RGBA(000, 000, 000, 0.25);
overflow: hidden;
}
.topbarlinks .quickLinks a i,
.topbarlinks .quickLinks label i {
font-size: 20px;
padding-left: 2px;
}
.topbarlinks .quickLinks a:hover,
.topbarlinks .quickLinks label:hover {
width: unset !important;
border-radius: 20px;
padding-right: 10px;
justify-content: center;
}
.topbarlinks .quickLinks a:hover i,
.topbarlinks .quickLinks label:hover i {
color: var(--accent);
}
.topbarlinks button {
background: unset !important;
color: var(--dark);
font-size: 30px;
}
.topbarlinks button:active {
transform: scale(1.1);
}
/****************************************
* 用户导航菜单样式
*****************************************/
#linkmenu-container {
position: fixed;
z-index: 9989;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
display: none;
}
#linkmenu {
position: fixed;
z-index: 9989;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: RGBA(var(--lightRGB), 0.9);
backdrop-filter: blur(10px);
visibility: hidden;
pointer-events: none;
display: flex;
justify-content: center;
align-items: center;
}
#linkmenu.show {
visibility: visible;
pointer-events: auto;
}
/* 终端样式 */
#terminal-container {
position: relative;
width: 90%;
max-width: 900px;
height: 80%;
max-height: 700px;
z-index: 9999;
background: var(--editor-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
border: var(--terminal-border);
display: flex;
flex-direction: column;
overflow: hidden;
backdrop-filter: blur(5px);
}
/* 终端编辑器样式 */
.editor {
width: 100%;
height: 100%;
background: var(--editor-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
overflow: hidden;
border: var(--terminal-border);
display: flex;
flex-direction: column;
backdrop-filter: blur(5px);
}
.editor-header {
background: var(--header-bg);
padding: 12px;
border-radius: var(--border-radius) var(--border-radius) 0 0;
display: flex;
align-items: center;
gap: 8px;
border-bottom: var(--terminal-border);
}
.window-btn {
width: 12px;
height: 12px;
border-radius: 50%;
position: relative;
cursor: pointer;
}
.close { background: var(--window-btn-close); }
.minimize { background: var(--window-btn-min); }
.maximize { background: var(--window-btn-max); }
.title-bar {
color: var(--line-color);
margin-left: 20px;
font-size: 0.9em;
font-family: var(--fontBody);
font-weight: 600;
}
.editor-content {
padding: 20px;
counter-reset: line;
font-size: 14px;
overflow-x: auto;
overflow-y: auto;
scrollbar-width: none;
-ms-overflow-style: none;
flex: 1;
font-family: var(--font-family);
background: transparent;
}
.editor-content::-webkit-scrollbar {
display: none;
}
.line {
display: flex;
padding: 2px 0;
position: relative;
min-height: 1.6em;
}
.line::before {
counter-increment: line;
content: counter(line);
color: var(--line-color);
width: 2em;
text-align: right;
padding-right: 1em;
position: absolute;
opacity: 0.7;
font-family: var(--font-family);
}
.line-content {
padding-left: 3em;
width: 100%;
font-family: var(--font-family);
}
.indent { margin-left: 2em; }
.indent-2 { margin-left: 4em; }
.keyword { color: var(--keyword-color); font-weight: 600; }
.string { color: var(--string-color); }
.comment { color: var(--comment-color); font-style: italic; }
.number { color: var(--number-color); }
.function { color: var(--function-color); font-weight: 600; }
.ai-output { color: var(--ai-output-color); }
.user-input { color: var(--user-input-color); font-weight: 600; }
.input-line {
display: flex;
align-items: center;
background: var(--editor-secondary-bg);
padding: 8px 10px;
border-radius: 4px;
margin: 0 20px 20px;
position: sticky;
bottom: 0;
z-index: 10;
border-top: var(--terminal-border);
}
.input-line::before {
content: ">";
color: var(--terminal-accent-color);
width: 2em;
text-align: right;
padding-right: 1em;
font-weight: bold;
}
.input-line input {
flex: 1;
background: transparent;
border: none;
color: var(--text-color);
font-family: var(--font-family);
font-size: 14px;
outline: none;
padding: 2px 0;
}
/* 通用工具容器样式 */
.tool-container {
background: var(--editor-secondary-bg);
border-radius: var(--border-radius);
margin: 15px 0;
border: var(--terminal-border);
overflow: hidden;
backdrop-filter: blur(5px);
width: 100%;
max-width: 100%;
}
/* 通用工具头部样式 */
.tool-header {
background: var(--header-bg);
padding: 12px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: var(--terminal-border);
}
.tool-title {
color: var(--text-color);
font-size: 14px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.tool-close {
background: none;
border: none;
color: var(--line-color);
cursor: pointer;
padding: 4px;
border-radius: 4px;
}
.tool-close:hover {
color: var(--text-color);
background: RGBA(var(--accentRGB), 0.1);
}
/* 通用工具内容样式 */
.tool-content {
padding: 20px;
width: 100%;
box-sizing: border-box;
}
/* 通用输入区域样式 */
.tool-input {
width: 100%;
padding: 12px 50px 12px 16px;
border: var(--terminal-border);
border-radius: 8px;
background: var(--editor-secondary-bg);
color: var(--text-color);
font-size: 14px;
outline: none;
box-sizing: border-box;
}
.tool-input:focus {
border-color: var(--terminal-accent-color);
box-shadow: 0 0 0 3px RGBA(var(--supportRGB), 0.2);
}
/* 通用按钮样式 */
.tool-btn {
background: var(--terminal-accent-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
display: flex;
align-items: center;
gap: 6px;
font-weight: 500;
}
.tool-btn:hover {
background: var(--terminal-accent-hover);
transform: translateY(-1px);
}
/* 视频播放器样式*/
.video-container {
background: var(--video-bg);
border-radius: var(--border-radius);
margin: 15px 0;
overflow: hidden;
border: var(--terminal-border);
width: 100%;
}
.video-player {
position: relative;
width: 100%;
height: 300px;
background: #000;
}
.video-player video, .video-player iframe {
width: 100%;
height: 100%;
object-fit: contain;
border: none;
}
.video-controls {
background: var(--editor-secondary-bg);
padding: 10px;
display: flex;
gap: 10px;
align-items: center;
flex-wrap: wrap;
}
.video-button {
background: var(--terminal-accent-color);
color: white;
border: none;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
display: flex;
align-items: center;
gap: 6px;
}
.video-button:hover {
background: var(--terminal-accent-hover);
}
/* 搜索结果样式 */
.search-results {
background: var(--editor-bg);
border-radius: var(--border-radius);
margin: 15px 0;
border: var(--terminal-border);
overflow: hidden;
width: 100%;
}
.search-result-item {
padding: 12px;
margin-bottom: 10px;
background: RGBA(var(--accentRGB), 0.05);
border-radius: 8px;
border: var(--terminal-border);
cursor: pointer;
}
.search-result-item:hover {
background: RGBA(var(--accentRGB), 0.1);
transform: translateY(-1px);
}
/* 通用信息展示样式 */
.tool-info {
background: RGBA(var(--supportRGB), 0.1);
border: 1px solid RGBA(var(--supportRGB), 0.3);
border-radius: 6px;
padding: 12px;
margin: 10px 0;
color: var(--text-color);
font-size: 13px;
}
/* 图片预览区域样式 */
.tool-preview-container {
position: relative;
width: 100%;
min-height: 200px;
margin-bottom: 15px;
border-radius: 8px;
overflow: hidden;
background: RGBA(var(--accentRGB), 0.05);
border: var(--terminal-border);
display: flex;
justify-content: center;
align-items: center;
}
.tool-preview {
max-width: 100%;
max-height: 400px;
display: none;
}
.tool-preview.active {
display: block;
}
.tool-placeholder {
text-align: center;
padding: 20px;
color: var(--line-color);
}
.tool-placeholder svg {
width: 48px;
height: 48px;
margin-bottom: 10px;
color: var(--terminal-accent-color);
}
.tool-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
/* 隐藏所有滚动条 */
::-webkit-scrollbar {
display: none;
}
* {
scrollbar-width: none;
-ms-overflow-style: none;
}
/****************************************
* 页眉样式
*****************************************/
#boardHeader {
position: relative;
display: grid;
grid-template-columns: 60% 40%;
height: var(--headerHeight);
margin-top: -80px;
}
#boardHeader .bannerInformation {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding: 60px;
background-color: var(--lighter);
border-radius: 15px 0px 15px 15px;
margin-right: -15px;
margin-bottom: -20px;
overflow: hidden;
box-shadow: 0px 0px 50px -10px RGBA(000, 000, 000, 0.25);
}
#boardHeader .bannerInformation.profile-active {
padding: 30px; /* Reduced padding for profile card */
}
#boardHeader .bannerInformation #headerWave1 {
position: absolute;
top: 0px;
width: 100%;
left: 0px;
pointer-events: none;
}
#boardHeader .bannerInformation #headerWave2 {
position: absolute;
bottom: 0px;
width: 100%;
left: 0px;
pointer-events: none;
}
/* 横幅标题样式 */
#boardHeader .bannerTitle {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
gap: 15px;
}
#boardHeader .bannerTitle h1 {
font: 500 60px/120% var(--fontBody);
letter-spacing: -2px;
}
#boardHeader .bannerTitle h1 b {
position: relative;
font-weight: 800;
}
#boardHeader .bannerTitle h2 {
font-weight: 800;
font-size: 18px;
color: RGBA(var(--darkerRGB), 0.75);
}
#boardHeader .bannerTitle h1 b:after {
content: "";
position: absolute;
z-index: -1;
bottom: 0px;
left: 0px;
display: block;
height: 30%;
width: 100%;
background: var(--light);
border-radius: 5px;
}
/* 横幅图片样式 */
#boardHeader .bannerImage {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: center;
background-image: var(--headerImage);
width: 100%;
height: calc(100% - 45px);
max-height: var(--headerHeight);
background-size: cover;
border-radius: 0px 20px 20px 0px;
}
#boardHeader .bannerImage:before {
content: "";
position: absolute;
z-index: 0;
bottom: -40px;
left: 0px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(84deg);
}
/* 管理员图片样式 */
#boardHeader .bannerStaff {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px 0px 10px 10px;
height: auto;
background-color: var(--light);
border-radius: 15px 0px 0px 15px;
}
#boardHeader .bannerStaff:before {
content: "";
position: absolute;
z-index: -1;
top: -40px;
right: 0px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--light);
transform: rotate(357deg);
}
#boardHeader .bannerStaff:after {
content: "";
position: absolute;
z-index: -1;
bottom: -40px;
right: 0px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--light);
transform: rotate(263deg);
}
#boardHeader .bannerStaff a.adminImage {
display: block;
width: 60px;
height: 60px;
background-color: var(--support);
border-radius: 10px;
}
#boardHeader .bannerStaff img {
display: block;
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 10px;
}
#boardHeader .bannerStaff a:hover img {
transform: scale(1.1);
}
/****************************************
* 中间内容区域样式
*****************************************/
#boardCrotch {
position: relative;
display: grid;
grid-template-columns: 1fr 3fr;
gap: 15px;
padding: 65px 30px 30px;
width: calc(100% + 60px);
background: var(--lighter);
margin: -30px;
}
#boardCrotch:before {
content: "";
position: absolute;
z-index: 0;
top: -40px;
left: 0px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(84deg);
}
#boardCrotch:after {
content: "";
position: absolute;
z-index: 0;
top: -40px;
right: 0px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(350deg);
}
#boardCrotchBottom {
position: relative;
display: block;
width: 100%;
}
#boardCrotchBottom:before {
content: "";
position: absolute;
z-index: 0;
top: 15px;
left: -30px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(165deg);
}
#boardCrotchBottom:after {
content: "";
position: absolute;
z-index: 0;
top: 15px;
right: -30px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(261deg);
}
section.siteArticle {
display: flex;
flex-direction: column;
gap: 15px;
}
section.siteIntroduction {
background: RGBA(var(--lightRGB), 0.75);
padding: 30px;
border-radius: 20px;
}
nav.siteLinks {
display: grid;
grid-template-columns: 1fr auto;
gap: 15px;
}
nav.siteLinks .navLinksContainer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
}
nav.siteLinks .navTitle {
display: flex;
flex-direction: column;
gap: 5px;
font: 700 40px/100% var(--fontBody);
letter-spacing: -1px;
}
span.navTitle > span:nth-child(1) {
font-size: 45px;
}
span.navTitle span {
position: relative;
z-index: 1;
}
span.navTitle span.navTitleClass:after {
content: "";
position: absolute;
z-index: -1;
bottom: 0px;
left: 0px;
display: block;
height: 50%;
width: 100%;
background: var(--light);
border-radius: 5px;
}
nav.siteLinks .navTitle i {
color: var(--accent);
font-size: 35px;
}
nav.siteLinks a {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
color: var(--dark);
font-weight: 700;
background-color: var(--accent);
padding: 5px 10px 5px 35px;
border-radius: 5px;
overflow: hidden;
}
nav.siteLinks a:nth-child(2n + 1) {
background-color: RGBA(var(--supportRGB), 1);
}
nav.siteLinks a i {
position: absolute;
left: -10px;
font-size: 35px;
font-weight: 100;
color: var(--lighter);
}
nav.siteLinks a:hover i {
transform: scale(1.4);
}
section.siteTime {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
gap: 15px;
padding: 30px;
width: 100%;
height: 100%;
color: var(--lightest);
background-color: var(--accent);
background-size: cover;
background-position: center;
background-blend-mode: hard-light;
border-radius: 20px;
}
section.siteTime h1 {
font: 800 30px/120% var(--fontBody);
letter-spacing: -1px;
text-shadow: 1px 2px 0px RGBA(var(--darkestRGB), 0.5);
}
section.siteTime h2 {
position: absolute;
bottom: 0px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 5px;
background: var(--lighter);
padding: 10px 15px 0px;
border-radius: 20px 20px 0px 0px;
color: var(--dark);
}
section.siteTime h2 i {
position: relative;
z-index: 1;
color: var(--accent);
font-size: 20px;
}
section.siteTime h2:before {
content: "";
position: absolute;
z-index: 0;
bottom: 0px;
right: -40px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(76deg);
}
section.siteTime h2:after {
content: "";
position: absolute;
z-index: 0;
bottom: 0px;
left: -40px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(4deg);
}
section.siteTime .siteTimeIcon {
position: absolute;
top: 0px;
left: 0px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: var(--lighter);
width: 50px;
height: 50px;
border-radius: 0px 0px 20px 0px;
}
section.siteTime .siteTimeIcon:before {
content: "";
position: absolute;
z-index: 0;
top: 0px;
right: -40px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(185deg);
}
section.siteTime .siteTimeIcon:after {
content: "";
position: absolute;
z-index: 0;
bottom: -39px;
left: 0px;
width: 40px;
height: 40px;
border-radius: 50%;
box-shadow: 20px 20px 0 var(--lighter);
transform: rotate(168deg);
}
section.siteTime .siteTimeIcon i {
font-size: 25px;
color: var(--accent);
}
section.siteTime:hover .siteTimeIcon i {
transform: scale(1.3);
}
/****************************************
* 垂直轮播导航样式
*****************************************/
.vertical-carousel-container {
position: relative;
height: 200px;
overflow: hidden;
border-radius: 20px;
background: var(--lighter);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
/* 垂直轮播页面样式 */
.vertical-carousel-page {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 115%;
padding: 20px;
opacity: 0;
pointer-events: none;
transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
transform: translateY(100%);
}
/* 当前活动页面 */
.vertical-carousel-page.active {
opacity: 1;
pointer-events: auto;
transform: translateY(0);
z-index: 2;
}
/* 上一个页面 - 向上移出 */
.vertical-carousel-page.prev {
transform: translateY(-100%);
z-index: 1;
}
/* 下一个页面 - 向下移出 */
.vertical-carousel-page.next {
transform: translateY(100%);
z-index: 1;
}
/* 导航链接样式 */
nav.siteLinks {
display: grid;
grid-template-columns: 1fr auto;
gap: 15px;
height: 100%;
}
nav.siteLinks .navLinksContainer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
height: calc(100% - 60px);
overflow-y: auto;
scrollbar-width: none;
-ms-overflow-style: none;
align-content: flex-start;
}
nav.siteLinks .navLinksContainer::-webkit-scrollbar {
display: none;
}
nav.siteLinks .navTitle {
display: flex;
flex-direction: column;
gap: 5px;
font: 700 40px/100% var(--fontBody);
letter-spacing: -1px;
}
span.navTitle > span:nth-child(1) {
font-size: 45px;
}
span.navTitle span {
position: relative;
z-index: 1;
}
span.navTitle span.navTitleClass:after {
content: "";
position: absolute;
z-index: -1;
bottom: 0px;
left: 0px;
display: block;
height: 50%;
width: 100%;
background: var(--light);
border-radius: 5px;
}
nav.siteLinks .navTitle i {
color: var(--accent);
font-size: 35px;
}
nav.siteLinks a {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
color: var(--dark);
font-weight: 700;
background-color: var(--accent);
padding: 5px 10px 5px 35px;
border-radius: 5px;
overflow: hidden;
white-space: nowrap;
transition: all 0.3s ease;
height: fit-content;
}
nav.siteLinks a:nth-child(2n + 1) {
background-color: RGBA(var(--supportRGB), 1);
}
nav.siteLinks a i {
position: absolute;
left: -10px;
font-size: 35px;
font-weight: 100;
color: var(--lighter);
transition: transform 0.3s ease;
}
nav.siteLinks a:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
nav.siteLinks a:hover i {
transform: scale(1.4);
}
/* 垂直轮播控制按钮 */
.vertical-carousel-controls {
position: absolute;
bottom: 10px;
/* 这是控制垂直位置的属性 */
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 5px;
z-index: 3;
background: rgba(var(--accentRGB), 0.2);
padding: 5px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
.vertical-carousel-btn {
width: 60px;
height: 25px;
border-radius: 12px;
border: none;
background: rgba(var(--accentRGB), 0.7);
color: white;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.vertical-carousel-btn:hover {
background: rgba(var(--supportRGB), 0.8);
transform: translateY(-2px);
}
.vertical-carousel-btn.active {
background: rgba(var(--supportRGB), 1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
/****************************************
* 内部内容容器样式
*****************************************/
#innerWrapper {
position: relative;
width: 100%;
padding: 30px 0px;
}
/****************************************
* 导航树样式
*****************************************/
.siteNav {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 20px;
color: RGBA(var(--darkestRGB), 0.75);
font: 600 14px/120% var(--fontBody);
background: linear-gradient(
45deg,
RGBA(var(--accentRGB), 0.5) 0%,
RGBA(var(--accentRGB), 0) 70%
),
linear-gradient(
135deg,
RGBA(var(--supportRGB), 0.5) 10%,
RGBA(var(--supportRGB), 0) 80%
),
linear-gradient(
225deg,
RGBA(var(--featureRGB), 0.5) 10%,
RGBA(var(--featureRGB), 0) 80%
),
linear-gradient(
315deg,
RGBA(var(--supportRGB), 0.5) 100%,
RGBA(var(--supportRGB), 0) 70%
);
padding: 10px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
.siteNav a,
.siteNav label {
color: var(--darkest);
}
.siteNav i {
font-size: 20px;
font-weight: 500;
color: var(--lightest);
}
/* 单篇文章展示区域 */
.single-article-container {
position: relative;
width: 100%;
height: 180px;
overflow: hidden;
border-radius: 8px;
background: white;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.article-slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.6s ease, transform 0.6s ease;
transform: translateX(100%);
display: flex;
flex-direction: column;
}
.article-slide.active {
opacity: 1;
transform: translateX(0);
z-index: 2;
}
.article-slide.prev {
transform: translateX(-100%);
z-index: 1;
}
.article-slide.next {
transform: translateX(100%);
z-index: 1;
}
.article-header {
position: relative;
height: 100px;
flex-shrink: 0;
}
.article-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.article-title {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0,0,0,0.7));
color: white;
font-size: 14px;
font-weight: 600;
padding: 10px;
line-height: 1.3;
text-shadow: 0 1px 3px rgba(0,0,0,0.5);
}
.article-content {
padding: 10px;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.article-excerpt {
font-size: 12px;
color: #666;
margin-bottom: 8px;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.article-meta {
display: flex;
justify-content: space-between;
font-size: 11px;
color: #999;
margin-top: auto;
}
.article-controls {
position: absolute;
bottom: 10px;
left: 0;
right: 0;
display: flex;
justify-content: center;
gap: 10px;
z-index: 3;
}
.article-control-btn {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(121, 159, 180, 0.3);
border: none;
cursor: pointer;
transition: all 0.3s ease;
}
.article-control-btn.active {
background: rgba(121, 159, 180, 1);
transform: scale(1.2);
}
.article-nav-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
border-radius: 50%;
background: rgba(255,255,255,0.8);
color: #799fb4;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 4;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
opacity: 0;
transition: opacity 0.3s ease;
}
.single-article-container:hover .article-nav-btn {
opacity: 1;
}
.article-prev-btn {
left: 10px;
}
.article-next-btn {
right: 10px;
}
/* 推荐文章页面特定样式 */
.recommend-page .navLinksContainer {
flex-direction: column;
flex-wrap: nowrap;
height: calc(100% - 50px);
padding: 0;
}
.recommend-page .navTitle {
font-size: 28px;
}
.recommend-page .navTitle > span:nth-child(1) {
font-size: 32px;
}
/****************************************
* 页脚样式
*****************************************/
#boardFooter {
position: relative;
width: 100%;
}
/****************************************
* 媒体查询 - 响应式设计
*****************************************/
@media screen and (max-width: 950px) {
}
@media screen and (max-width: 860px) {
#boardHeader {
display: flex !important;
flex-direction: column !important;
gap: 40px;
height: unset !important;
}
#boardHeader .bannerInformation {
border-radius: 15px !important;
}
#boardHeader .bannerInformation.profile-active {
padding: 30px; /* Ensure padding is adjusted on mobile too */
}
#boardHeader .bannerImage:before {
top: 92px;
left: -44px;
}
.bannerInformation {
margin: 0px !important;
padding: 200px 40px !important;
}
#boardHeader .bannerImage {
background-image: unset !important;
height: unset !important;
margin-bottom: 30px !important;
}
#boardHeader .bannerStaff {
display: flex;
flex-direction: row;
gap: 30px;
padding: unset !important;
background-color: unset !important;
border-radius: unset !important;
}
#boardHeader .bannerStaff:after,
#boardHeader .bannerStaff:before {
display: none !important;
}
#boardCrotch {
grid-template-columns: unset !important;
grid-template-rows: auto 1fr !important;
gap: 40px !important;
margin-top: 0px !important;
}
section.siteArticle {
z-index: 0;
flex-direction: column-reverse !important;
gap: 40px !important;
}
section.siteTime {
zindex: 1;
background-image: unset !important;
padding-bottom: 60px;
}
/* Mobile adjustments for terminal position */
#terminal-container {
width: 95%;
height: 85%;
max-height: none;
}
/* Mobile adjustments for terminal menu */
#linkmenu {
padding: 20px;
}
/* Mobile adjustments for video player */
.video-container {
margin-left: -15px;
margin-right: -15px;
border-radius: 0;
width: calc(100% + 30px);
}
/* Mobile adjustments for tool container */
.tool-container {
margin-left: -15px;
margin-right: -15px;
border-radius: 0;
width: calc(100% + 30px);
}
}
/* 每日一言 */
.siteIntroduction {
min-height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
}
.quote-content {
font-size: 18px;
line-height: 1.6;
margin-bottom: 10px;
}
.quote-from {
font-size: 14px;
color: var(--line-color);
text-align: right;
font-style: italic;
}
/****************************************
* 技术动态区域样式 - 修复版本
*****************************************/
.tech-trends {
margin-top: 30px;
padding: 0;
background: transparent;
border: none;
width: 100%;
}
/* 分类区域 */
.category {
margin-top: var(--layout-margin);
width: 100%;
}
/* 分类标题 */
.category-header {
background-color: var(--accent);
color: var(--lightest);
border: var(--panel-bordering);
width: max-content;
padding: var(--inside-margin) var(--layout-margin);
margin-bottom: -1.5rem;
font-size: 1rem;
font-family: var(--font-2);
font-style: italic;
font-weight: 700 !important;
position: relative;
z-index: 2;
border-radius: 8px 8px 0 0;
}
/* 基础分类布局 */
.category-basics {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: stretch;
flex-wrap: wrap;
background: var(--bg);
border: var(--panel-bordering);
border-radius: 0 8px 8px 8px;
overflow: hidden;
min-height: 300px;
}
/* 论坛板块样式 */
.forum {
background-color: var(--bg);
padding: var(--layout-margin);
position: relative;
border-right: var(--panel-bordering);
}
.forum:last-child {
border-right: none;
}
.guidebook, .news, .services {
min-height: 200px;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
z-index: 1;
padding: var(--layout-margin);
}
.guidebook {
width: 60%;
align-items: flex-start;
min-height: 300px;
position: relative;
}
/* 指南背景效果 */
.guidebook::before {
content: '';
background-color: var(--bg);
background-image: var(--guidebook-img);
background-blend-mode: luminosity;
background-size: cover;
background-position: center;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
opacity: 0.1;
filter: contrast(50%);
z-index: -1;
border-radius: 8px;
}
.guidebook h3 {
font-size: 2.5rem;
margin: 0 0 var(--inside-margin) 0;
color: var(--dark);
font-weight: 700;
}
.guidebook h3 a {
color: var(--dark);
text-decoration: none;
}
.guidebook h3 a:hover {
color: var(--accent);
}
.guidebook p {
background-color: RGBA(var(--lightRGB), 0.9);
border: var(--panel-bordering);
width: 100%;
padding: var(--inside-margin);
position: relative;
font-size: var(--small-font);
line-height: 1.6;
border-radius: 6px;
color: var(--dark);
}
/* 新闻服务区域 */
.news-services {
width: 40%;
margin-top: 0;
position: relative;
color: var(--font-color-light);
display: flex;
flex-direction: column;
gap: var(--inside-margin);
}
.news {
width: 100%;
background: RGBA(var(--accentRGB), 0.1);
border-radius: 8px;
padding: var(--layout-margin);
}
.news h4 {
font-size: 1rem;
text-transform: uppercase;
margin-bottom: var(--small-margin);
color: var(--accent);
font-weight: 600;
}
.news h4 a {
color: var(--accent);
text-decoration: none;
}
.news .news-details {
width: 100%;
margin: var(--small-margin) 0;
display: flex;
justify-content: space-between;
font-size: var(--small-font);
text-transform: uppercase;
color: RGBA(var(--darkRGB), 0.7);
}
.news h3 {
margin: var(--small-margin) 0;
font-size: 1.5rem;
text-align: left;
color: var(--dark);
font-weight: 600;
}
.news h3 a {
color: var(--dark);
text-decoration: none;
}
.news h3 a:hover {
color: var(--accent);
}
.news h5 {
text-transform: uppercase;
font-weight: normal;
font-size: var(--small-font);
color: RGBA(var(--darkRGB), 0.7);
}
.news h5 a {
color: var(--accent);
text-decoration: none;
}
/* 会员服务区域 */
.services {
width: 100%;
background: RGBA(var(--supportRGB), 0.1);
border-radius: 8px;
padding: var(--layout-margin);
}
.services h3 {
font-size: 1.5rem;
color: var(--dark);
margin-bottom: var(--inside-margin);
font-weight: 600;
}
.services h3 a {
color: var(--dark);
text-decoration: none;
}
.services h3 a:hover {
color: var(--accent);
}
.services-last {
display: flex;
align-items: center;
justify-content: flex-start;
margin-top: var(--small-margin);
font-size: var(--small-font);
text-transform: uppercase;
gap: var(--inside-margin);
}
.services-last img {
border: var(--panel-bordering);
width: calc(40px + var(--small-margin));
height: calc(40px + var(--small-margin));
object-fit: cover;
border-radius: 6px;
flex-shrink: 0;
}
.services-last div {
background: var(--bg);
border: var(--panel-bordering);
padding: var(--small-margin);
position: relative;
color: var(--font-color-light);
border-radius: 6px;
flex: 1;
}
.services-last div p {
margin: 2px 0;
font-size: var(--small-font);
}
.services-last div a {
color: var(--accent);
text-decoration: none;
}
.services-last div a:hover {
text-decoration: underline;
}
/* 对话气泡三角形 */
.services-last div::before {
content: '';
background-color: transparent;
border-right: var(--triangle-size) solid var(--border-color);
border-bottom: var(--triangle-size) solid transparent;
border-top: var(--triangle-size) solid transparent;
width: 0;
height: 0;
position: absolute;
top: calc(var(--triangle-size) - 1px);
right: calc(100%);
}
.services-last div::after {
content: '';
background-color: transparent;
border-right: calc(var(--triangle-size) - 1px) solid var(--bg);
border-bottom: calc(var(--triangle-size) - 1px) solid transparent;
border-top: calc(var(--triangle-size) - 1px) solid transparent;
width: 0;
height: 0;
position: absolute;
top: calc(var(--triangle-size));
right: calc(100%);
}
/* 底部信息*/
.siteNav {
background: #799fb4;
color: #333;
padding: 10px;
border-radius: 20px;
backdrop-filter: none;
}
.status-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
width: 100%;
max-width: 800px;
}
.status-info {
display: flex;
align-items: center;
gap: 25px;
padding: 5px 0;
}
#fps-counter {
font-family: var(--font-family);
font-size: 13px;
color: var(--dark);
letter-spacing: 0.5px;
}
.weather-widget {
display: flex;
transition: all 0.3s ease;
}
.weather-content {
display: flex;
align-items: center;
gap: 15px;
}
.weather-main {
display: flex;
align-items: center;
gap: 5px;
}
.weather-location {
display: flex;
align-items: center;
gap: 5px;
font-size: 13px;
color: var(--dark);
}
.weather-location i {
color: var(--accent);
font-size: 12px;
}
.weather-temp {
display: flex;
align-items: center;
gap: 5px;
font-size: 14px;
font-weight: 500;
color: var(--dark);
}
.weather-temp i {
color: var(--feature);
}
.weather-details {
display: flex;
align-items: center;
gap: 12px;
}
.weather-condition {
display: flex;
align-items: center;
gap: 5px;
color: var(--dark);
}
.weather-icon {
color: var(--support);
font-size: 12px;
}
.weather-stats {
display: flex;
gap: 12px;
}
.weather-stats span {
display: flex;
align-items: center;
gap: 3px;
color: var(--dark);
}
.weather-stats i {
font-size: 11px;
}
.weather-loading,
.weather-error {
font-size: 13px;
padding: 5px 0;
color: var(--dark);
}
//* 页脚链接样式 */
.siteNav {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
flex-wrap: wrap; /* 允许换行 */
gap: 10px; /* 元素间距 */
padding: 10px 0; /* 上下内边距 */
width: 100%; /* 确保占据全部宽度 */
}
.footer-info {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: 10px 20px; /* 行间距10px,列间距20px */
font-size: 14px;
color: var(--dark);
width: 100%; /* 确保占据全部宽度 */
text-align: center; /* 文本居中 */
}
.footer-info a {
color: var(--dark);
text-decoration: none;
transition: color 0.3s;
}
.footer-info a:hover {
color: var(--accent);
text-decoration: underline;
}
#performance-info {
display: inline-flex;
align-items: center;
gap: 5px;
}
/* 响应式调整 - 在小屏幕上堆叠显示 */
@media (max-width: 600px) {
.footer-info {
flex-direction: column;
gap: 5px;
}
}
/* 加载动画 */
.loader {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(var(--accentRGB), 0.3);
border-radius: 50%;
border-top-color: var(--accent);
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* 平滑滚动 */
html {
scroll-behavior: smooth;
}
/* 图片懒加载 */
img[data-src] {
opacity: 0;
transition: opacity 0.3s;
}
img.lazyloaded {
opacity: 1;
}
/* 访问性改进 */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
/* 打印样式 */
@media print {
body * {
visibility: hidden;
}
#printable, #printable * {
visibility: visible;
}
#printable {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
}
/* 代码格式化容器样式 */
.code-formatter-container {
background: var(--editor-secondary-bg);
border-radius: var(--border-radius);
margin: 15px 0;
border: var(--terminal-border);
overflow: hidden;
backdrop-filter: blur(5px);
width: 100%;
max-width: 100%;
}
.code-formatter-header {
background: var(--header-bg);
padding: 12px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: var(--terminal-border);
}
.code-formatter-title {
color: var(--text-color);
font-size: 14px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.code-formatter-close {
background: none;
border: none;
color: var(--line-color);
cursor: pointer;
padding: 4px;
border-radius: 4px;
}
.code-formatter-content {
padding: 15px;
width: 100%;
box-sizing: border-box;
}
.code-formatter-textarea {
width: 100%;
min-height: 200px;
padding: 12px;
border: var(--terminal-border);
border-radius: 8px;
background: var(--editor-bg);
color: var(--text-color);
font-family: var(--font-family);
font-size: 14px;
line-height: 1.5;
resize: vertical;
outline: none;
white-space: pre;
overflow-x: auto;
}
.code-formatter-actions {
display: flex;
gap: 10px;
margin-top: 15px;
flex-wrap: wrap;
}
.code-formatter-btn {
background: var(--terminal-accent-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
display: flex;
align-items: center;
gap: 6px;
font-weight: 500;
}
.code-formatter-btn:hover {
background: var(--terminal-accent-hover);
transform: translateY(-1px);
}
.code-type-selector {
flex: 1;
min-width: 120px;
padding: 8px 12px;
border: var(--terminal-border);
border-radius: 6px;
background: var(--editor-bg);
color: var(--text-color);
font-family: var(--fontBody);
font-size: 12px;
outline: none;
}
/* 躲猫猫*/
#maomao {
position: fixed;
bottom: 40px;
right: -5px;
width: 57px;
height: 70px;
background-image: url(https://siitake.cn/src/mao.svg);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
transition: background .3s;
z-index: 99999; /* Added to ensure it stays on top */
}
#maomao:hover {
background-position: 60px 50%;
}
/* 手机设备 (小于768px) */
@media screen and (max-width: 860px) {
#boardHeader .bannerImage video {
display: none !important;
}
#boardHeader .bannerStaff {
position: relative;
background: var(--lighter);
padding: 15px;
border-radius: 15px;
margin-top: 20px;
display: flex;
justify-content: center;
flex-wrap: wrap;
}
}
/* 个人信息卡片样式 */
.profile-card {
display: flex;
flex-direction: column;
align-items: center;
max-width: 500px; /* Added for better desktop layout */
margin: 0 auto; /* Added for better desktop layout */
padding: 20px; /* Added for internal spacing */
}
.profile-avatar-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.profile-avatar {
width: 140px;
height: 140px;
border-radius: 50%;
border: 5px solid var(--accent);
object-fit: cover;
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
transition: all 0.4s ease;
position: relative;
z-index: 2;
}
.profile-avatar:hover {
transform: scale(1.05);
}
/* 头像装饰环 */
.profile-avatar-container::before {
content: "";
position: absolute;
width: 160px;
height: 160px;
border: 2px solid RGBA(var(--supportRGB), 0.3);
border-radius: 50%;
animation: rotate 20s linear infinite;
z-index: 1;
}
.profile-avatar-container::after {
content: "";
position: absolute;
width: 180px;
height: 180px;
border: 1px solid RGBA(var(--featureRGB), 0.2);
border-radius: 50%;
animation: rotate 30s linear infinite reverse;
z-index: 1;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.profile-info {
text-align: center;
display: flex;
flex-direction: column;
gap: 15px;
}
.profile-name {
font: 800 36px/120% var(--fontBody);
color: var(--dark);
letter-spacing: -1px;
position: relative;
display: inline-block;
}
.profile-name::after {
content: "";
position: absolute;
bottom: -5px;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 3px;
background: linear-gradient(90deg, var(--accent), var(--support));
border-radius: 2px;
}
.profile-title {
font: 600 20px/140% var(--fontBody);
color: var(--accent);
margin-bottom: 10px;
}
.profile-description {
font: 400 16px/160% var(--fontBody);
color: RGBA(var(--darkRGB), 0.8);
max-width: 400px;
margin: 0 auto;
}
/* 社交链接样式 */
.social-links {
display: flex;
gap: 20px;
margin-top: 30px;
flex-wrap: wrap;
justify-content: center;
}
.social-link {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
border-radius: 50%;
background: var(--accent);
color: white;
font-size: 24px;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
text-decoration: none;
overflow: hidden;
cursor: pointer;
}
.social-link::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.2) 50%, transparent 70%);
transform: translateX(-100%);
transition: transform 0.6s ease;
}
.social-link:hover::before {
transform: translateX(100%);
}
.social-link:hover {
transform: translateY(-8px) scale(1.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
}
.social-link:active {
transform: translateY(-5px) scale(1.05);
}
/* 社交平台特定颜色 */
.social-link.wechat {
background: linear-gradient(135deg, #07c160, #05a050);
}
.social-link.qq {
background: linear-gradient(135deg, #12b7f5, #0ea5e9);
}
.social-link.zhihu {
background: linear-gradient(135deg, #0084ff, #0066cc);
}
.social-link.bilibili {
background: linear-gradient(135deg, #fb7299, #f43f5e);
}
/* 社交链接标签 */
.social-link-label {
position: absolute;
bottom: -35px;
left: 50%;
transform: translateX(-50%);
background: var(--dark);
color: var(--lighter);
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: all 0.3s ease;
z-index: 10;
}
.social-link-label::before {
content: "";
position: absolute;
top: -4px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid var(--dark);
}
.social-link:hover .social-link-label {
opacity: 1;
transform: translateX(-50%) translateY(-5px);
}
/* ================================
* 交互提示模态框 (Optimized/Shrunk)
* ================================ */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(5px);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
z-index: 2000;
}
.modal-overlay.show {
opacity: 1;
visibility: visible;
}
.modal {
background: var(--lighter);
border-radius: 15px; /* Reduced border-radius */
padding: 30px; /* Reduced padding */
max-width: 350px; /* Reduced max-width */
width: 90%;
text-align: center;
transform: scale(0.9) translateY(20px);
transition: all 0.3s ease;
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25); /* Adjusted shadow */
border: 1px solid RGBA(var(--accentRGB), 0.2);
}
.modal-overlay.show .modal {
transform: scale(1) translateY(0);
}
.modal-icon {
font-size: 40px; /* Reduced font size */
margin-bottom: 15px; /* Reduced margin */
color: var(--accent);
}
.modal-title {
font: 700 20px/130% var(--fontBody); /* Reduced font size */
color: var(--dark);
margin-bottom: 10px; /* Reduced margin */
}
.modal-content {
font: 400 14px/150% var(--fontBody); /* Reduced font size */
color: RGBA(var(--darkRGB), 0.8);
margin-bottom: 20px; /* Reduced margin */
}
.modal-buttons {
display: flex;
gap: 10px; /* Reduced gap */
justify-content: center;
}
.modal-btn {
padding: 10px 20px; /* Reduced padding */
border-radius: 20px; /* Adjusted border-radius */
font: 600 13px var(--fontBody); /* Reduced font size */
cursor: pointer;
transition: all 0.3s ease;
border: none;
min-width: 90px; /* Adjusted min-width */
}
.modal-btn.primary {
background: var(--accent);
color: white;
}
.modal-btn.primary:hover {
background: var(--support);
transform: translateY(-2px);
}
.modal-btn.secondary {
background: transparent;
color: var(--dark);
border: 2px solid var(--accent);
}
.modal-btn.secondary:hover {
background: var(--accent);
color: white;
}
</style>
</head>
<div id="maomao" onMouseOut="duoMaomao()"></div>
<body class="act-idx code-00 group-4">
<!-- 波浪背景SVG -->
<svg id="headerWave" style="transform:rotate(180deg); transition: 0.3s" viewBox="0 0 1440 490" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="sw-gradient-0" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 0px); opacity:1" fill="url(#sw-gradient-0)" d="M0,294L80,253.2C160,212,320,131,480,155.2C640,180,800,310,960,334.8C1120,359,1280,278,1440,261.3C1600,245,1760,294,1920,294C2080,294,2240,245,2400,220.5C2560,196,2720,196,2880,187.8C3040,180,3200,163,3360,179.7C3520,196,3680,245,3840,277.7C4000,310,4160,327,4320,294C4480,261,4640,180,4800,147C4960,114,5120,131,5280,179.7C5440,229,5600,310,5760,351.2C5920,392,6080,392,6240,326.7C6400,261,6560,131,6720,65.3C6880,0,7040,0,7200,65.3C7360,131,7520,261,7680,334.8C7840,408,8000,425,8160,432.8C8320,441,8480,441,8640,400.2C8800,359,8960,278,9120,220.5C9280,163,9440,131,9600,171.5C9760,212,9920,327,10080,359.3C10240,392,10400,343,10560,310.3C10720,278,10880,261,11040,228.7C11200,196,11360,147,11440,122.5L11520,98L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
<defs>
<linearGradient id="sw-gradient-1" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 50px); opacity:0.9" fill="url(#sw-gradient-1)" d="M0,196L80,220.5C160,245,320,294,480,294C640,294,800,245,960,212.3C1120,180,1280,163,1440,163.3C1600,163,1760,180,1920,196C2080,212,2240,229,2400,245C2560,261,2720,278,2880,294C3040,310,3200,327,3360,318.5C3520,310,3680,278,3840,294C4000,310,4160,376,4320,343C4480,310,4640,180,4800,138.8C4960,98,5120,147,5280,204.2C5440,261,5600,327,5760,318.5C5920,310,6080,229,6240,236.8C6400,245,6560,343,6720,318.5C6880,294,7040,147,7200,138.8C7360,131,7520,261,7680,277.7C7840,294,8000,196,8160,179.7C8320,163,8480,229,8640,212.3C8800,196,8960,98,9120,49C9280,0,9440,0,9600,0C9760,0,9920,0,10080,8.2C10240,16,10400,33,10560,32.7C10720,33,10880,16,11040,49C11200,82,11360,163,11440,204.2L11520,245L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
<defs>
<linearGradient id="sw-gradient-2" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 100px); opacity:0.8" fill="url(#sw-gradient-2)" d="M0,294L80,285.8C160,278,320,261,480,212.3C640,163,800,82,960,114.3C1120,147,1280,294,1440,302.2C1600,310,1760,180,1920,147C2080,114,2240,180,2400,187.8C2560,196,2720,147,2880,106.2C3040,65,3200,33,3360,57.2C3520,82,3680,163,3840,196C4000,229,4160,212,4320,179.7C4480,147,4640,98,4800,122.5C4960,147,5120,245,5280,277.7C5440,310,5600,278,5760,269.5C5920,261,6080,278,6240,277.7C6400,278,6560,261,6720,220.5C6880,180,7040,114,7200,73.5C7360,33,7520,16,7680,24.5C7840,33,8000,65,8160,122.5C8320,180,8480,261,8640,277.7C8800,294,8960,245,9120,212.3C9280,180,9440,163,9600,155.2C9760,147,9920,147,10080,187.8C10240,229,10400,310,10560,334.8C10720,359,10880,327,11040,294C11200,261,11360,229,11440,212.3L11520,196L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
</svg>
<!-- 主容器 -->
<div id="boardWrapper">
<!-- 用户菜单容器 -->
<div id="linkmenu-container">
<div id="linkmenu">
<!-- 终端容器 -->
<div id="terminal-container">
<!-- 终端编辑器 -->
<div class="editor" id="mainEditor">
<div class="editor-header">
<span class="window-btn close"></span>
<span class="window-btn minimize"></span>
<span class="window-btn maximize"></span>
<span class="title-bar">terminal.js - 藤原的个人终端</span>
</div>
<div class="editor-content" id="editorContent">
<div class="line">
<div class="line-content">
<span class="comment">// 个人信息配置</span>
</div>
</div>
<div class="line">
<div class="line-content">
<span class="keyword">const</span>
<span class="function">profile</span> = {
</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="keyword">name</span>: <span class="string">"藤原"</span>,
</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="keyword">title</span>: <span class="string">"职场牛马!!!"</span>,
</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="keyword">contact</span>: {
</div>
</div>
<div class="line">
<div class="line-content indent-2">
<span class="keyword">email</span>: <span class="string">
<a href="mailto:2083737075@qq.com">"2083737075@qq.com"</a>
</span>,
</div>
</div>
<div class="line">
<div class="line-content indent-2">
<span class="keyword">website</span>: <span class="string">
<a href="http://tengyuan.icu" target="_blank">"TengYuan.icu"</a>
</span>,
</div>
</div>
<div class="line">
<div class="line-content indent-2">
<span class="keyword">FileCodeBox</span>: <span class="string">
<a href="http://wp.tengyuan.icu/" target="_blank">"wp.tengyuan.icu"</a>
</span>,
</div>
</div>
<div class="line">
<div class="line-content indent">},</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="keyword">links</span>: {
</div>
</div>
<div class="line">
<div class="line-content indent-2">
<span class="keyword">travel blog</span>: <span class="string">
<a href="http://blog.tengyuan.icu/" target="_blank">"blog.tengyuan.icu"</a>
</span>,
</div>
</div>
<div class="line">
<div class="line-content indent-2">
<span class="keyword">birthday</span>: <span class="string">
<a href="http://sr.0814.cn" target="_blank">"2001/11/01"</a>
</span>,
</div>
</div>
<div class="line">
<div class="line-content indent">},</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="comment">// 座右铭</span>
</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="keyword">motto</span>: <span class="string">"以清简代码,筑玖维数字宇宙。"</span>,
</div>
</div>
<div class="line">
<div class="line-content indent">
<span class="keyword">copyright</span>: <span class="string">"2017-<span id="year"></span> 藤原"</span>,
</div>
</div>
<div class="line">
<div class="line-content">};</div>
</div>
<div class="line">
<div class="line-content">
<span class="comment">// 终端交互</span>
</div>
</div>
<div class="line">
<div class="line-content">
<span class="function">console</span>.<span class="function">log</span>(<span class="string">"欢迎访问藤原的个人终端"</span>);
</div>
</div>
<div class="line">
<div class="line-content">
<span class="function">console</span>.<span class="function">log</span>(<span class="string">"输入 'help' 获取可用命令"</span>);
</div>
</div>
</div>
<!-- 输入行 -->
<div class="input-line">
<input type="text" id="userInput" placeholder="输入命令..." autocomplete="off">
</div>
</div>
</div>
</div>
</div>
<!-- 顶部导航栏 -->
<div id="topbar">
<nav class="topbarlinks guest" style="display: none;">
<section>
<button onclick="usertoggle()" class="memberAvatar">
<i class="ri-align-justify"></i>
</button>
</section>
<section class="quickLinks">
<a href="/">
<i class="ri-settings-3-line"></i>
</a>
<a href="/">
<i class="ri-logout-circle-r-line"></i>
</a>
</section>
</nav>
<nav class="topbarlinks member">
<section>
<button onclick="usertoggle()" class="memberAvatar">
<i class="ri-align-justify"></i>
</button>
</section>
<section class="quickLinks">
<label class="theme-switch" for="checkbox" id="theme_switch_click">
<input type="checkbox" id="checkbox">
<i class="ri-lightbulb-line light-icon"></i>
<i class="ri-lightbulb-flash-line dark-icon"></i>
<span>主题切换</span>
</label>
<a href="/">
<i class="ri-question-answer-line"></i>
<span>3 条消息</span>
</a>
<a href="/">
<i class="ri-feedback-line"></i>
<span>10 条提醒</span>
</a>
<a href="/">
<i class="ri-settings-3-line"></i>
<span>账户设置</span>
</a>
</section>
</nav>
</div>
<!-- 页眉部分 -->
<header id="boardHeader">
<div class="bannerInformation">
<svg id="headerWave1" style="transform:rotate(180deg); transition: 0.3s" viewBox="0 0 1440 490" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="sw-gradient-0" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 0px); opacity:1" fill="url(#sw-gradient-0)" d="M0,343L80,359.3C160,376,320,408,480,367.5C640,327,800,212,960,212.3C1120,212,1280,327,1440,383.8C1600,441,1760,441,1920,383.8C2080,327,2240,212,2400,171.5C2560,131,2720,163,2880,147C3040,131,3200,65,3360,98C3520,131,3680,261,3840,318.5C4000,376,4160,359,4320,318.5C4480,278,4640,212,4800,163.3C4960,114,5120,82,5280,89.8C5440,98,5600,147,5760,163.3C5920,180,6080,163,6240,138.8C6400,114,6560,82,6720,106.2C6880,131,7040,212,7200,253.2C7360,294,7520,294,7680,261.3C7840,229,8000,163,8160,147C8320,131,8480,163,8640,171.5C8800,180,8960,163,9120,138.8C9280,114,9440,82,9600,89.8C9760,98,9920,147,10080,163.3C10240,180,10400,163,10560,147C10720,131,10880,114,11040,89.8C11200,65,11360,33,11440,16.3L11520,0L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
<defs>
<linearGradient id="sw-gradient-1" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 50px); opacity:0.9" fill="url(#sw-gradient-1)" d="M0,147L80,179.7C160,212,320,278,480,269.5C640,261,800,180,960,155.2C1120,131,1280,163,1440,220.5C1600,278,1760,359,1920,351.2C2080,343,2240,245,2400,204.2C2560,163,2720,180,2880,228.7C3040,278,3200,359,3360,343C3520,327,3680,212,3840,179.7C4000,147,4160,196,4320,228.7C4480,261,4640,278,4800,236.8C4960,196,5120,98,5280,98C5440,98,5600,196,5760,269.5C5920,343,6080,392,6240,408.3C6400,425,6560,408,6720,343C6880,278,7040,163,7200,122.5C7360,82,7520,114,7680,122.5C7840,131,8000,114,8160,138.8C8320,163,8480,229,8640,253.2C8800,278,8960,261,9120,261.3C9280,261,9440,278,9600,294C9760,310,9920,327,10080,334.8C10240,343,10400,343,10560,334.8C10720,327,10880,310,11040,326.7C11200,343,11360,392,11440,416.5L11520,441L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
<defs>
<linearGradient id="sw-gradient-2" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 100px); opacity:0.8" fill="url(#sw-gradient-2)" d="M0,441L80,432.8C160,425,320,408,480,359.3C640,310,800,229,960,220.5C1120,212,1280,278,1440,318.5C1600,359,1760,376,1920,326.7C2080,278,2240,163,2400,147C2560,131,2720,212,2880,277.7C3040,343,3200,392,3360,383.8C3520,376,3680,310,3840,269.5C4000,229,4160,212,4320,204.2C4480,196,4640,196,4800,187.8C4960,180,5120,163,5280,163.3C5440,163,5600,180,5760,228.7C5920,278,6080,359,6240,351.2C6400,343,6560,245,6720,245C6880,245,7040,343,7200,318.5C7360,294,7520,147,7680,98C7840,49,8000,98,8160,171.5C8320,245,8480,343,8640,383.8C8800,425,8960,408,9120,343C9280,278,9440,163,9600,122.5C9760,82,9920,114,10080,179.7C10240,245,10400,343,10560,392C10720,441,10880,441,11040,416.5C11200,392,11360,343,11440,318.5L11520,294L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
</svg>
<div class="bannerTitle">
<h1 id="welcome-message">Life is a wilderness!<b> Mom</b>.</h1>
<h2 id="tengyuan-title">TENG YUAN</h2>
</div>
<!-- 新增个人信息卡片 -->
<div class="profile-card" id="profile-card" style="display: none;">
<div class="profile-avatar-container">
<img src="https://img.alicdn.com/imgextra/i2/2214968904665/O1CN01SEHUss1kKcibIYTOJ_!!2214968904665.jpg"
alt="藤原头像"
class="profile-avatar">
</div>
<div class="profile-info">
<div class="profile-name">TENG YUAN</div>
<div class="profile-title">职场牛马</div>
<div class="profile-description">
人生是旷野!<br>
妈妈。
</div>
</div>
<div class="social-links">
<div class="social-link wechat" onclick="showWeChatModal()">
<i class="ri-wechat-line"></i>
<div class="social-link-label">微信</div>
</div>
<div class="social-link qq" onclick="showQQModal()">
<i class="ri-qq-line"></i>
<div class="social-link-label">QQ</div>
</div>
<a href="https://www.zhihu.com/" class="social-link zhihu" target="_blank">
<i class="ri-zhihu-line"></i>
<div class="social-link-label">知乎</div>
</a>
<a href="https://www.bilibili.com/" class="social-link bilibili" target="_blank">
<i class="ri-bilibili-line"></i>
<div class="social-link-label">哔哩哔哩</div>
</a>
</div>
</div>
<svg id="headerWave2" style="transform:rotate(0deg); transition: 0.3s" viewBox="0 0 1440 490" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="sw-gradient-0" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 0px); opacity:1" fill="url(#sw-gradient-0)" d="M0,98L80,147C160,196,320,294,480,334.8C640,376,800,359,960,318.5C1120,278,1280,212,1440,187.8C1600,163,1760,180,1920,196C2080,212,2240,229,2400,204.2C2560,180,2720,114,2880,147C3040,180,3200,310,3360,326.7C3520,343,3680,245,3840,220.5C4000,196,4160,245,4320,220.5C4480,196,4640,98,4800,98C4960,98,5120,196,5280,204.2C5440,212,5600,131,5760,130.7C5920,131,6080,212,6240,212.3C6400,212,6560,131,6720,122.5C6880,114,7040,180,7200,187.8C7360,196,7520,147,7680,179.7C7840,212,8000,327,8160,383.8C8320,441,8480,441,8640,392C8800,343,8960,245,9120,171.5C9280,98,9440,49,9600,49C9760,49,9920,98,10080,130.7C10240,163,10400,180,10560,155.2C10720,131,10880,65,11040,65.3C11200,65,11360,131,11440,163.3L11520,196L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
<defs>
<linearGradient id="sw-gradient-1" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 50px); opacity:0.9" fill="url(#sw-gradient-1)" d="M0,294L80,318.5C160,343,320,392,480,392C640,392,800,343,960,294C1120,245,1280,196,1440,179.7C1600,163,1760,180,1920,228.7C2080,278,2240,359,2400,392C2560,425,2720,408,2880,343C3040,278,3200,163,3360,98C3520,33,3680,16,3840,32.7C4000,49,4160,98,4320,122.5C4480,147,4640,147,4800,122.5C4960,98,5120,49,5280,49C5440,49,5600,98,5760,130.7C5920,163,6080,180,6240,163.3C6400,147,6560,98,6720,98C6880,98,7040,147,7200,196C7360,245,7520,294,7680,277.7C7840,261,8000,180,8160,155.2C8320,131,8480,163,8640,155.2C8800,147,8960,98,9120,138.8C9280,180,9440,310,9600,310.3C9760,310,9920,180,10080,171.5C10240,163,10400,278,10560,294C10720,310,10880,229,11040,179.7C11200,131,11360,114,11440,106.2L11520,98L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
<defs>
<linearGradient id="sw-gradient-2" x1="0" x2="0" y1="1" y2="0">
<stop stop-color="var(--accent)" offset="0%"></stop>
<stop stop-color="var(--support)" offset="50%"></stop>
<stop stop-color="var(--feature)" offset="100%"></stop>
</linearGradient>
</defs>
<path style="transform:translate(0, 100px); opacity:0.8" fill="url(#sw-gradient-2)" d="M0,196L80,179.7C160,163,320,131,480,155.2C640,180,800,261,960,310.3C1120,359,1280,376,1440,326.7C1600,278,1760,163,1920,106.2C2080,49,2240,49,2400,81.7C2560,114,2720,180,2880,212.3C3040,245,3200,245,3360,261.3C3520,278,3680,310,3840,310.3C4000,310,4160,278,4320,220.5C4480,163,4640,82,4800,40.8C4960,0,5120,0,5280,32.7C5440,65,5600,131,5760,130.7C5920,131,6080,65,6240,40.8C6400,16,6560,33,6720,49C6880,65,7040,82,7200,73.5C7360,65,7520,33,7680,65.3C7840,98,8000,196,8160,236.8C8320,278,8480,261,8640,245C8800,229,8960,212,9120,245C9280,278,9440,359,9600,359.3C9760,359,9920,278,10080,228.7C10240,180,10400,163,10560,204.2C10720,245,10880,343,11040,343C11200,392,11360,245,11440,196L11520,147L11520,490L11440,490C11360,490,11200,490,11040,490C10880,490,10720,490,10560,490C10400,490,10240,490,10080,490C9920,490,9760,490,9600,490C9440,490,9280,490,9120,490C8960,490,8800,490,8640,490C8480,490,8320,490,8160,490C8000,490,7840,490,7680,490C7520,490,7360,490,7200,490C7040,490,6880,490,6720,490C6560,490,6400,490,6240,490C6080,490,5920,490,5760,490C5600,490,5440,490,5280,490C5120,490,4960,490,4800,490C4640,490,4480,490,4320,490C4160,490,4000,490,3840,490C3680,490,3520,490,3360,490C3200,490,3040,490,2880,490C2720,490,2560,490,2400,490C2240,490,2080,490,1920,490C1760,490,1600,490,1440,490C1280,490,1120,490,960,490C800,490,640,490,480,490C320,490,160,490,80,490L0,490Z"></path>
</svg>
</div>
<aside class="bannerImage">
<!-- 视频背景(必须加 playsinline 兼容移动端) -->
<video autoplay muted loop playsinline style="position: absolute; width: 100%; height: 100%; object-fit: cover;">
<source src="http://cloud.video.taobao.com/play/u/2214968904665/p/2/e/6/t/1/525727450638.mp4" type="video/mp4">
你的浏览器不支持视频播放
</video>
<!-- 管理员头像(保持在视频上层) -->
<div class="bannerStaff">
<a href="#" class="adminImage">
<img src="https://img.alicdn.com/imgextra/i2/2214968904665/O1CN01SEHUss1kKcibIYTOJ_!!2214968904665.jpg">
</a>
<a href="#" class="adminImage">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01aTWCuI1kKciYs3UMM_!!2214968904665.jpg">
</a>
<a href="#" class="adminImage">
<img src="https://img.alicdn.com/imgextra/i3/2214968904665/O1CN01BWuteG1kKcibhuu9d_!!2214968904665.jpg">
</a>
<a href="#" class="adminImage">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01Ixz8Ms1kKciZNZyv4_!!2214968904665.jpg">
</a>
</div>
</aside>
</header>
<!-- 微信模态框 -->
<div class="modal-overlay" id="wechat-modal">
<div class="modal">
<div class="modal-icon">
<i class="ri-wechat-line"></i>
</div>
<div class="modal-title">微信联系</div>
<div class="modal-content">
微信号:请通过邮箱联系获取<br />
邮箱:2083737075@qq.com<br /><br />
<small>为了隐私安全,微信号不直接展示</small>
</div>
<div class="modal-buttons">
<button class="modal-btn primary" onclick="copyEmail()">复制邮箱</button>
<button class="modal-btn secondary" onclick="closeModal('wechat-modal')">关闭</button>
</div>
</div>
</div>
<!-- QQ模态框 -->
<div class="modal-overlay" id="qq-modal">
<div class="modal">
<div class="modal-icon">
<i class="ri-qq-line"></i>
</div>
<div class="modal-title">QQ联系</div>
<div class="modal-content">
QQ号:2083737075<br /><br />
点击下方按钮可以直接打开QQ聊天
</div>
<div class="modal-buttons">
<button class="modal-btn primary" onclick="openQQ()">打开QQ</button>
<button class="modal-btn secondary" onclick="closeModal('qq-modal')">关闭</button>
</div>
</div>
</div>
<!-- 中间内容区域 -->
<div id="boardCrotch">
<section class="siteTime" style="background-image: var(--settingImage);">
<div class="siteTimeIcon">
<i class="ri-map-pin-user-fill"></i>
</div>
<h1>虚构的城市</h1>
<h2>
<i class="ri-sun-foggy-line"></i> 2025年夏季
</h2>
</section>
<!-- 导航区域 -->
<section class="siteArticle">
<!-- 垂直轮播容器 -->
<div class="vertical-carousel-container">
<!-- 导航链接页面 -->
<div class="vertical-carousel-page active" data-page="navigation">
<nav class="siteLinks">
<div class="navLinksContainer">
<a href="https://weixin.qq.com/" target="_blank">
<i class="ri-wechat-line"></i> WeChat
</a>
<a href="https://im.qq.com/" target="_blank">
<i class="ri-qq-line"></i> QQ
</a>
<a href="https://www.zhihu.com/" target="_blank">
<i class="ri-zhihu-line"></i> Zhihu
</a>
<a href="https://www.bilibili.com/" target="_blank">
<i class="ri-bilibili-line"></i> Bilibili
</a>
<a href="https://github.com/" target="_blank">
<i class="ri-github-line"></i> GitHub
</a>
<a href="https://stackoverflow.com/" target="_blank">
<i class="ri-stack-overflow-line"></i> Stack Overflow
</a>
<a href="https://developer.mozilla.org/" target="_blank">
<i class="ri-firefox-line"></i> MDN Web Docs
</a>
<a href="https://www.npmjs.com/" target="_blank">
<i class="ri-npmjs-line"></i> NPM
</a>
<a href="https://codepen.io/" target="_blank">
<i class="ri-codepen-line"></i> CodePen
</a>
<a href="https://dribbble.com/" target="_blank">
<i class="ri-dribbble-line"></i> Dribbble
</a>
<a href="https://unsplash.com/" target="_blank">
<i class="ri-camera-line"></i> Unsplash
</a>
<a href="https://fonts.google.com/" target="_blank">
<i class="ri-font-size"></i> Google Fonts
</a>
<a href="https://www.figma.com/" target="_blank">
<i class="ri-pencil-ruler-2-line"></i> Figma
</a>
<a href="https://tailwindcss.com/" target="_blank">
<i class="ri-css3-line"></i> Tailwind CSS
</a>
<a href="https://reactjs.org/" target="_blank">
<i class="ri-reactjs-line"></i> React
</a>
<a href="https://vuejs.org/" target="_blank">
<i class="ri-vuejs-line"></i> Vue.js
</a>
</div>
<span class="navTitle">
<span>quick</span>
<span class="navTitleClass">
<i class="ri-arrow-go-back-line"></i> nav
</span>
</span>
</nav>
</div>
<!-- 友情链接页面 -->
<div class="vertical-carousel-page" data-page="friends">
<nav class="siteLinks">
<div class="navLinksContainer">
<a href="https://izio.cc" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 知栖小筑
</a>
<a href="/" target="_blank" title="一款上班摸鱼的神器">
<i class="ri-user-heart-line"></i> 老板来了
</a>
<a href="https://yilx.net" target="_blank" title="风带来种子,时间使之发芽">
<i class="ri-user-heart-line"></i> 熙の主页
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链4
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链5
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链6
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链7
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链8
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链9
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链10
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链11
</a>
<a href="/" target="_blank" title="没有bug的代码是不完美的">
<i class="ri-user-heart-line"></i> 友链12
</a>
</div>
<span class="navTitle">
<span>friends</span>
<span class="navTitleClass">
<i class="ri-heart-line"></i> links
</span>
</span>
</nav>
</div>
<!-- 导航区域 -->
<section class="siteArticle">
<!-- 垂直轮播容器 -->
<div class="vertical-carousel-container">
<!-- 推荐文章页面-->
<div class="vertical-carousel-page recommend-page" data-page="recommend">
<nav class="siteLinks">
<div class="navLinksContainer">
<div class="single-article-container">
<!-- 文章1 -->
<div class="article-slide active" data-index="0"
onclick="window.open('https://example.com/articles/frontend-trends-2025', '_blank')"
style="cursor: pointer;">
<div class="article-header">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01x1Sp471kKciYVOjv5_!!2214968904665.jpg_.webp"
alt="前端开发"
class="article-image">
<h3 class="article-title">前端开发2025趋势与新技术探索</h3>
</div>
<div class="article-content">
<p class="article-excerpt">深入探讨2025年前端开发的新技术和工具,包括WebAssembly、AI辅助开发等前沿技术的实际应用案例和最佳实践方案,帮助开发者把握技术发展方向...</p>
<div class="article-meta">
</div>
</div>
</div>
<!-- 文章2 -->
<div class="article-slide" data-index="1"
onclick="window.open('https://example.com/articles/css-grid-guide', '_blank')"
style="cursor: pointer;">
<div class="article-header">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01x1Sp471kKciYVOjv5_!!2214968904665.jpg_.webp"
alt="CSS布局"
class="article-image">
<h3 class="article-title">CSS Grid布局完全指南与实践</h3>
</div>
<div class="article-content">
<p class="article-excerpt">从基础概念到高级技巧,全面解析CSS Grid布局系统,结合实际案例演示如何构建复杂的响应式网页布局,提升开发效率和设计灵活性...</p>
<div class="article-meta">
</div>
</div>
</div>
<!-- 文章3 -->
<div class="article-slide" data-index="2"
onclick="window.open('https://example.com/articles/js-optimization', '_blank')"
style="cursor: pointer;">
<div class="article-header">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01x1Sp471kKciYVOjv5_!!2214968904665.jpg_.webp"
alt="JS优化"
class="article-image">
<h3 class="article-title">JavaScript性能优化10个实用技巧</h3>
</div>
<div class="article-content">
<p class="article-excerpt">分享10个经过验证的JavaScript性能优化技巧,包括代码结构优化、内存管理、DOM操作优化等,让你的网站运行更加流畅,提升用户体验...</p>
<div class="article-meta">
</div>
</div>
</div>
<!-- 文章4 -->
<div class="article-slide" data-index="3"
onclick="window.open('https://example.com/articles/responsive-design', '_blank')"
style="cursor: pointer;">
<div class="article-header">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01x1Sp471kKciYVOjv5_!!2214968904665.jpg_.webp"
alt="响应式设计"
class="article-image">
<h3 class="article-title">响应式设计2025最佳实践方案</h3>
</div>
<div class="article-content">
<p class="article-excerpt">解析2025年响应式设计的最新趋势和技术,从移动优先到自适应布局,提供完整的解决方案和实用技巧,适应各种设备和屏幕尺寸...</p>
<div class="article-meta">
</div>
</div>
</div>
<!-- 文章5 -->
<div class="article-slide" data-index="4"
onclick="window.open('https://example.com/articles/web-animation', '_blank')"
style="cursor: pointer;">
<div class="article-header">
<img src="https://img.alicdn.com/imgextra/i1/2214968904665/O1CN01x1Sp471kKciYVOjv5_!!2214968904665.jpg_.webp"
alt="Web动画"
class="article-image">
<h3 class="article-title">现代Web动画设计与实现指南</h3>
</div>
<div class="article-content">
<p class="article-excerpt">使用CSS和JavaScript创建流畅的Web动画,从基础动画原理到高级交互效果,全面讲解如何提升用户体验和页面表现力的完整指南...</p>
<div class="article-meta">
</div>
</div>
</div>
<!-- 导航按钮 -->
<button class="article-nav-btn article-prev-btn" onclick="prevArticle()">
<i class="ri-arrow-left-s-line"></i>
</button>
<button class="article-nav-btn article-next-btn" onclick="nextArticle()">
<i class="ri-arrow-right-s-line"></i>
</button>
<!-- 控制点 -->
<div class="article-controls">
<button class="article-control-btn active" data-index="0"></button>
<button class="article-control-btn" data-index="1"></button>
<button class="article-control-btn" data-index="2"></button>
<button class="article-control-btn" data-index="3"></button>
<button class="article-control-btn" data-index="4"></button>
</div>
</div>
</div>
<span class="navTitle">
<span>recommend</span>
<span class="navTitleClass">
<i class="ri-bookmark-line"></i> articles
</span>
</span>
</nav>
</div>
<!-- 轮播控制按钮 -->
<div class="vertical-carousel-controls">
<button class="vertical-carousel-btn active" data-page="0" title="导航链接">
<i class="ri-compass-3-line"></i>
</button>
<button class="vertical-carousel-btn" data-page="1" title="友情链接">
<i class="ri-heart-line"></i>
</button>
<button class="vertical-carousel-btn" data-page="2" title="推荐文章">
<i class="ri-bookmark-line"></i>
</button>
</div>
</div>
</section>
</div>
<!-- 每日一言区域 -->
<section class="siteIntroduction" id="daily-quote">
<div class="quote-content">加载中...</div>
<div class="quote-from"></div>
</section>
</div>
<div id="boardCrotchBottom"></div>
<!-- 技术动态区域 -->
<div class="tech-trends">
<div class="category">
<div class="category-header">
技术动态与公告
</div>
<div class="category-basics">
<div class="forum guidebook">
<h3>
<a href="#" title="指南书">指南书</a>
</h3>
<p>
欢迎来到我们的角色扮演世界!这里汇聚了最优秀的创作者和玩家,共同构建精彩的故事。了解我们的团队成员,他们将为您提供最佳的游戏体验。
</p>
</div>
<div class="news-services">
<div class="forum news">
<h4>
<a href="#" title="每日星球">每日 <i class="ri-planet-line"></i> 星球</a>
</h4>
<div class="news-details">
<p>第 N°01 期</p>
<p>2025年1月15日</p>
</div>
<h3>
<a href="#" title="公告">超人从坟墓中归来!</a>
</h3>
<h5>
作者 <a href="#" title="露易丝·莱恩">露易丝·莱恩</a>
</h5>
</div>
<div class="forum services">
<h3>
<a href="#" title="会员服务">会员服务</a>
</h3>
<div class="services-last">
<img src="https://64.media.tumblr.com/f874e2d85797b8859ab056dc7e0bb682/de9f381ae561706d-d4/s640x960/44e13e9f0cd3bbe5e277ed0622ce4f5f8c8f029d.jpg" alt="个人资料">
<div>
<p><a href="#" title="最后帖子">最后帖子</a> 由 <a href="#" title="个人资料">神奇蜘蛛侠</a></p>
<p>2025年1月16日</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 内部内容容器 -->
<div id="innerWrapper">
<!-- 导航树样式 -->
<nav class="siteNav">
<i class="ri-hearts-line"></i>
<!-- 页脚信息行 -->
<div class="footer-info">
<span>© 2025 藤原 All Rights Reserved</span>
<a href="https://beian.miit.gov.cn/" target="_blank">ICP备案号: 闽ICP备2025097315号-2</a>
<a href="https://www.travellings.cn/go.html" target="_blank" rel="noopener" title="开往-友链接力">
<img src="https://www.travellings.cn/assets/logo.svg" alt="开往-友链接力" width="120">
</a>
<a href="https://www.rainyun.com/NTUwMDI0_" target="_blank" rel="noopener" title="开往-友链接力">
<img src="https://www.rainyun.com/img/logo.d193755d.png" alt="雨云服务器" width="120">
</a>
<span id="performance-info"></span>
</div>
</nav>
<!-- 隐藏的文件输入元素 -->
<input type="file" id="fileInput" accept="image/*" style="display: none;">
<script id="xplayer" src="https://y.cenguigui.cn/Static/player12/js/player.js" key="68613b9a36853" api="https://y.cenguigui.cn/"></script>
<!-- JavaScript代码 -->
<script>
/**
* ================================================================================
* 藤原终端系统 - 主要JavaScript文件
* ================================================================================
*
* 功能模块:
* 1. 终端交互系统
* 2. 影视解析功能
* 3. 短视频解析功能
* 4. 图片格式转换
* 5. 代码格式化工具
* 6. AI对话功能
* 7. 网络工具
* 8. 垂直轮播系统
* 9. 安全保护功能
* 10. 主题切换功能
*
* ================================================================================
*/
/**
* ================================================================================
* 全局变量配置
* ================================================================================
*/
// API配置信息
const API_CONFIG = {
id: "10003788",
key: "ffa8afb46dce4916c5a74fd73c8de9f6",
endpoints: {
ai: "https://cn.apihz.cn/api/ai/wxtiny.php",
ping: "https://cn.apihz.cn/api/wangzhan/ping.php",
shortVideo: "http://124.220.49.230/api/fun/douyin.php",
},
};
// 终端相关变量
const commandHistoryArray = JSON.parse(localStorage.getItem("commandHistory") || "[]");
let historyIndex = -1;
let totalParseCount = Number.parseInt(localStorage.getItem("totalParseCount") || "0");
let successParseCount = Number.parseInt(localStorage.getItem("successParseCount") || "0");
let indentSize = 4; // 默认缩进4个空格
// DOM元素引用
const editorContent = document.getElementById("editorContent");
const userInput = document.getElementById("userInput");
const fileInput = document.getElementById("fileInput");
/**
* ================================================================================
* 支持的视频平台配置
* ================================================================================
*/
// 支持的视频平台列表
const supportedVideoPlatforms = [
"v.qq.com", // 腾讯视频
"iqiyi.com", // 爱奇艺
"youku.com", // 优酷
"mgtv.com", // 芒果TV
"bilibili.com", // 哔哩哔哩
"sohu.com", // 搜狐视频
"le.com", // 乐视视频
"pptv.com", // PPTV
"wasu.cn", // 华数TV
"1905.com", // 电影网
"fun.tv", // 风行网
"acfun.cn", // AcFun
"douyu.com", // 斗鱼直播
"huya.com", // 虎牙直播
"yy.com", // YY直播
];
// 影视解析接口配置
const videoApis = [
{ name: "默认线路【推荐】", url: "https://www.yemu.xyz/?url=" },
{ name: "线路一【推荐】", url: "https://jx.we-vip.com/?url=" },
{ name: "线路二【推荐】", url: "https://z1.m1907.top/?jx=" },
{ name: "线路三", url: "https://www.ckplayer.vip/jiexi/?url=" },
{ name: "线路五", url: "https://jx.jsonplayer.com/player/?url=" },
{ name: "线路六", url: "https://jx.4kdv.com/?url=" },
{ name: "线路七", url: "https://api.jiexi.la/?url=" },
{ name: "线路八", url: "https://jx.qqwtt.com/?url=" },
{ name: "线路九", url: "https://www.playm3u8.cn/jiexi.php?url=" },
{ name: "线路十", url: "https://jx.xmflv.com/?url=" },
];
/**
* ================================================================================
* 帮助信息配置
* ================================================================================
*/
// 系统帮助文本
const helpText = `
可用命令:
基础命令:
- help: 显示帮助信息
- clear: 清空终端
- history: 显示命令历史记录
代码工具:
- format [code]: 格式化代码 (支持: sql, json, html, css, js)
例如: format {"name":"John","age":30}
- minify [code]: 压缩代码 (支持: sql, json, html, css, js)
例如: minify <div><p>Hello</p></div>
- detect [code]: 自动检测代码类型
例如: detect SELECT * FROM users
设置:
- set indent [size]: 设置缩进大小 (1-8个空格)
例如: set indent 4
影视工具:
- shortvideo [url]: 解析短视频(支持抖音、快手、小红书)
例如: shortvideo https://v.douyin.com/xxxxxx
网络工具:
- ping [url]: 测试网站或IP的ping延迟
例如: ping www.example.com
AI工具:
- ai [message]: 与AI助手对话
例如: ai 你好
图片工具:
- image [format]: 转换图片格式 (支持: jpg, png, webp, bmp)
例如: image png
其他工具:
- stats: 显示系统统计信息
`;
/**
* ================================================================================
* 初始化函数
* ================================================================================
*/
/**
* 设置当前年份
*/
function initializeYear() {
const yearElement = document.getElementById("year");
if (yearElement) {
yearElement.textContent = new Date().getFullYear();
}
}
/**
* 更新解析统计
*/
function updateParseStats() {
localStorage.setItem("totalParseCount", totalParseCount.toString());
localStorage.setItem("successParseCount", successParseCount.toString());
}
/**
* ================================================================================
* 终端核心功能
* ================================================================================
*/
/**
* 检查URL是否属于支持的视频平台
* @param {string} url - 要检查的URL
* @returns {boolean} 是否支持
*/
function isSupportedVideoUrl(url) {
if (!url) return false;
try {
const domain = new URL(url).hostname.toLowerCase();
return supportedVideoPlatforms.some((platform) => domain.includes(platform));
} catch (e) {
return false;
}
}
/**
* 打字机效果函数
* @param {HTMLElement} element - 目标元素
* @param {string} text - 要显示的文本
* @param {number} speed - 打字速度
* @returns {Promise} 完成Promise
*/
function typeWriterEffect(element, text, speed = 10) {
return new Promise((resolve) => {
let i = 0;
const typing = () => {
if (i < text.length) {
element.textContent += text.charAt(i);
i++;
setTimeout(typing, speed);
} else {
resolve();
}
};
typing();
});
}
/**
* 添加AI回复行
* @param {string} text - 回复文本
* @returns {Promise<HTMLElement>} 创建的行元素
*/
async function addAILine(text) {
const line = document.createElement("div");
line.className = "line";
const lineContent = document.createElement("div");
lineContent.className = "line-content ai-output";
lineContent.textContent = "藤原: ";
line.appendChild(lineContent);
editorContent.appendChild(line);
editorContent.scrollTop = editorContent.scrollHeight;
await typeWriterEffect(lineContent, text);
return line;
}
/**
* 添加用户输入行
* @param {string} text - 用户输入文本
* @returns {HTMLElement} 创建的行元素
*/
function addUserLine(text) {
const line = document.createElement("div");
line.className = "line";
const lineContent = document.createElement("div");
lineContent.className = "line-content user-input";
lineContent.textContent = `> ${text}`;
line.appendChild(lineContent);
editorContent.appendChild(line);
editorContent.scrollTop = editorContent.scrollHeight;
return line;
}
/**
* 清空终端
*/
function clearTerminal() {
const lines = document.querySelectorAll(".line");
lines.forEach((line) => {
const content = line.querySelector(".line-content").textContent;
if (
!content.includes("// 个人信息配置") &&
!content.includes("const profile") &&
!content.includes("name:") &&
!content.includes("title:") &&
!content.includes("contact:") &&
!content.includes("email:") &&
!content.includes("website:") &&
!content.includes("FileCodeBox:") &&
!content.includes("links:") &&
!content.includes("travel blog:") &&
!content.includes("birthday:") &&
!content.includes("motto:") &&
!content.includes("copyright:") &&
!content.includes("};") &&
!content.includes("// 终端交互") &&
!content.includes("console.log")
) {
line.remove();
}
});
// 移除各种组件
const componentsToRemove = [".video-container", ".tool-container", ".search-results", ".code-formatter-container"];
componentsToRemove.forEach((selector) => {
const element = document.querySelector(selector);
if (element) element.remove();
});
}
/**
* ================================================================================
* 代码格式化工具
* ================================================================================
*/
/**
* 格式化代码
* @param {string} code - 要格式化的代码
* @param {string} type - 代码类型
* @returns {string} 格式化后的代码
*/
function formatCode(code, type) {
try {
code = code.trim();
switch (type.toLowerCase()) {
case "json":
try {
const parsed = JSON.parse(code);
return JSON.stringify(parsed, null, " ".repeat(indentSize));
} catch (e) {
throw new Error(`JSON解析错误: ${e.message}`);
}
case "html":
return formatHTML(code);
case "js":
return formatJavaScript(code);
case "css":
return formatCSS(code);
case "sql":
return formatSQL(code);
default:
return code;
}
} catch (e) {
return `格式化错误: ${e.message}`;
}
}
/**
* 格式化HTML代码
* @param {string} html - HTML代码
* @returns {string} 格式化后的HTML
*/
function formatHTML(html) {
let formatted = "";
let indent = 0;
let currentLine = "";
for (let i = 0; i < html.length; i++) {
const char = html[i];
const nextChar = html[i + 1];
if (char === "<" && nextChar === "/") {
// 结束标签
indent = Math.max(0, indent - 1);
if (currentLine.trim()) {
formatted += " ".repeat(indent * indentSize) + currentLine + "\n";
currentLine = "";
}
currentLine += char;
} else if (char === "<") {
// 开始标签
if (currentLine.trim()) {
formatted += " ".repeat(indent * indentSize) + currentLine + "\n";
currentLine = "";
}
currentLine += char;
if (nextChar !== "!" && nextChar !== "?") {
indent++;
}
} else if (char === ">") {
// 标签结束
currentLine += char;
formatted += " ".repeat(Math.max(0, indent - 1) * indentSize) + currentLine + "\n";
currentLine = "";
} else {
currentLine += char;
}
}
return formatted.trim();
}
/**
* 格式化JavaScript代码
* @param {string} js - JavaScript代码
* @returns {string} 格式化后的JavaScript
*/
function formatJavaScript(js) {
let jsIndent = 0;
let jsResult = "";
let inString = false;
let stringChar = "";
// 处理基础缩进
js = js
.replace(/([{}[\]])/g, "\n$1\n")
.replace(/([;,])\s*/g, "$1\n")
.replace(/\n+/g, "\n");
const lines = js.split("\n");
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) continue;
// 处理字符串中的内容
if (inString) {
jsResult += trimmed;
if (trimmed.endsWith(stringChar)) {
inString = false;
stringChar = "";
}
continue;
}
if (trimmed.startsWith('"') || trimmed.startsWith("'")) {
inString = true;
stringChar = trimmed[0];
}
if (trimmed.endsWith("}") || trimmed.endsWith("]")) {
jsIndent--;
}
jsResult += " ".repeat(jsIndent * indentSize) + trimmed + "\n";
if (trimmed.endsWith("{") || trimmed.endsWith("[")) {
jsIndent++;
}
}
return jsResult.trim();
}
/**
* 格式化CSS代码
* @param {string} css - CSS代码
* @returns {string} 格式化后的CSS
*/
function formatCSS(css) {
return css
.replace(/\s*{\s*/g, " {\n" + " ".repeat(indentSize))
.replace(/;\s*/g, ";\n" + " ".repeat(indentSize))
.replace(/\s*}\s*/g, "\n}\n")
.replace(/,\s*/g, ",\n")
.trim();
}
/**
* 格式化SQL代码
* @param {string} sql - SQL代码
* @returns {string} 格式化后的SQL
*/
function formatSQL(sql) {
const keywords = [
"SELECT",
"FROM",
"WHERE",
"JOIN",
"INNER JOIN",
"LEFT JOIN",
"RIGHT JOIN",
"ORDER BY",
"GROUP BY",
"HAVING",
"INSERT",
"UPDATE",
"DELETE",
"CREATE",
"ALTER",
"DROP",
];
let formatted = sql;
keywords.forEach((keyword) => {
const regex = new RegExp(`\\b${keyword}\\b`, "gi");
formatted = formatted.replace(regex, `\n${keyword}`);
});
return formatted.trim();
}
/**
* 压缩代码
* @param {string} code - 要压缩的代码
* @param {string} type - 代码类型
* @returns {string} 压缩后的代码
*/
function minifyCode(code, type) {
try {
code = code.trim();
switch (type.toLowerCase()) {
case "json":
try {
const parsed = JSON.parse(code);
return JSON.stringify(parsed);
} catch (e) {
throw new Error(`JSON解析错误: ${e.message}`);
}
case "html":
return code
.replace(/\s+/g, " ")
.replace(/<!--[\s\S]*?-->/g, "")
.replace(/>\s+</g, "><")
.trim();
case "css":
return code
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/\s+/g, " ")
.replace(/\s*([{};:,])\s*/g, "$1")
.replace(/;}/g, "}")
.trim();
case "js":
return code
.replace(/\/\/.*|\/\*[\s\S]*?\*\//g, "")
.replace(/\s+/g, " ")
.replace(/\s*([=+\-*/%&|^~!<>?:;,{}()[\]])\s*/g, "$1")
.replace(/;}/g, "}")
.trim();
default:
return code;
}
} catch (e) {
return `压缩错误: ${e.message}`;
}
}
/**
* 检测代码类型
* @param {string} code - 要检测的代码
* @returns {string} 检测到的代码类型
*/
function detectCodeType(code) {
code = code.trim();
// 尝试解析为JSON
try {
JSON.parse(code);
return "json";
} catch (e) {}
// 检查HTML
if (code.startsWith("<") || code.match(/<[a-z][\s\S]*>/i)) {
return "html";
}
// 检查CSS
if (
code.match(/(^|\}|\{)[^{}]*\{[^{}]*\}/) ||
code.match(/\.([a-z][\w-]*)\s*\{|#([a-z][\w-]*)\s*\{|@(media|keyframes|import)/i)
) {
return "css";
}
// 检查SQL
if (code.match(/\b(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|FROM|WHERE|JOIN)\b/i)) {
return "sql";
}
// 检查JS
if (code.match(/function\s*\(|=>|\b(let|const|var)\s+\w+\s*=|console\.log|import\s+|export\s+/)) {
return "js";
}
return "text";
}
/**
* 创建代码格式化器
* @param {string} initialCode - 初始代码
* @param {string} initialType - 初始类型
* @param {string} operation - 操作类型
*/
function createCodeFormatter(initialCode = "", initialType = "auto", operation = "format") {
// 移除现有的格式化器
const existingFormatter = document.querySelector(".code-formatter-container");
if (existingFormatter) {
existingFormatter.remove();
return;
}
const formatter = document.createElement("div");
formatter.className = "code-formatter-container";
// 创建头部
const header = document.createElement("div");
header.className = "code-formatter-header";
const title = document.createElement("div");
title.className = "code-formatter-title";
title.innerHTML = `
<i class="ri-code-line"></i>
${operation === "format" ? "代码格式化工具" : "代码压缩工具"}
`;
const closeBtn = document.createElement("button");
closeBtn.className = "code-formatter-close";
closeBtn.innerHTML =
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
closeBtn.addEventListener("click", () => formatter.remove());
header.appendChild(title);
header.appendChild(closeBtn);
// 创建内容区域
const content = document.createElement("div");
content.className = "code-formatter-content";
// 代码类型选择器
const typeSelector = document.createElement("select");
typeSelector.className = "code-type-selector";
typeSelector.innerHTML = `
<option value="auto" ${initialType === "auto" ? "selected" : ""}>自动检测</option>
<option value="json" ${initialType === "json" ? "selected" : ""}>JSON</option>
<option value="html" ${initialType === "html" ? "selected" : ""}>HTML</option>
<option value="css" ${initialType === "css" ? "selected" : ""}>CSS</option>
<option value="js" ${initialType === "js" ? "selected" : ""}>JavaScript</option>
<option value="sql" ${initialType === "sql" ? "selected" : ""}>SQL</option>
`;
// 创建双面板布局
const panelContainer = document.createElement("div");
panelContainer.style.cssText = `
display: flex;
gap: 15px;
margin-bottom: 15px;
`;
// 输入面板
const inputPanel = createCodePanel("输入代码", initialCode, false);
// 输出面板
const outputPanel = createCodePanel("输出结果", "", true);
panelContainer.appendChild(inputPanel);
panelContainer.appendChild(outputPanel);
// 操作按钮
const actions = createFormatterActions(operation, typeSelector, inputPanel, outputPanel);
content.appendChild(panelContainer);
content.appendChild(actions);
formatter.appendChild(header);
formatter.appendChild(content);
// 添加到编辑器内容区
editorContent.appendChild(formatter);
editorContent.scrollTop = editorContent.scrollHeight;
// 自动聚焦到输入文本区域
const inputTextarea = inputPanel.querySelector("textarea");
inputTextarea.focus();
// 如果初始代码不为空,自动处理
if (initialCode.trim()) {
const processBtn = actions.querySelector(".code-formatter-btn");
processBtn.click();
}
}
/**
* 创建代码面板
* @param {string} label - 面板标签
* @param {string} value - 初始值
* @param {boolean} readOnly - 是否只读
* @returns {HTMLElement} 面板元素
*/
function createCodePanel(label, value, readOnly) {
const panel = document.createElement("div");
panel.style.cssText = `
flex: 1;
display: flex;
flex-direction: column;
`;
const labelEl = document.createElement("div");
labelEl.style.cssText = `
font-size: 12px;
color: var(--line-color);
margin-bottom: 5px;
`;
labelEl.textContent = label;
const textarea = document.createElement("textarea");
textarea.className = "code-formatter-textarea";
textarea.style.cssText = `
flex: 1;
min-height: 200px;
${readOnly ? "background: rgba(var(--accentRGB), 0.05);" : ""}
`;
textarea.value = value;
textarea.readOnly = readOnly;
panel.appendChild(labelEl);
panel.appendChild(textarea);
return panel;
}
/**
* 创建格式化器操作按钮
* @param {string} operation - 操作类型
* @param {HTMLElement} typeSelector - 类型选择器
* @param {HTMLElement} inputPanel - 输入面板
* @param {HTMLElement} outputPanel - 输出面板
* @returns {HTMLElement} 操作按钮容器
*/
function createFormatterActions(operation, typeSelector, inputPanel, outputPanel) {
const actions = document.createElement("div");
actions.className = "code-formatter-actions";
const processBtn = document.createElement("button");
processBtn.className = "code-formatter-btn";
processBtn.innerHTML = `
<i class="ri-${operation === "format" ? "indent-increase" : "indent-decrease"}"></i>
${operation === "format" ? "格式化代码" : "压缩代码"}
`;
const copyBtn = document.createElement("button");
copyBtn.className = "code-formatter-btn";
copyBtn.innerHTML = `
<i class="ri-clipboard-line"></i>
复制结果
`;
const detectBtn = document.createElement("button");
detectBtn.className = "code-formatter-btn";
detectBtn.innerHTML = `
<i class="ri-search-line"></i>
检测类型
`;
// 绑定事件处理器
setupFormatterEvents(processBtn, copyBtn, detectBtn, typeSelector, inputPanel, outputPanel, operation, actions);
actions.appendChild(typeSelector);
actions.appendChild(processBtn);
actions.appendChild(copyBtn);
actions.appendChild(detectBtn);
return actions;
}
/**
* 设置格式化器事件
* @param {HTMLElement} processBtn - 处理按钮
* @param {HTMLElement} copyBtn - 复制按钮
* @param {HTMLElement} detectBtn - 检测按钮
* @param {HTMLElement} typeSelector - 类型选择器
* @param {HTMLElement} inputPanel - 输入面板
* @param {HTMLElement} outputPanel - 输出面板
* @param {string} operation - 操作类型
* @param {HTMLElement} actions - 操作容器
*/
function setupFormatterEvents(
processBtn,
copyBtn,
detectBtn,
typeSelector,
inputPanel,
outputPanel,
operation,
actions,
) {
const inputTextarea = inputPanel.querySelector("textarea");
const outputTextarea = outputPanel.querySelector("textarea");
// 处理按钮点击事件
processBtn.addEventListener("click", () => {
const code = inputTextarea.value;
const type = typeSelector.value === "auto" ? detectCodeType(code) : typeSelector.value;
try {
const processed = operation === "format" ? formatCode(code, type) : minifyCode(code, type);
outputTextarea.value = processed;
showFormatterMessage(actions, `${operation === "format" ? "格式化" : "压缩"}成功 (类型: ${type})`, "success");
} catch (error) {
showFormatterMessage(actions, `${operation === "format" ? "格式化" : "压缩"}失败: ${error.message}`, "error");
}
});
// 复制按钮点击事件
copyBtn.addEventListener("click", () => {
outputTextarea.select();
document.execCommand("copy");
showFormatterMessage(actions, "代码已复制到剪贴板", "success");
});
// 检测按钮点击事件
detectBtn.addEventListener("click", () => {
const code = inputTextarea.value;
const type = detectCodeType(code);
showFormatterMessage(actions, `检测到的代码类型: ${type}`, "info");
if (type !== "text" && typeSelector.querySelector(`option[value="${type}"]`)) {
typeSelector.value = type;
}
});
}
/**
* 显示格式化器消息
* @param {HTMLElement} container - 容器元素
* @param {string} message - 消息内容
* @param {string} type - 消息类型
*/
function showFormatterMessage(container, message, type) {
// 移除旧的消息
const oldMessage = container.querySelector(".formatter-message");
if (oldMessage) oldMessage.remove();
const messageEl = document.createElement("div");
messageEl.className = "formatter-message";
messageEl.style.cssText = `
color: var(--${type === "error" ? "error" : type === "success" ? "success" : "terminal-accent"}-color);
font-size: 12px;
margin-top: 10px;
text-align: center;
`;
messageEl.textContent = message;
container.appendChild(messageEl);
// 3秒后自动消失
setTimeout(() => {
if (messageEl.parentNode) {
messageEl.style.opacity = "0";
setTimeout(() => messageEl.remove(), 300);
}
}, 3000);
}
/**
* ================================================================================
* 影视解析功能
* ================================================================================
*/
/**
* 解析视频
* @param {string} url - 视频URL
*/
function parseVideo(url) {
// 检查URL是否属于支持的视频平台
if (!isSupportedVideoUrl(url)) {
addAILine("藤原: 不支持该视频平台的解析,目前支持以下平台:");
addAILine("腾讯视频、爱奇艺、优酷、芒果TV、哔哩哔哩等");
return;
}
// 移除现有的播放器
const existingPlayer = document.querySelector(".video-container");
if (existingPlayer) {
existingPlayer.remove();
}
// 增加解析次数统计
totalParseCount++;
updateParseStats();
// 显示加载状态
const loadingLine = createLoadingLine("正在解析视频,请稍候...");
// 创建视频播放器
const videoContainer = createVideoPlayer(url);
// 添加到编辑器内容区
editorContent.appendChild(videoContainer);
editorContent.scrollTop = editorContent.scrollHeight;
// 更新加载状态
const loadingContent = loadingLine.querySelector(".line-content");
loadingContent.textContent = "藤原: 视频解析完成!";
// 增加成功统计
successParseCount++;
updateParseStats();
}
/**
* 创建加载行
* @param {string} message - 加载消息
* @returns {HTMLElement} 加载行元素
*/
function createLoadingLine(message) {
const loadingLine = document.createElement("div");
loadingLine.className = "line";
const loadingContent = document.createElement("div");
loadingContent.className = "line-content ai-output";
loadingContent.textContent = `藤原: ${message}`;
loadingLine.appendChild(loadingContent);
editorContent.appendChild(loadingLine);
editorContent.scrollTop = editorContent.scrollHeight;
return loadingLine;
}
/**
* 创建视频播放器
* @param {string} url - 视频URL
* @returns {HTMLElement} 视频播放器容器
*/
function createVideoPlayer(url) {
const videoContainer = document.createElement("div");
videoContainer.className = "video-container";
// 创建视频元素
const videoPlayer = document.createElement("div");
videoPlayer.className = "video-player";
const videoElement = document.createElement("iframe");
videoElement.id = "terminal-video";
// 使用默认解析线路
const defaultApi = videoApis[0];
videoElement.src = defaultApi.url + encodeURIComponent(url);
videoElement.frameBorder = "0";
videoElement.allowFullscreen = true;
videoElement.style.width = "100%";
videoElement.style.height = "100%";
videoPlayer.appendChild(videoElement);
// 视频控制区域
const videoControls = createVideoControls(url, defaultApi);
videoContainer.appendChild(videoPlayer);
videoContainer.appendChild(videoControls);
return videoContainer;
}
/**
* 创建视频控制器
* @param {string} url - 视频URL
* @param {Object} currentApi - 当前API
* @returns {HTMLElement} 控制器元素
*/
function createVideoControls(url, currentApi) {
const videoControls = document.createElement("div");
videoControls.className = "video-controls";
// 当前线路显示
const currentLine = document.createElement("span");
currentLine.style.cssText = "color: var(--line-color); font-size: 12px; margin-right: 10px;";
currentLine.textContent = `当前线路: ${currentApi.name}`;
// 创建控制按钮
const buttons = [
{ text: "刷新", handler: () => refreshVideo() },
{ text: "切换线路", handler: () => showVideoApiSelector(url) },
{ text: "全屏", handler: () => requestVideoFullscreen() },
{ text: "关闭", handler: () => closeVideoPlayer() },
];
videoControls.appendChild(currentLine);
buttons.forEach(({ text, handler }) => {
const button = document.createElement("button");
button.className = "video-button";
button.textContent = text;
button.addEventListener("click", handler);
videoControls.appendChild(button);
});
return videoControls;
}
/**
* 刷新视频
*/
function refreshVideo() {
const videoElement = document.getElementById("terminal-video");
if (videoElement) {
videoElement.src = videoElement.src;
}
}
/**
* 请求视频全屏
*/
function requestVideoFullscreen() {
const videoElement = document.getElementById("terminal-video");
if (videoElement && videoElement.requestFullscreen) {
videoElement.requestFullscreen();
}
}
/**
* 关闭视频播放器
*/
function closeVideoPlayer() {
const videoContainer = document.querySelector(".video-container");
if (videoContainer) {
videoContainer.remove();
}
}
/**
* 显示线路选择器
* @param {string} originalUrl - 原始URL
*/
function showVideoApiSelector(originalUrl) {
addAILine("可用解析线路:");
const selectorContainer = document.createElement("div");
selectorContainer.className = "tool-container";
// 创建头部
const header = createToolHeader("选择解析线路", "ri-list-settings-line", () => selectorContainer.remove());
// 创建内容区域
const content = document.createElement("div");
content.className = "tool-content";
content.style.padding = "15px";
// 添加线路选项
videoApis.forEach((api, index) => {
const apiBtn = document.createElement("button");
apiBtn.className = "tool-btn";
apiBtn.style.width = "100%";
apiBtn.style.marginBottom = "10px";
apiBtn.style.textAlign = "left";
apiBtn.innerHTML = `<i class="ri-play-line"></i> ${index + 1}. ${api.name}`;
apiBtn.addEventListener("click", () => {
switchVideoApi(originalUrl, index);
selectorContainer.remove();
});
content.appendChild(apiBtn);
});
selectorContainer.appendChild(header);
selectorContainer.appendChild(content);
editorContent.appendChild(selectorContainer);
editorContent.scrollTop = editorContent.scrollHeight;
}
/**
* 切换视频解析线路
* @param {string} originalUrl - 原始URL
* @param {number} apiIndex - API索引
*/
function switchVideoApi(originalUrl, apiIndex) {
const api = videoApis[apiIndex];
const apiUrl = api.url + encodeURIComponent(originalUrl);
// 更新iframe的src
const videoElement = document.getElementById("terminal-video");
if (videoElement) {
videoElement.src = apiUrl;
// 更新当前线路显示
const currentLine = document.querySelector(".video-controls span");
if (currentLine) {
currentLine.textContent = `当前线路: ${api.name}`;
}
addAILine(`已切换到 ${api.name}`);
}
}
/**
* ================================================================================
* 短视频解析功能
* ================================================================================
*/
/**
* 解析短视频
* @param {string} url - 短视频URL
*/
async function parseShortVideo(url) {
// 移除现有的解析结果
const existingResult = document.querySelector(".short-video-result");
if (existingResult) {
existingResult.remove();
}
// 增加解析次数统计
totalParseCount++;
updateParseStats();
// 显示加载状态
const loadingLine = createLoadingLine("正在解析短视频,请稍候...");
// 检查URL是否有效
if (!url || !url.startsWith("http")) {
const loadingContent = loadingLine.querySelector(".line-content");
loadingContent.textContent = "藤原: 请输入有效的短视频URL";
return;
}
try {
// 构建API请求URL
const params = new URLSearchParams({
id: API_CONFIG.id,
key: API_CONFIG.key,
url: url.replace(/&/g, "<"), // 替换&为<,根据API要求
});
const apiUrl = `${API_CONFIG.endpoints.shortVideo}?${params.toString()}`;
// 发送请求
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.code !== 200) {
throw new Error(data.msg || "解析失败");
}
// 创建结果容器
const resultContainer = createShortVideoResult(data);
// 添加到编辑器内容区
editorContent.appendChild(resultContainer);
editorContent.scrollTop = editorContent.scrollHeight;
// 更新加载状态
const loadingContent = loadingLine.querySelector(".line-content");
loadingContent.textContent = "藤原: 短视频解析完成!";
// 增加成功统计
successParseCount++;
updateParseStats();
} catch (error) {
console.error("短视频解析失败:", error);
const loadingContent = loadingLine.querySelector(".line-content");
loadingContent.textContent = `藤原: 短视频解析失败 - ${error.message}`;
// 显示重试按钮
const retryBtn = document.createElement("button");
retryBtn.className = "tool-btn";
retryBtn.style.marginTop = "10px";
retryBtn.innerHTML = '<i class="ri-refresh-line"></i> 重试';
retryBtn.addEventListener("click", () => parseShortVideo(url));
loadingLine.appendChild(retryBtn);
}
}
/**
* 创建短视频解析结果
* @param {Object} data - 解析数据
* @returns {HTMLElement} 结果容器
*/
function createShortVideoResult(data) {
const resultContainer = document.createElement("div");
resultContainer.className = "tool-container short-video-result";
// 头部
const header = createToolHeader("短视频解析结果", "ri-video-line", () => resultContainer.remove());
// 内容区域
const content = document.createElement("div");
content.className = "tool-content";
// 作者信息区域
const authorInfo = createAuthorInfo(data);
// 标题和描述
const titleInfo = createTitleInfo(data);
// 媒体内容
let mediaContent = "";
if (data.type === "视频") {
mediaContent = createVideoContent(data);
} else if (data.type === "图集" && data.images && data.images.length > 0) {
mediaContent = createGalleryContent(data);
} else {
throw new Error("无法识别的媒体类型");
}
// 音乐信息
const musicInfo = createMusicInfo(data);
content.innerHTML = authorInfo + titleInfo + mediaContent + musicInfo;
resultContainer.appendChild(header);
resultContainer.appendChild(content);
return resultContainer;
}
/**
* 创建作者信息
* @param {Object} data - 数据对象
* @returns {string} HTML字符串
*/
function createAuthorInfo(data) {
return `
<div style="display: flex; align-items: center; margin-bottom: 15px; padding: 12px; background: rgba(var(--accentRGB), 0.1); border-radius: 8px;">
<img src="${data.head?.[0] || "https://picsum.photos/100/100"}"
style="width: 40px; height: 40px; border-radius: 50%; margin-right: 12px; object-fit: cover;">
<div style="flex: 1; overflow: hidden;">
<div style="font-weight: 600; color: var(--text-color); margin-bottom: 2px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">
${data.name || "未知作者"}
</div>
<div style="font-size: 12px; color: var(--line-color); white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">
${data.signature || "暂无签名"}
</div>
</div>
</div>
`;
}
/**
* 创建标题信息
* @param {Object} data - 数据对象
* @returns {string} HTML字符串
*/
function createTitleInfo(data) {
return `
<div style="margin-bottom: 15px; padding: 12px; background: rgba(var(--supportRGB), 0.1); border-radius: 8px;">
<div style="font-weight: 600; color: var(--text-color); margin-bottom: 5px;">
${data.title || "无标题"}
</div>
<div style="font-size: 12px; color: var(--line-color);">
发布于 ${data.create_time ? new Date(data.create_time * 1000).toLocaleString() : "未知时间"}
</div>
</div>
`;
}
/**
* 创建视频内容
* @param {Object} data - 数据对象
* @returns {string} HTML字符串
*/
function createVideoContent(data) {
return `
<div style="position: relative; padding-top: 56.25%; margin-bottom: 15px; border-radius: 8px; overflow: hidden; background: #000;">
<video controls
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
poster="${data.cover || ""}"
crossorigin="anonymous">
<source src="${data.video || data.yvideo}" type="video/mp4">
您的浏览器不支持视频播放
</video>
</div>
<div class="tool-actions">
<button class="tool-btn" onclick="downloadVideo('${data.video || data.yvideo}', '${data.name || "短视频"}_${Date.now()}')">
<i class="ri-download-line"></i>
下载视频
</button>
<button class="tool-btn" onclick="showFullImage('${data.cover || ""}')">
<i class="ri-image-line"></i>
查看封面
</button>
</div>
`;
}
/**
* 创建图集内容
* @param {Object} data - 数据对象
* @returns {string} HTML字符串
*/
function createGalleryContent(data) {
const galleryHTML = data.images
.map(
(img, index) => `
<div style="position: relative; margin-bottom: 10px;">
<img src="${img}"
alt="图片 ${index + 1}"
style="width: 100%; border-radius: 8px; cursor: pointer;"
onclick="showFullImage('${img}')">
<div style="position: absolute; top: 8px; right: 8px; background: rgba(0,0,0,0.7); color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px;">
${index + 1}/${data.images.length}
</div>
</div>
`,
)
.join("");
return `
<div style="max-height: 400px; overflow-y: auto; margin-bottom: 15px;">
${galleryHTML}
</div>
<div class="tool-actions">
<button class="tool-btn" onclick="downloadAllImages(${JSON.stringify(data.images).replace(/"/g, """)}, '${data.name || "图集"}_${Date.now()}')">
<i class="ri-download-line"></i>
打包下载 (${data.images.length}张)
</button>
</div>
`;
}
/**
* 创建音乐信息
* @param {Object} data - 数据对象
* @returns {string} HTML字符串
*/
function createMusicInfo(data) {
if (!data.musictitle) return "";
return `
<div style="margin-top: 15px; padding: 12px; background: rgba(var(--featureRGB), 0.1); border-radius: 8px;">
<h4 style="color: var(--text-color); margin-bottom: 8px; display: flex; align-items: center; gap: 8px;">
<i class="ri-music-2-line"></i>
背景音乐
</h4>
<div style="font-size: 14px; color: var(--line-color); margin-bottom: 5px;">
${data.musictitle}
</div>
<div style="font-size: 12px; color: var(--line-color);">
${data.musicauthor || "未知作者"}
</div>
</div>
`;
}
/**
* ================================================================================
* 图片转换功能
* ================================================================================
*/
/**
* 创建图片转换器
* @param {string} targetFormat - 目标格式
*/
function createImageConverter(targetFormat) {
const existingConverter = document.querySelector(".image-converter");
if (existingConverter) {
existingConverter.remove();
return;
}
const converter = document.createElement("div");
converter.className = "tool-container image-converter";
// 头部
const header = createToolHeader("图片格式转换器", "ri-image-line", () => converter.remove());
// 内容区域
const content = document.createElement("div");
content.className = "tool-content";
// 预览区域
const previewContainer = createImagePreview();
// 尺寸设置区域
const sizeControls = createSizeControls();
// 格式信息
const formatInfo = createFormatInfo(targetFormat);
// 操作按钮
const actions = createImageActions(targetFormat, previewContainer);
content.appendChild(previewContainer);
content.appendChild(sizeControls);
content.appendChild(formatInfo);
content.appendChild(actions);
converter.appendChild(header);
converter.appendChild(content);
editorContent.appendChild(converter);
editorContent.scrollTop = editorContent.scrollHeight;
}
/**
* 创建图片预览区域
* @returns {HTMLElement} 预览容器
*/
function createImagePreview() {
const previewContainer = document.createElement("div");
previewContainer.className = "tool-preview-container";
const previewImage = document.createElement("img");
previewImage.className = "tool-preview";
const placeholder = document.createElement("div");
placeholder.className = "tool-placeholder";
placeholder.innerHTML = `
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<polyline points="21 15 16 10 5 21"></polyline>
</svg>
<div>请选择要转换的图片</div>
<div style="font-size:0.8em;margin-top:8px;opacity:0.7;">支持 JPG, PNG, WEBP, BMP 格式</div>
`;
previewContainer.appendChild(previewImage);
previewContainer.appendChild(placeholder);
return previewContainer;
}
/**
* 创建尺寸控制区域
* @returns {HTMLElement} 尺寸控制容器
*/
function createSizeControls() {
const sizeControls = document.createElement("div");
sizeControls.style.cssText = `
display: flex;
gap: 10px;
margin: 15px 0;
align-items: center;
`;
// 宽度输入
const widthControl = document.createElement("div");
widthControl.style.cssText = "flex: 1;";
widthControl.innerHTML = `
<label style="display: block; margin-bottom: 5px; font-size: 12px; color: var(--dark);">宽度 (px)</label>
<input type="number" id="imageWidth" class="tool-input" placeholder="自动" min="1" style="width: 100%;">
`;
// 高度输入
const heightControl = document.createElement("div");
heightControl.style.cssText = "flex: 1;";
heightControl.innerHTML = `
<label style="display: block; margin-bottom: 5px; font-size: 12px; color: var(--dark);">高度 (px)</label>
<input type="number" id="imageHeight" class="tool-input" placeholder="自动" min="1" style="width: 100%;">
`;
// 保持宽高比复选框
const ratioControl = document.createElement("div");
ratioControl.style.cssText = "flex: 1; display: flex; align-items: center;";
ratioControl.innerHTML = `
<input type="checkbox" id="keepAspectRatio" checked style="margin-right: 8px;">
<label for="keepAspectRatio" style="font-size: 12px; color: var(--dark);">保持宽高比</label>
`;
sizeControls.appendChild(widthControl);
sizeControls.appendChild(heightControl);
sizeControls.appendChild(ratioControl);
return sizeControls;
}
/**
* 创建格式信息
* @param {string} targetFormat - 目标格式
* @returns {HTMLElement} 格式信息元素
*/
function createFormatInfo(targetFormat) {
const formatInfo = document.createElement("div");
formatInfo.innerHTML = `
<div class="tool-info">
<strong>目标格式:</strong>${targetFormat.toUpperCase()}<br>
<strong>支持格式:</strong>JPG, PNG, WEBP, BMP 等主流图片格式
</div>
`;
return formatInfo;
}
/**
* 创建图片操作按钮
* @param {string} targetFormat - 目标格式
* @param {HTMLElement} previewContainer - 预览容器
* @returns {HTMLElement} 操作按钮容器
*/
function createImageActions(targetFormat, previewContainer) {
const actions = document.createElement("div");
actions.className = "tool-actions";
const selectBtn = document.createElement("button");
selectBtn.className = "tool-btn";
selectBtn.innerHTML = `
<i class="ri-folder-open-line"></i>
选择图片
`;
const convertBtn = document.createElement("button");
convertBtn.className = "tool-btn";
convertBtn.innerHTML = `
<i class="ri-refresh-line"></i>
转换为 ${targetFormat.toUpperCase()}
`;
// 设置事件处理器
setupImageEvents(selectBtn, convertBtn, targetFormat, previewContainer);
actions.appendChild(selectBtn);
actions.appendChild(convertBtn);
return actions;
}
/**
* 设置图片事件处理器
* @param {HTMLElement} selectBtn - 选择按钮
* @param {HTMLElement} convertBtn - 转换按钮
* @param {string} targetFormat - 目标格式
* @param {HTMLElement} previewContainer - 预览容器
*/
function setupImageEvents(selectBtn, convertBtn, targetFormat, previewContainer) {
const previewImage = previewContainer.querySelector(".tool-preview");
const placeholder = previewContainer.querySelector(".tool-placeholder");
// 创建临时文件输入元素
const tempFileInput = document.createElement("input");
tempFileInput.type = "file";
tempFileInput.accept = "image/*";
tempFileInput.style.display = "none";
// 点击选择按钮时触发文件选择
selectBtn.addEventListener("click", () => {
tempFileInput.click();
});
// 文件选择处理
tempFileInput.addEventListener("change", (e) => {
const file = e.target.files[0];
if (!file) return;
if (!file.type.match("image.*")) {
addAILine("请选择有效的图片文件");
return;
}
const reader = new FileReader();
reader.onload = (event) => {
previewImage.src = event.target.result;
previewImage.classList.add("active");
placeholder.style.display = "none";
// 图片加载完成后设置原始尺寸
previewImage.onload = function () {
setupImageSizeControls(this);
};
};
reader.readAsDataURL(file);
});
// 转换按钮事件
convertBtn.addEventListener("click", () => {
if (!previewImage.src) {
addAILine("请先选择要转换的图片");
return;
}
// 获取尺寸设置
const width = document.getElementById("imageWidth").value;
const height = document.getElementById("imageHeight").value;
const keepRatio = document.getElementById("keepAspectRatio").checked;
convertImage(previewImage, targetFormat, {
width: width ? Number.parseInt(width) : null,
height: height ? Number.parseInt(height) : null,
keepAspectRatio: keepRatio,
});
});
}
/**
* 设置图片尺寸控制
* @param {HTMLImageElement} img - 图片元素
*/
function setupImageSizeControls(img) {
const widthInput = document.getElementById("imageWidth");
const heightInput = document.getElementById("imageHeight");
widthInput.value = img.naturalWidth;
heightInput.value = img.naturalHeight;
// 计算原始宽高比
const originalRatio = img.naturalWidth / img.naturalHeight;
// 宽度变化时自动计算高度(如果保持宽高比)
widthInput.addEventListener("input", function () {
if (document.getElementById("keepAspectRatio").checked && originalRatio) {
heightInput.value = Math.round(this.value / originalRatio);
}
});
// 高度变化时自动计算宽度(如果保持宽高比)
heightInput.addEventListener("input", function () {
if (document.getElementById("keepAspectRatio").checked && originalRatio) {
widthInput.value = Math.round(this.value * originalRatio);
}
});
}
/**
* 图片转换函数
* @param {HTMLImageElement} imgElement - 图片元素
* @param {string} format - 目标格式
* @param {Object} options - 转换选项
*/
function convertImage(imgElement, format, options = {}) {
try {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// 计算目标尺寸
let targetWidth = options.width || imgElement.naturalWidth;
let targetHeight = options.height || imgElement.naturalHeight;
// 如果保持宽高比且只指定了一个尺寸
if (options.keepAspectRatio) {
const originalRatio = imgElement.naturalWidth / imgElement.naturalHeight;
if (options.width && !options.height) {
targetHeight = Math.round(options.width / originalRatio);
} else if (!options.width && options.height) {
targetWidth = Math.round(options.height * originalRatio);
}
}
// 设置画布尺寸
canvas.width = targetWidth;
canvas.height = targetHeight;
// 绘制图片(带缩放)
ctx.drawImage(imgElement, 0, 0, targetWidth, targetHeight);
// 确定MIME类型
let mimeType;
const quality = 0.9;
switch (format.toLowerCase()) {
case "jpg":
case "jpeg":
mimeType = "image/jpeg";
break;
case "png":
mimeType = "image/png";
break;
case "webp":
mimeType = "image/webp";
break;
case "bmp":
mimeType = "image/png";
addAILine("注意:BMP格式将转换为PNG格式");
break;
default:
mimeType = "image/jpeg";
}
// 转换并下载
canvas.toBlob(
(blob) => {
if (!blob) {
addAILine("图片转换失败,请重试");
return;
}
const url = URL.createObjectURL(blob);
const downloadLink = document.createElement("a");
downloadLink.href = url;
downloadLink.download = `converted-image-${Date.now()}.${format}`;
// 触发下载
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
// 清理URL对象
setTimeout(() => URL.revokeObjectURL(url), 1000);
addAILine(`图片已成功转换为 ${format.toUpperCase()} 格式并开始下载!`);
addAILine(`文件大小: ${(blob.size / 1024).toFixed(1)}KB`);
addAILine(`尺寸: ${targetWidth}x${targetHeight}px`);
},
mimeType,
quality,
);
} catch (error) {
addAILine(`图片转换失败: ${error.message}`);
}
}
/**
* ================================================================================
* 通用工具函数
* ================================================================================
*/
/**
* 创建工具头部
* @param {string} title - 标题
* @param {string} icon - 图标类名
* @param {Function} closeHandler - 关闭处理器
* @returns {HTMLElement} 头部元素
*/
function createToolHeader(title, icon, closeHandler) {
const header = document.createElement("div");
header.className = "tool-header";
const titleEl = document.createElement("div");
titleEl.className = "tool-title";
titleEl.innerHTML = `<i class="${icon}"></i> ${title}`;
const closeBtn = document.createElement("button");
closeBtn.className = "tool-close";
closeBtn.innerHTML =
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
closeBtn.addEventListener("click", closeHandler);
header.appendChild(titleEl);
header.appendChild(closeBtn);
return header;
}
/**
* URL提取函数
* @param {string} text - 文本内容
* @returns {string|null} 提取的URL
*/
function extractURL(text) {
try {
const urlRegex =
/(https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*))/g;
const matches = text.match(urlRegex);
return matches ? matches[0] : null;
} catch (e) {
console.error("URL提取错误:", e);
return null;
}
}
/**
* 显示全屏图片
* @param {string} url - 图片URL
*/
function showFullImage(url) {
const overlay = document.createElement("div");
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
cursor: zoom-out;
`;
const img = document.createElement("img");
img.src = url;
img.style.maxWidth = "90%";
img.style.maxHeight = "90%";
img.style.borderRadius = "10px";
overlay.onclick = () => overlay.remove();
overlay.appendChild(img);
document.body.appendChild(overlay);
}
/**
* 下载所有图片
* @param {Array} images - 图片URL数组
* @param {string} title - 标题
*/
async function downloadAllImages(images, title) {
if (!window.JSZip) {
showAlert("打包下载功能需要JSZip库支持");
return;
}
try {
const zip = new JSZip();
const imgFolder = zip.folder("images");
showAlert("正在打包下载,请稍候...");
const downloadPromises = images.map(async (imgUrl, index) => {
try {
const response = await fetch(imgUrl);
if (!response.ok) throw new Error(`图片${index + 1}下载失败`);
const blob = await response.blob();
imgFolder.file(`image_${index + 1}.jpg`, blob);
} catch (error) {
console.warn(`图片${index + 1}下载失败:`, error);
}
});
await Promise.all(downloadPromises);
const zipBlob = await zip.generateAsync({
type: "blob",
compression: "DEFLATE",
compressionOptions: { level: 6 },
});
const cleanTitle = title.replace(/[<>:"/\\|?*]/g, "");
saveAs(zipBlob, `${cleanTitle}.zip`);
showAlert("打包下载完成!");
} catch (error) {
console.error("打包下载失败:", error);
showAlert("打包下载失败,请重试");
}
}
/**
* 下载视频
* @param {string} url - 视频URL
* @param {string} title - 标题
*/
async function downloadVideo(url, title) {
try {
showAlert("正在下载视频,请稍候...");
const response = await fetch(url);
if (!response.ok) throw new Error(`下载失败: ${response.status}`);
const blob = await response.blob();
const cleanTitle = title.replace(/[<>:"/\\|?*]/g, "");
saveAs(blob, `${cleanTitle}.mp4`);
showAlert("视频下载完成!");
} catch (error) {
console.error("视频下载失败:", error);
showAlert("视频下载失败,请重试");
}
}
/**
* 显示提示信息
* @param {string} message - 提示消息
*/
function showAlert(message) {
const alert = document.createElement("div");
alert.style.cssText = `
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: rgba(30, 41, 59, 0.95);
color: white;
padding: 12px 24px;
border-radius: 25px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
z-index: 9999;
font-size: 14px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
`;
alert.textContent = message;
document.body.appendChild(alert);
setTimeout(() => alert.remove(), 3000);
}
/**
* 保存命令历史
* @param {string} command - 命令内容
*/
function saveToHistory(command) {
if (commandHistoryArray.length === 0 || commandHistoryArray[commandHistoryArray.length - 1] !== command) {
commandHistoryArray.push(command);
if (commandHistoryArray.length > 20) {
commandHistoryArray.shift();
}
localStorage.setItem("commandHistory", JSON.stringify(commandHistoryArray));
}
historyIndex = -1;
}
/**
* 显示命令历史
*/
function showCommandHistory() {
if (commandHistoryArray.length === 0) {
addAILine("暂无命令历史记录");
return;
}
addAILine("命令历史记录:");
commandHistoryArray
.slice()
.reverse()
.forEach((cmd, index) => {
addAILine(`${commandHistoryArray.length - index}. ${cmd}`);
});
}
/**
* ================================================================================
* AI对话功能
* ================================================================================
*/
/**
* 发送AI消息
* @param {string} message - 消息内容
*/
async function sendMessage(message) {
if (!message) return;
const thinkingLine = document.createElement("div");
thinkingLine.className = "line";
const thinkingContent = document.createElement("div");
thinkingContent.className = "line-content ai-output";
thinkingContent.textContent = "藤原: 正在思考中...";
thinkingLine.appendChild(thinkingContent);
editorContent.appendChild(thinkingLine);
editorContent.scrollTop = editorContent.scrollHeight;
try {
const endpoint = `${API_CONFIG.endpoints.ai}?id=${API_CONFIG.id}&key=${API_CONFIG.key}&words=${encodeURIComponent(message)}`;
const response = await fetch(endpoint);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
thinkingLine.remove();
if (data.code === 200 && data.msg) {
const replyLine = document.createElement("div");
replyLine.className = "line";
const replyContent = document.createElement("div");
replyContent.className = "line-content ai-output";
replyContent.textContent = "藤原: ";
replyLine.appendChild(replyContent);
editorContent.appendChild(replyLine);
editorContent.scrollTop = editorContent.scrollHeight;
await typeWriterEffect(replyContent, data.msg);
} else {
addAILine(`AI回复失败: ${data.msg || "未知错误"}`);
}
} catch (error) {
thinkingLine.remove();
addAILine(`AI服务暂时不可用: ${error.message}`);
console.error("AI API错误:", error);
}
}
/**
* ================================================================================
* 网络工具功能
* ================================================================================
*/
/**
* Ping网站
* @param {string} host - 主机地址
*/
async function pingWebsite(host) {
// 显示加载状态
const loadingLine = createLoadingLine("正在测试ping...");
try {
// 构建API请求URL
const params = new URLSearchParams({
id: API_CONFIG.id,
key: API_CONFIG.key,
host: host,
});
const apiUrl = `${API_CONFIG.endpoints.ping}?${params.toString()}`;
// 发送请求
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.code === 200) {
// 成功响应
const loadingContent = loadingLine.querySelector(".line-content");
loadingContent.textContent = "藤原: Ping测试完成!";
// 创建结果行
const resultLine = document.createElement("div");
resultLine.className = "line";
const resultContent = document.createElement("div");
resultContent.className = "line-content ai-output";
resultContent.style.whiteSpace = "pre-wrap";
// 构建结果文本
const resultText = `Ping测试结果:
目标地址: ${data.host}
实际地址: ${data.realhost}
IP地址: ${data.ip}
延迟: ${data.time}毫秒
节点位置: ${data.dy}(${data.dz})`;
resultContent.textContent = resultText;
resultLine.appendChild(resultContent);
editorContent.appendChild(resultLine);
} else {
throw new Error(data.msg || "Ping测试失败");
}
} catch (error) {
console.error("Ping测试失败:", error);
const loadingContent = loadingLine.querySelector(".line-content");
loadingContent.textContent = `藤原: Ping测试失败 - ${error.message}`;
// 显示重试按钮
const retryBtn = document.createElement("button");
retryBtn.className = "tool-btn";
retryBtn.style.marginTop = "10px";
retryBtn.innerHTML = '<i class="ri-refresh-line"></i> 重试';
retryBtn.addEventListener("click", () => pingWebsite(host));
loadingLine.appendChild(retryBtn);
}
editorContent.scrollTop = editorContent.scrollHeight;
}
/**
* 显示系统统计
*/
function showStats() {
addAILine("系统统计信息:");
addAILine(`总解析次数: ${totalParseCount}`);
addAILine(`成功解析次数: ${successParseCount}`);
const rate = totalParseCount > 0 ? Math.round((successParseCount / totalParseCount) * 100) : 0;
addAILine(`成功率: ${rate}%`);
addAILine(`命令历史记录: ${commandHistoryArray.length} 条`);
addAILine(`当前时间: ${new Date().toLocaleString()}`);
addAILine(`浏览器: ${navigator.userAgent.split(" ")[0]}`);
}
/**
* ================================================================================
* 命令处理系统
* ================================================================================
*/
/**
* 处理命令输入
* @param {string} input - 输入命令
*/
async function processCommand(input) {
const command = input.trim().toLowerCase();
const parts = input.trim().split(" ");
const cmd = parts[0].toLowerCase();
const args = parts.slice(1).join(" ");
// 保存到历史记录
saveToHistory(input.trim());
// 添加用户输入行
addUserLine(input);
// 处理不同命令
switch (cmd) {
case "help":
addAILine(helpText);
break;
case "clear":
clearTerminal();
addAILine("终端已清空");
break;
case "history":
showCommandHistory();
break;
case "format":
if (args) {
const code = args;
const type = detectCodeType(code);
createCodeFormatter(code, type, "format");
} else {
addAILine('请提供要格式化的代码,例如: format {"name":"John"}');
}
break;
case "minify":
if (args) {
const code = args;
const type = detectCodeType(code);
createCodeFormatter(code, type, "minify");
} else {
addAILine("请提供要压缩的代码,例如: minify <div><p>Hello</p></div>");
}
break;
case "detect":
if (args) {
const code = args;
const type = detectCodeType(code);
addAILine(`检测到的代码类型: ${type}`);
} else {
addAILine("请提供要检测的代码,例如: detect SELECT * FROM users");
}
break;
case "set":
if (parts[1] === "indent" && parts[2]) {
const size = Number.parseInt(parts[2]);
if (size >= 1 && size <= 8) {
indentSize = size;
addAILine(`缩进大小已设置为 ${size} 个空格`);
} else {
addAILine("缩进大小必须在1-8之间");
}
} else {
addAILine("无效的设置命令,使用: set indent [1-8]");
}
break;
case "video":
if (args) {
const url = extractURL(args) || args;
parseVideo(url);
} else {
addAILine("请提供视频URL,例如: video https://v.qq.com/x/cover/xxx.html");
addAILine("支持的平台: 爱奇艺、腾讯视频、优酷、芒果TV、哔哩哔哩等");
}
break;
case "shortvideo":
if (args) {
const url = extractURL(args) || args;
parseShortVideo(url);
} else {
addAILine("请提供短视频URL,例如: shortvideo https://v.douyin.com/xxx");
addAILine("支持的平台: 抖音、快手、小红书等");
}
break;
case "ai":
if (args) {
await sendMessage(args);
} else {
addAILine("请输入要对话的内容,例如: ai 你好");
}
break;
case "image":
const format = args || "jpg";
const supportedFormats = ["jpg", "jpeg", "png", "webp", "bmp"];
if (supportedFormats.includes(format.toLowerCase())) {
createImageConverter(format.toLowerCase());
addAILine(`图片转换器已启动,目标格式: ${format.toUpperCase()}`);
} else {
addAILine(`不支持的格式: ${format}`);
addAILine(`支持的格式: ${supportedFormats.join(", ")}`);
}
break;
case "stats":
showStats();
break;
case "ping":
if (args) {
await pingWebsite(args);
} else {
addAILine("请提供要ping的网站或IP地址,例如: ping www.example.com");
}
break;
default:
// 检查是否包含URL,如果是则尝试解析
const detectedUrl = extractURL(input);
if (detectedUrl) {
if (
detectedUrl.includes("douyin.com") ||
detectedUrl.includes("kuaishou.com") ||
detectedUrl.includes("xiaohongshu.com")
) {
parseShortVideo(detectedUrl);
} else {
parseVideo(detectedUrl);
}
} else {
addAILine(`未知命令: ${cmd}`);
addAILine('输入 "help" 查看可用命令');
}
break;
}
}
/**
* 设置命令输入
* @param {string} command - 命令内容
*/
function setCommandInput(command) {
userInput.value = command;
userInput.focus();
}
/**
* ================================================================================
* 事件处理系统
* ================================================================================
*/
/**
* 设置输入框事件处理
*/
function setupInputEvents() {
// 输入框事件处理
userInput.addEventListener("keydown", async (e) => {
if (e.key === "Enter") {
e.preventDefault();
const input = userInput.value.trim();
if (input) {
userInput.value = "";
await processCommand(input);
}
} else if (e.key === "ArrowUp") {
e.preventDefault();
if (historyIndex < commandHistoryArray.length - 1) {
historyIndex++;
userInput.value = commandHistoryArray[commandHistoryArray.length - 1 - historyIndex];
}
} else if (e.key === "ArrowDown") {
e.preventDefault();
if (historyIndex > 0) {
historyIndex--;
userInput.value = commandHistoryArray[commandHistoryArray.length - 1 - historyIndex];
} else if (historyIndex === 0) {
historyIndex = -1;
userInput.value = "";
}
}
});
// 粘贴处理
userInput.addEventListener("paste", (e) => {
setTimeout(() => {
const pastedText = userInput.value;
const url = extractURL(pastedText);
if (url && url === pastedText.trim()) {
// 如果粘贴的是纯URL,自动识别类型
setTimeout(() => {
userInput.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter" }));
}, 100);
}
}, 10);
});
}
/**
* 设置全局键盘快捷键
*/
function setupGlobalKeyboardShortcuts() {
document.addEventListener("keydown", (e) => {
// Ctrl/Cmd + K 清空终端
if ((e.ctrlKey || e.metaKey) && e.key === "k") {
e.preventDefault();
clearTerminal();
addAILine("终端已清空 (快捷键: Ctrl/Cmd+K)");
}
// Ctrl/Cmd + L 聚焦输入框
if ((e.ctrlKey || e.metaKey) && e.key === "l") {
e.preventDefault();
userInput.focus();
userInput.select();
}
// ESC 键清空当前输入
if (e.key === "Escape") {
userInput.value = "";
userInput.focus();
}
// Ctrl/Cmd + / 显示帮助
if ((e.ctrlKey || e.metaKey) && e.key === "/") {
e.preventDefault();
processCommand("help");
}
});
}
/**
* 设置页面焦点管理
*/
function setupFocusManagement() {
// 页面可见性变化时重新聚焦
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
setTimeout(() => userInput.focus(), 100);
}
});
// 点击终端区域时聚焦输入框
editorContent.addEventListener("click", () => {
userInput.focus();
});
}
/**
* ================================================================================
* 主题切换功能
* ================================================================================
*/
/**
* 初始化主题切换
*/
function initializeThemeToggle() {
if (localStorage.getItem("theme") === "light") {
const checkbox = document.getElementById("checkbox");
if (checkbox) checkbox.checked = true;
}
const themeToggle = document.querySelector('.theme-switch input[type="checkbox"]');
if (themeToggle) {
themeToggle.addEventListener("change", switchTheme, false);
}
}
/**
* 切换主题
* @param {Event} e - 事件对象
*/
function switchTheme(e) {
if (e.target.checked) {
document.documentElement.setAttribute("data-theme", "light");
localStorage.setItem("theme", "light");
} else {
document.documentElement.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
}
}
/**
* ================================================================================
* 用户菜单功能
* ================================================================================
*/
/**
* 切换用户菜单
*/
function usertoggle() {
const linkmenu = document.getElementById("linkmenu");
const container = document.getElementById("linkmenu-container");
if (linkmenu && container) {
if (linkmenu.classList.contains("show")) {
linkmenu.classList.remove("show");
container.style.display = "none";
} else {
linkmenu.classList.add("show");
container.style.display = "block";
}
}
}
/**
* ================================================================================
* 性能监控系统
* ================================================================================
*/
/**
* 初始化性能监控
*/
function initializePerformanceMonitoring() {
// 记录页面加载开始时间
const pageLoadStart = performance.now();
let pageLoadedTime = null;
let loadTime = null;
// 页面完全加载后计算加载时间
window.addEventListener("load", () => {
const pageLoadEnd = performance.now();
loadTime = (pageLoadEnd - pageLoadStart) / 1000; // 转换为秒
pageLoadedTime = new Date();
// 更新性能信息显示
function updatePerformanceInfo() {
if (!pageLoadedTime) return;
const now = new Date();
const uptime = Math.floor((now - pageLoadedTime) / 1000);
const hours = Math.floor(uptime / 3600).toString().padStart(2, '0');
const minutes = Math.floor((uptime % 3600) / 60).toString().padStart(2, '0');
const seconds = (uptime % 60).toString().padStart(2, '0');
const performanceInfo = document.getElementById("performance-info");
if (performanceInfo) {
const infoText = `| 加载耗时: ${loadTime.toFixed(3)}秒 | 运行时长: ${hours}时${minutes}分${seconds}秒`;
performanceInfo.textContent = infoText;
}
}
// 初始更新
updatePerformanceInfo();
// 每秒更新一次运行时间
setInterval(updatePerformanceInfo, 1000);
});
}
/**
* ================================================================================
* 自定义弹窗系统
* ================================================================================
*/
/**
* 初始化自定义弹窗样式
*/
function initializeCustomAlert() {
const alertStyle = document.createElement("style");
alertStyle.textContent = `
.custom-alert {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 320px;
padding: 25px;
border-radius: 16px;
z-index: 99999;
text-align: center;
animation: fadeIn 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
background: rgba(var(--lighterRGB), 0.95);
backdrop-filter: blur(10px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
border: 1px solid rgba(var(--accentRGB), 0.3);
overflow: hidden;
}
.custom-alert p {
margin: 0 0 20px;
color: var(--dark);
font-family: var(--fontBody);
font-size: 16px;
line-height: 1.6;
padding: 0 10px;
}
.custom-alert .alert-icon {
font-size: 48px;
margin-bottom: 15px;
color: var(--accent);
}
.custom-alert .alert-buttons {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 10px;
}
.custom-alert button {
flex: 1;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-family: var(--fontBody);
font-size: 14px;
font-weight: 600;
transition: all 0.25s;
border: none;
outline: none;
}
.custom-alert .confirm-btn {
background: rgba(var(--accentRGB), 0.8);
color: white;
}
.custom-alert .confirm-btn:hover {
background: rgba(var(--supportRGB), 0.8);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translate(-50%, -60%) scale(0.95);
}
to {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
@keyframes fadeOut {
from {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
to {
opacity: 0;
transform: translate(-50%, -40%) scale(0.95);
}
}
`;
document.head.appendChild(alertStyle);
}
/**
* 显示自定义提示
* @param {string} message - 提示消息
* @param {Object} options - 选项配置
* @returns {Object} 控制对象
*/
function showCustomAlert(message, options = {}) {
// 移除现有的提示
const existingAlert = document.querySelector(".custom-alert");
if (existingAlert) existingAlert.remove();
// 创建弹窗元素
const alertBox = document.createElement("div");
alertBox.className = "custom-alert";
// 添加图标
const icon = document.createElement("div");
icon.className = "alert-icon";
icon.innerHTML = options.icon || '<i class="ri-information-line"></i>';
alertBox.appendChild(icon);
// 添加消息内容
const messageEl = document.createElement("p");
messageEl.textContent = message;
alertBox.appendChild(messageEl);
// 添加按钮容器
const buttonsContainer = document.createElement("div");
buttonsContainer.className = "alert-buttons";
// 添加确认按钮
const confirmBtn = document.createElement("button");
confirmBtn.className = "confirm-btn";
confirmBtn.textContent = options.confirmText || "我知道了";
confirmBtn.addEventListener("click", () => {
alertBox.style.animation = "fadeOut 0.3s ease-out forwards";
setTimeout(() => alertBox.remove(), 300);
if (options.onConfirm) options.onConfirm();
});
buttonsContainer.appendChild(confirmBtn);
alertBox.appendChild(buttonsContainer);
// 添加到页面
document.body.appendChild(alertBox);
// 自动消失时间
const autoCloseTime = options.autoClose || 5000;
if (autoCloseTime > 0) {
setTimeout(() => {
if (alertBox.parentNode) {
alertBox.style.animation = "fadeOut 0.3s ease-out forwards";
setTimeout(() => alertBox.remove(), 300);
}
}, autoCloseTime);
}
return {
close: () => {
alertBox.style.animation = "fadeOut 0.3s ease-out forwards";
setTimeout(() => alertBox.remove(), 300);
},
};
}
/**
* ================================================================================
* 安全保护功能
* ================================================================================
*/
/**
* 初始化安全保护
*/
function initializeSecurity() {
// 禁止右键菜单
document.addEventListener("contextmenu", (e) => {
e.preventDefault();
showCustomAlert("为了保护内容安全,右键菜单功能已禁用", {
icon: '<i class="ri-forbid-line"></i>',
confirmText: "好的",
autoClose: 3000,
});
});
// 禁止快捷键组合
const blockedShortcuts = [
{
keys: ["F12"],
message: "开发者工具功能已禁用",
icon: '<i class="ri-tools-line"></i>',
},
{
keys: ["u", "U"],
ctrl: true,
message: "查看源代码功能已禁用",
icon: '<i class="ri-code-view"></i>',
},
{
keys: ["i", "I", "j", "J", "c", "C"],
ctrl: true,
shift: true,
message: "开发者工具功能已禁用",
icon: '<i class="ri-terminal-box-line"></i>',
},
];
document.addEventListener("keydown", (e) => {
for (const shortcut of blockedShortcuts) {
const keyMatch = shortcut.keys.includes(e.key);
const ctrlMatch = !shortcut.ctrl || (shortcut.ctrl && e.ctrlKey);
const shiftMatch = !shortcut.shift || (shortcut.shift && e.shiftKey);
if (keyMatch && ctrlMatch && shiftMatch) {
e.preventDefault();
e.stopPropagation();
showCustomAlert(shortcut.message, {
icon: shortcut.icon,
confirmText: "明白了",
autoClose: 3000,
});
return;
}
}
});
}
/**
* ================================================================================
* 每日一言功能
* ================================================================================
*/
/**
* 获取每日一言
*/
async function fetchDailyQuote() {
try {
const response = await fetch("https://api.nnxv.cn/api/yiyan.php");
const data = await response.json();
const quoteContent = document.querySelector(".quote-content");
const quoteFrom = document.querySelector(".quote-from");
if (quoteContent && quoteFrom) {
quoteContent.textContent = data.content;
quoteFrom.textContent = `—— ${data.from}《${data.typeName}》`;
}
} catch (error) {
console.error("获取每日一言失败:", error);
const quoteContent = document.querySelector(".quote-content");
if (quoteContent) {
quoteContent.textContent = "获取每日一言失败,请刷新重试";
}
}
}
/**
* ================================================================================
* 垂直轮播系统
* ================================================================================
*/
// 垂直轮播相关变量
let currentVerticalPage = 0;
let verticalAutoScrollInterval;
let isVerticalCarouselInitialized = false;
let isVerticalScrollPaused = false;
let verticalScrollPauseTimeout = null;
// 文章轮播相关变量
let currentArticle = 0;
let articleInterval;
let articles = [];
let controlBtns = [];
// 配置选项
const VERTICAL_CAROUSEL_CONFIG = {
autoScrollInterval: 8000,
swipeThreshold: 50,
animationDuration: 600,
enableAutoScroll: true,
enableTouch: true,
pauseOnHover: true,
};
const ARTICLE_CAROUSEL_CONFIG = {
autoScrollInterval: 5000,
verticalScrollPauseDuration: 10000,
};
/**
* 获取DOM元素
* @returns {Object} DOM元素对象
*/
function getDOMElements() {
articles = document.querySelectorAll('.article-slide');
controlBtns = document.querySelectorAll('.article-control-btn');
return {
verticalPages: document.querySelectorAll(".vertical-carousel-page"),
verticalButtons: document.querySelectorAll(".vertical-carousel-btn"),
verticalContainer: document.querySelector(".vertical-carousel-container"),
articleContainer: document.querySelector('.single-article-container')
};
}
/**
* 初始化轮播系统
*/
function initializeCarousels() {
const {
verticalPages,
verticalButtons,
verticalContainer,
articleContainer
} = getDOMElements();
// 检查必要的DOM元素是否存在
if (!verticalPages.length || !verticalButtons.length || !verticalContainer) {
console.error("无法找到必要的DOM元素");
return;
}
// 初始化垂直轮播
initializeVerticalCarousel({
pages: verticalPages,
buttons: verticalButtons,
container: verticalContainer
});
// 初始化文章轮播
if (articles.length && controlBtns.length && articleContainer) {
initArticleCarousel({
articles: articles,
controlBtns: controlBtns,
container: articleContainer
});
} else {
console.warn("文章轮播元素未找到");
}
}
/**
* 初始化垂直轮播
* @param {Object} options - 配置选项
*/
function initializeVerticalCarousel({pages, buttons, container}) {
console.log("🎠 初始化垂直轮播系统...");
// 设置按钮点击事件
buttons.forEach((button, index) => {
button.addEventListener('click', function(e) {
e.preventDefault();
const pageIndex = parseInt(this.getAttribute("data-page")) || index;
const direction = pageIndex > currentVerticalPage ? "next" : "prev";
goToVerticalPage(pageIndex, direction, pages, buttons);
});
});
// 设置触摸事件
if (VERTICAL_CAROUSEL_CONFIG.enableTouch) {
setupVerticalCarouselTouch(container, pages, buttons);
}
// 初始化第一页
goToVerticalPage(0, 'auto', pages, buttons);
// 开始自动轮播
if (VERTICAL_CAROUSEL_CONFIG.enableAutoScroll) {
startVerticalAutoScroll(pages);
}
console.log("✅ 垂直轮播系统初始化完成");
}
/**
* 跳转到指定垂直页面
* @param {number} index - 页面索引
* @param {string} direction - 方向
* @param {NodeList} pages - 页面元素列表
* @param {NodeList} buttons - 按钮元素列表
*/
function goToVerticalPage(index, direction, pages, buttons) {
const totalPages = pages.length;
if (index < 0) index = totalPages - 1;
if (index >= totalPages) index = 0;
// 更新页面状态
pages.forEach((page, i) => {
page.classList.remove("active", "prev", "next");
if (i === index) {
page.classList.add("active");
} else if (i < index) {
page.classList.add("prev");
} else {
page.classList.add("next");
}
});
// 更新按钮状态
buttons.forEach((btn, i) => {
btn.classList.toggle("active", i === index);
});
currentVerticalPage = index;
}
/**
* 设置垂直轮播触摸事件
* @param {HTMLElement} container - 容器元素
* @param {NodeList} pages - 页面元素列表
* @param {NodeList} buttons - 按钮元素列表
*/
function setupVerticalCarouselTouch(container, pages, buttons) {
let touchStartY = 0;
container.addEventListener('touchstart', (e) => {
touchStartY = e.touches[0].clientY;
}, {passive: true});
container.addEventListener('touchend', (e) => {
const touchEndY = e.changedTouches[0].clientY;
const deltaY = touchEndY - touchStartY;
if (Math.abs(deltaY) > VERTICAL_CAROUSEL_CONFIG.swipeThreshold) {
if (deltaY > 0) {
goToVerticalPage(currentVerticalPage - 1, 'prev', pages, buttons);
} else {
goToVerticalPage(currentVerticalPage + 1, 'next', pages, buttons);
}
}
}, {passive: true});
}
/**
* 开始垂直自动轮播
* @param {NodeList} pages - 页面元素列表
*/
function startVerticalAutoScroll(pages) {
clearInterval(verticalAutoScrollInterval);
verticalAutoScrollInterval = setInterval(() => {
const nextPage = (currentVerticalPage + 1) % pages.length;
goToVerticalPage(nextPage, "next", pages, buttons);
}, VERTICAL_CAROUSEL_CONFIG.autoScrollInterval);
}
/**
* 初始化文章轮播
* @param {Object} options - 配置选项
*/
function initArticleCarousel({articles, controlBtns, container}) {
console.log("📰 初始化文章轮播系统...");
// 初始显示
updateArticleDisplay();
// 开始自动轮播
startArticleAutoScroll();
// 鼠标悬停控制
container.addEventListener('mouseenter', pauseArticleAutoScroll);
container.addEventListener('mouseleave', resumeArticleAutoScroll);
// 控制点点击事件
controlBtns.forEach(btn => {
btn.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
goToArticle(index);
});
});
console.log("✅ 文章轮播系统初始化完成");
}
/**
* 更新文章显示
*/
function updateArticleDisplay() {
articles.forEach((article, index) => {
article.classList.remove('active', 'prev', 'next');
if (index === currentArticle) {
article.classList.add('active');
} else if (index < currentArticle) {
article.classList.add('prev');
} else {
article.classList.add('next');
}
});
controlBtns.forEach((btn, index) => {
btn.classList.toggle('active', index === currentArticle);
});
}
/**
* 跳转到指定文章
* @param {number} index - 文章索引
*/
function goToArticle(index) {
currentArticle = index;
if (currentArticle >= articles.length) currentArticle = 0;
if (currentArticle < 0) currentArticle = articles.length - 1;
updateArticleDisplay();
pauseVerticalScrollForDuration();
}
/**
* 下一篇文章
*/
function nextArticle() {
goToArticle(currentArticle + 1);
}
/**
* 上一篇文章
*/
function prevArticle() {
goToArticle(currentArticle - 1);
}
/**
* 开始文章自动轮播
*/
function startArticleAutoScroll() {
clearInterval(articleInterval);
articleInterval = setInterval(nextArticle, ARTICLE_CAROUSEL_CONFIG.autoScrollInterval);
}
/**
* 暂停文章自动轮播
*/
function pauseArticleAutoScroll() {
clearInterval(articleInterval);
}
/**
* 恢复文章自动轮播
*/
function resumeArticleAutoScroll() {
startArticleAutoScroll();
}
/**
* 暂停垂直滚动一段时间
*/
function pauseVerticalScrollForDuration() {
if (!VERTICAL_CAROUSEL_CONFIG.enableAutoScroll || isVerticalScrollPaused) return;
isVerticalScrollPaused = true;
clearInterval(verticalAutoScrollInterval);
if (verticalScrollPauseTimeout) {
clearTimeout(verticalScrollPauseTimeout);
}
verticalScrollPauseTimeout = setTimeout(() => {
isVerticalScrollPaused = false;
const pages = document.querySelectorAll(".vertical-carousel-page");
startVerticalAutoScroll(pages);
}, ARTICLE_CAROUSEL_CONFIG.verticalScrollPauseDuration);
}
/**
* ================================================================================
* jQuery功能初始化
* ================================================================================
*/
/**
* 初始化jQuery功能
*/
function initializeJQueryFeatures() {
$(document).ready(() => {
$("div.topic-description descript:empty").hide();
$("span.topic-desc:empty").hide();
$(".pagination").html($(".pagination").html().split(" ").join(""));
$("#ucpmenu p").each(function () {
$(this).html(
$(this)
.html()
.replace(/· <a href="(.+?)" style="display: none;">(.+?)<\/a><br>/gi, ""),
);
});
$(".pformleft:contains('Date of Birth')").parent().hide();
$(".pformstrip:contains('Your personal profile')").hide();
const newMsg = Number.parseInt("<!-- |new_msg| -->") != Number.NaN ? Number.parseInt("<!-- |new_msg| -->") : 0;
if (newMsg > 0) {
$(".nonewmsg").addClass("newmsg");
} else {
$(".nonewmsg").removeClass("newmsg");
}
const newAlert =
Number.parseInt("<!-- |new_alerts| -->") != Number.NaN ? Number.parseInt("<!-- |new_alerts| -->") : 0;
if (newAlert > 0) {
$(".nonewnotif").addClass("newnotif");
} else {
$(".nonewnotif").removeClass("newnotif");
}
$("#recent-topics").appendTo("#recent-topics-clip");
});
}
/**
* ================================================================================
* 主初始化函数
* ================================================================================
*/
/**
* 初始化终端系统
*/
async function initializeTerminalSystem() {
console.log("🚀 开始初始化终端系统...");
// 基础初始化
initializeYear();
updateParseStats();
// 事件处理初始化
setupInputEvents();
setupGlobalKeyboardShortcuts();
setupFocusManagement();
// 主题和UI初始化
initializeThemeToggle();
initializeCustomAlert();
// 性能监控初始化
initializePerformanceMonitoring();
// 安全保护初始化
initializeSecurity();
// 每日一言初始化
fetchDailyQuote();
// jQuery功能初始化
if (typeof $ !== "undefined") {
initializeJQueryFeatures();
}
// 聚焦到输入框
if (userInput) {
userInput.focus();
}
// 显示欢迎信息
await addAILine("(。・ω・。)ノ♡ 欢迎来到藤原的数字空间");
await addAILine("✨ 这里是一个融合创意与技术的终端世界");
await addAILine("");
await addAILine("💡 你可以:");
await addAILine("- 输入 'help' 查看所有命令");
await addAILine("- 直接粘贴视频/图片链接进行解析");
await addAILine("- 使用快捷键提高效率");
await addAILine("");
await addAILine(`⏰ 当前时间: ${new Date().toLocaleString()}`);
await addAILine("🌙 系统主题: " + (localStorage.getItem("theme") === "light" ? "明亮模式" : "暗黑模式"));
await addAILine("");
await addAILine("请开始你的探索之旅吧~");
console.log("✅ 终端系统初始化完成");
}
// Set current year for copyright
document.getElementById('year').textContent = new Date().getFullYear();
// 2秒后隐藏欢迎消息和TENG YUAN标题,并显示个人信息卡片
setTimeout(function() {
document.getElementById('welcome-message').style.display = 'none';
document.getElementById('tengyuan-title').style.display = 'none';
const profileCard = document.getElementById('profile-card');
profileCard.style.display = 'flex'; // Make it visible
// Add a class to bannerInformation to adjust its padding
document.querySelector('.bannerInformation').classList.add('profile-active');
profileCard.style.opacity = '0';
profileCard.style.transform = 'translateY(20px)';
setTimeout(() => {
profileCard.style.opacity = '1';
profileCard.style.transform = 'translateY(0)';
profileCard.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
}, 50);
}, 2000);
/**
* ================================
* Social Link Interaction Functions
* ================================
*/
/**
* Placeholder for a toast notification function
*/
function showToast(message) {
console.log("Toast:", message);
// In a real application, you would implement a visual toast notification here.
// For example, by creating a div, adding it to the body, and styling it.
}
/**
* Show WeChat modal
*/
function showWeChatModal() {
showModal('wechat-modal');
}
/**
* Show QQ modal
*/
function showQQModal() {
showModal('qq-modal');
}
/**
* Show modal
* @param {string} modalId - Modal ID
*/
function showModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.add('show');
document.body.style.overflow = 'hidden';
// Add click outside to close functionality
modal.addEventListener('click', function (e) {
if (e.target === modal) {
closeModal(modalId);
}
});
}
}
/**
* Close modal
* @param {string} modalId - Modal ID
*/
function closeModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.remove('show');
document.body.style.overflow = 'auto';
}
}
/**
* Copy email address
*/
function copyEmail() {
const email = '2083737075@qq.com';
if (navigator.clipboard) {
navigator.clipboard
.writeText(email)
.then(() => {
showToast('邮箱地址已复制到剪贴板!');
closeModal('wechat-modal');
})
.catch(() => {
fallbackCopyEmail(email);
});
} else {
fallbackCopyEmail(email);
}
}
/**
* Fallback copy method
* @param {string} text - Text to copy
*/
function fallbackCopyEmail(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
showToast('邮箱地址已复制到剪贴板!');
closeModal('wechat-modal');
} catch (err) {
showToast('复制失败,请手动复制:' + text);
}
document.body.removeChild(textArea);
}
/**
* Open QQ chat
*/
function openQQ() {
const qqUrl = 'tencent://message/?uin=2083737075&Site=&Menu=yes';
const webQQUrl = 'https://wpa.qq.com/msgrd?v=3&uin=2083737075&site=qq&menu=yes';
// Attempt to open QQ client
window.open(qqUrl, '_blank');
// Offer web version option after a delay
setTimeout(() => {
if (confirm('如果QQ客户端未打开,是否使用网页版QQ?')) {
window.open(webQQUrl, '_blank');
}
}, 2000);
closeModal('qq-modal');
}
/**
* ================================================================================
* 页面加载事件处理
* ================================================================================
*/
// 页面DOM加载完成后初始化
document.addEventListener("DOMContentLoaded", async () => {
await initializeTerminalSystem();
// 检查是否存在轮播容器并初始化
const container = document.querySelector(".vertical-carousel-container");
if (container) {
setTimeout(() => {
initializeCarousels();
}, 100);
}
});
// 防止页面刷新时丢失焦点
window.addEventListener("beforeunload", () => {
localStorage.setItem("commandHistory", JSON.stringify(commandHistoryArray));
});
//躲猫猫
var randomNum = function(minNum, maxNum) {
switch(arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1, 10);
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
default:
return 0;
}
}
//躲猫猫的「猫猫」形象出自游戏「Don't catch Cats」(https://apps.apple.com/app/dont-catch-cats/id1375311035)。
var duoMaomao = function() {
var maomao = document.getElementById('maomao');
maomao.style.bottom = randomNum(5, 80) + 'vh';
}
/**
* ================================================================================
* 全局API暴露
* ================================================================================
*/
// 全局暴露主要功能
if (typeof window !== "undefined") {
window.usertoggle = usertoggle;
window.randomNum = randomNum;
window.duoMaomao = duoMaomao;
window.showFullImage = showFullImage;
window.downloadVideo = downloadVideo;
window.downloadAllImages = downloadAllImages;
}
console.log("🎯 藤原终端系统加载完成");
</script>
</body>
</html>
index.html