个人主页edit icon

作者:
藤原
Fork(复制)
下载
嵌入
设置
BUG反馈
index.html
style.css
index.js
现在支持上传本地图片了!
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>藤原的个人终端</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap">
    <style>
:root {
    --editor-bg: #1e1e1e;
    --editor-secondary-bg: #252526;
    --line-color: #858585;
    --text-color: #d4d4d4;
    --keyword-color: #569cd6;
    --string-color: #ce9178;
    --comment-color: #6a9955;
    --number-color: #b5cea8;
    --function-color: #dcdcaa;
    --font-family: 'JetBrains Mono', 'Consolas', 'Monaco', monospace;
    --header-bg: #2d2d2d;
    --window-btn-close: #ff5f56;
    --window-btn-min: #ffbd2e;
    --window-btn-max: #27c93f;
    --ai-output-color: #4ec9b0;
    --user-input-color: #d7ba7d;
    --video-bg: #000000;
    --accent-color: #0a84ff;
    --accent-hover: #409eff;
    --box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    --border-radius: 8px;
    --calendar-today-bg: rgba(10, 132, 255, 0.3);
    --calendar-selected-bg: var(--accent-color);
    --weather-temp-high: #ff7e67;
    --weather-temp-low: #70c1ff;
    --birthday-color: #ff4081;
    --birthday-bg: rgba(255, 64, 129, 0.15);
}

[data-theme="light"] {
    --editor-bg: #f5f5f5;
    --editor-secondary-bg: #ebebeb;
    --line-color: #858585;
    --text-color: #333333;
    --keyword-color: #0000ff;
    --string-color: #a31515;
    --comment-color: #008000;
    --number-color: #098658;
    --function-color: #795e26;
    --header-bg: #e5e5e5;
    --ai-output-color: #098658;
    --user-input-color: #0000ff;
    --video-bg: #f0f0f0;
    --accent-color: #0a84ff;
    --accent-hover: #409eff;
    --box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
    --calendar-today-bg: rgba(10, 132, 255, 0.2);
    --calendar-selected-bg: var(--accent-color);
    --weather-temp-high: #ff5a3d;
    --weather-temp-low: #4a9eff;
    --birthday-color: #ff4081;
    --birthday-bg: rgba(255, 64, 129, 0.1);
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-color: var(--editor-bg);
    color: var(--text-color);
    font-family: var(--font-family);
    line-height: 1.6;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px;
    transition: background-color 0.3s, color 0.3s;
    background-image: 
        radial-gradient(circle at 10% 20%, rgba(100, 100, 255, 0.03) 0%, transparent 20%),
        radial-gradient(circle at 90% 80%, rgba(100, 255, 100, 0.03) 0%, transparent 20%);
    background-attachment: fixed;
}

.theme-switch {
    position: fixed;
    top: 20px;
    right: 20px;
    background: var(--header-bg);
    border-radius: 30px;
    padding: 8px 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    z-index: 100;
    box-shadow: var(--box-shadow);
    transition: all 0.3s ease;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.theme-switch:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
}

.theme-icon {
    width: 18px;
    height: 18px;
    transition: transform 0.3s ease;
}

.theme-switch:hover .theme-icon {
    transform: rotate(30deg);
}

.editor {
    width: 100%;
    max-width: 900px;
    margin: 20px auto;
    background: var(--editor-bg);
    border-radius: var(--border-radius);
    box-shadow: var(--box-shadow);
    transition: all 0.3s;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.editor:hover {
    transform: translateY(-5px);
    box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4);
}

.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;
    transition: background-color 0.3s;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.window-btn {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    transition: all 0.2s;
    position: relative;
    cursor: pointer;
}

.window-btn:hover::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 6px;
    height: 6px;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 50%;
}

.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;
    transition: color 0.3s;
}

.editor-content {
    padding: 20px;
    counter-reset: line;
    font-size: 14px;
    overflow-x: auto;
    max-height: 70vh;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--line-color) transparent;
}

.editor-content::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

.editor-content::-webkit-scrollbar-track {
    background: transparent;
}

.editor-content::-webkit-scrollbar-thumb {
    background-color: var(--line-color);
    border-radius: 4px;
}

.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;
    transition: color 0.3s;
    opacity: 0.7;
}

.line-content {
    padding-left: 3em;
    width: 100%;
}

.indent { margin-left: 2em; }
.indent-2 { margin-left: 4em; }

.keyword { color: var(--keyword-color); }
.string { color: var(--string-color); }
.comment { color: var(--comment-color); }
.number { color: var(--number-color); }
.function { color: var(--function-color); }

.ai-output { color: var(--ai-output-color); }
.user-input { color: var(--user-input-color); }

a {
    color: var(--accent-color);
    text-decoration: none;
    transition: all 0.2s;
    position: relative;
}

a:hover {
    color: var(--accent-hover);
}

a::after {
    content: '';
    position: absolute;
    width: 0;
    height: 1px;
    bottom: 0;
    left: 0;
    background-color: var(--accent-hover);
    transition: width 0.3s ease;
}

a:hover::after {
    width: 100%;
}

.cursor {
    display: inline-block;
    width: 2px;
    height: 1.2em;
    background: var(--text-color);
    margin-left: 2px;
    animation: blink 1s step-end infinite;
    vertical-align: middle;
    transition: background 0.3s;
}

@keyframes blink {
    50% { opacity: 0; }
}

.input-line {
    display: flex;
    align-items: center;
    margin-top: 10px;
    background: var(--editor-secondary-bg);
    padding: 8px 10px;
    border-radius: 4px;
    transition: all 0.3s;
}

.input-line:focus-within {
    box-shadow: 0 0 0 2px var(--accent-color);
}

.input-line::before {
    content: ">";
    color: var(--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;
}

.video-container {
    margin-top: 20px;
    width: 100%;
    background: var(--video-bg);
    border-radius: var(--border-radius);
    overflow: hidden;
    transition: all 0.3s;
    box-shadow: var(--box-shadow);
}

.video-container video {
    width: 100%;
    display: block;
    border-radius: var(--border-radius) var(--border-radius) 0 0;
}

.video-info {
    padding: 15px;
    font-size: 0.9em;
    color: var(--text-color);
    background: var(--editor-secondary-bg);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.video-commands {
    margin-top: 10px;
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.video-command {
    background: var(--header-bg);
    padding: 8px 16px;
    border-radius: 20px;
    cursor: pointer;
    font-size: 0.85em;
    transition: all 0.2s;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.video-command:hover {
    background: var(--accent-color);
    color: white;
    transform: translateY(-2px);
}

.image-converter {
    margin-top: 20px;
    width: 100%;
    background: var(--editor-secondary-bg);
    border-radius: var(--border-radius);
    padding: 20px;
    transition: all 0.3s;
    box-shadow: var(--box-shadow);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.image-preview-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 20px;
}

.image-preview {
    max-width: 100%;
    max-height: 300px;
    margin-bottom: 15px;
    border-radius: var(--border-radius);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
    transition: all 0.3s;
}

.image-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    margin-top: 15px;
    background: var(--editor-bg);
    padding: 15px;
    border-radius: var(--border-radius);
}

.image-control {
    display: flex;
    flex-direction: column;
    min-width: 120px;
    flex: 1;
}

.image-control label {
    font-size: 0.85em;
    margin-bottom: 8px;
    color: var(--line-color);
}

.image-control input, 
.image-control select {
    background: var(--editor-secondary-bg);
    border: 1px solid var(--line-color);
    color: var(--text-color);
    padding: 8px 12px;
    border-radius: 4px;
    font-family: var(--font-family);
    transition: all 0.2s;
}

.image-control input:focus, 
.image-control select:focus {
    border-color: var(--accent-color);
    outline: none;
    box-shadow: 0 0 0 2px rgba(10, 132, 255, 0.3);
}

.image-control input[type="range"] {
    -webkit-appearance: none;
    height: 6px;
    background: var(--editor-bg);
    border-radius: 3px;
    padding: 0;
}

.image-control input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 16px;
    height: 16px;
    background: var(--accent-color);
    border-radius: 50%;
    cursor: pointer;
}

.image-actions {
    display: flex;
    gap: 12px;
    margin-top: 20px;
    justify-content: center;
}

.image-btn {
    background: var(--accent-color);
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 20px;
    cursor: pointer;
    font-family: var(--font-family);
    font-weight: bold;
    transition: all 0.2s;
    min-width: 120px;
    text-align: center;
}

.image-btn:hover {
    background: var(--accent-hover);
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(10, 132, 255, 0.3);
}

.image-download-link {
    display: none;
}

.tooltip {
    position: relative;
}

.tooltip:hover::before {
    content: attr(data-tooltip);
    position: absolute;
    bottom: 120%;
    left: 50%;
    transform: translateX(-50%);
    background: var(--header-bg);
    color: var(--text-color);
    padding: 5px 10px;
    border-radius: 4px;
    font-size: 0.8em;
    white-space: nowrap;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
    z-index: 100;
}

/* 打字机动画 */
@keyframes typing {
    from { width: 0 }
    to { width: 100% }
}

.typing-animation {
    overflow: hidden;
    white-space: nowrap;
    animation: typing 1s steps(30, end);
}

/* 命令面板 */
.command-palette {
    position: absolute;
    top: 50px;
    left: 50%;
    transform: translateX(-50%);
    width: 90%;
    max-width: 600px;
    background: var(--editor-secondary-bg);
    border-radius: var(--border-radius);
    box-shadow: var(--box-shadow);
    padding: 15px;
    z-index: 1000;
    display: none;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.command-header {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
}

.command-search {
    flex: 1;
    background: var(--editor-bg);
    border: 1px solid var(--line-color);
    color: var(--text-color);
    padding: 8px 12px;
    border-radius: 4px;
    font-family: var(--font-family);
}

.command-list {
    max-height: 300px;
    overflow-y: auto;
}

.command-item {
    padding: 8px 12px;
    cursor: pointer;
    border-radius: 4px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.command-item:hover {
    background: var(--editor-bg);
}

.command-item.selected {
    background: var(--accent-color);
    color: white;
}

.command-icon {
    width: 16px;
    height: 16px;
}

.command-shortcut {
    margin-left: auto;
    color: var(--line-color);
    font-size: 0.8em;
}

/* 命令历史记录样式 */
.command-history {
    margin-top: 20px;
    background: var(--editor-secondary-bg);
    border-radius: var(--border-radius);
    padding: 15px;
    display: none;
}

.history-title {
    font-size: 0.9em;
    margin-bottom: 10px;
    color: var(--accent-color);
}

.history-list {
    max-height: 200px;
    overflow-y: auto;
}

.history-item {
    padding: 5px 0;
    cursor: pointer;
    display: flex;
    align-items: center;
}

.history-item:hover {
    color: var(--accent-color);
}

.history-item::before {
    content: ">";
    margin-right: 10px;
    color: var(--line-color);
}

/* 日历组件样式 */
.calendar-container {
    margin-top: 20px;
    background: var(--editor-secondary-bg);
    border-radius: var(--border-radius);
    padding: 20px;
    box-shadow: var(--box-shadow);
    border: 1px solid rgba(255, 255, 255, 0.1);
    transition: all 0.3s;
}

.calendar-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

.calendar-title {
    font-size: 1.2em;
    font-weight: bold;
}

.calendar-nav {
    display: flex;
    gap: 10px;
}

.calendar-btn {
    background: var(--editor-bg);
    border: none;
    color: var(--text-color);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s;
}

.calendar-btn:hover {
    background: var(--accent-color);
    color: white;
}

.calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 5px;
}

.calendar-weekday {
    text-align: center;
    font-size: 0.8em;
    color: var(--line-color);
    padding: 5px 0;
    font-weight: bold;
}

.calendar-day {
    text-align: center;
    padding: 8px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.2s;
    position: relative;
}

.calendar-day:hover {
    background: var(--editor-bg);
}

.calendar-day.today {
    background: var(--calendar-today-bg);
    font-weight: bold;
}

.calendar-day.selected {
    background: var(--calendar-selected-bg);
    color: white;
}

.calendar-day.other-month {
    color: var(--line-color);
    opacity: 0.5;
}

/* 生日标记样式 */
.calendar-day.birthday {
    color: var(--birthday-color);
    font-weight: bold;
}

.calendar-day.birthday::after {
    content: '🎂';
    font-size: 0.7em;
    position: absolute;
    bottom: 2px;
    right: 2px;
}

.calendar-day.birthday:hover {
    background: var(--birthday-bg);
}

.calendar-events {
    margin-top: 15px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    padding-top: 15px;
}

.calendar-events-title {
    font-size: 0.9em;
    margin-bottom: 10px;
    color: var(--accent-color);
}

.calendar-event {
    background: var(--editor-bg);
    padding: 8px 12px;
    border-radius: 4px;
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.calendar-event-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent-color);
}

.calendar-event-time {
    font-size: 0.8em;
    color: var(--line-color);
}

/* 生日事件样式 */
.calendar-event.birthday-event {
    background: var(--birthday-bg);
    border-left: 3px solid var(--birthday-color);
}

.calendar-event.birthday-event .calendar-event-dot {
    background: var(--birthday-color);
}

/* 天气组件样式 */
.weather-container {
    margin-top: 20px;
    background: var(--editor-secondary-bg);
    border-radius: var(--border-radius);
    padding: 20px;
    box-shadow: var(--box-shadow);
    border: 1px solid rgba(255, 255, 255, 0.1);
    transition: all 0.3s;
}

.weather-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

.weather-location {
    font-size: 1.2em;
    font-weight: bold;
    display: flex;
    align-items: center;
    gap: 8px;
}

.weather-refresh {
    background: var(--editor-bg);
    border: none;
    color: var(--text-color);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s;
}

.weather-refresh:hover {
    background: var(--accent-color);
    color: white;
    transform: rotate(180deg);
}

.weather-current {
    display: flex;
    align-items: center;
    margin-bottom: 20px;
}

.weather-icon {
    width: 64px;
    height: 64px;
    margin-right: 15px;
}

.weather-temp {
    font-size: 2.5em;
    font-weight: bold;
}

.weather-desc {
    margin-left: 15px;
}

.weather-details {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 15px;
    margin-bottom: 20px;
}

.weather-detail {
    background: var(--editor-bg);
    padding: 10px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.weather-detail-icon {
    width: 20px;
    height: 20px;
    opacity: 0.7;
}

.weather-detail-value {
    font-weight: bold;
}

.weather-forecast {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 10px;
}

.forecast-day {
    background: var(--editor-bg);
    padding: 10px;
    border-radius: 4px;
    text-align: center;
}

.forecast-date {
    font-size: 0.8em;
    color: var(--line-color);
    margin-bottom: 5px;
}

.forecast-icon {
    width: 32px;
    height: 32px;
    margin: 5px auto;
}

.forecast-temp {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
}

.forecast-high {
    color: var(--weather-temp-high);
    font-weight: bold;
}

.forecast-low {
    color: var(--weather-temp-low);
    font-size: 0.9em;
}

.weather-search {
    margin-top: 15px;
    display: flex;
    gap: 10px;
}

.weather-search input {
    flex: 1;
    background: var(--editor-bg);
    border: 1px solid var(--line-color);
    color: var(--text-color);
    padding: 8px 12px;
    border-radius: 4px;
    font-family: var(--font-family);
}

.weather-search button {
    background: var(--accent-color);
    color: white;
    border: none;
    padding: 8px 15px;
    border-radius: 4px;
    cursor: pointer;
    font-family: var(--font-family);
    transition: all 0.2s;
}

.weather-search button:hover {
    background: var(--accent-hover);
}

/* 命令面板分类 */
.command-category {
    font-size: 0.8em;
    color: var(--line-color);
    padding: 5px 12px;
    margin-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.command-category:first-child {
    border-top: none;
    margin-top: 0;
}

/* 关闭后的界面样式 */
.shutdown-screen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #000;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    color: #fff;
    font-family: var(--font-family);
    z-index: 1000;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.5s ease;
}

.shutdown-screen.active {
    opacity: 1;
    pointer-events: all;
}

.shutdown-text {
    font-size: 2em;
    margin-bottom: 20px;
    text-align: center;
}

.restart-btn {
    background: #0a84ff;
    color: white;
    border: none;
    padding: 12px 24px;
    border-radius: 30px;
    cursor: pointer;
    font-family: var(--font-family);
    font-size: 1em;
    transition: all 0.3s;
    margin-top: 30px;
}

.restart-btn:hover {
    background: #409eff;
    transform: translateY(-3px);
    box-shadow: 0 10px 20px rgba(10, 132, 255, 0.3);
}

.terminal-signature {
    position: absolute;
    bottom: 30px;
    font-size: 0.8em;
    color: rgba(255, 255, 255, 0.5);
}

/* 响应式设计优化 */
@media (max-width: 768px) {
    body {
        padding: 10px;
    }

    .editor {
        width: 100%;
        margin: 0;
        font-size: 14px;
    }

    .editor-content {
        padding: 15px 10px;
        max-height: 60vh;
    }

    .line-content {
        padding-left: 2.5em;
    }

    .indent { margin-left: 1.5em; }
    .indent-2 { margin-left: 3em; }

    .title-bar {
        font-size: 0.8em;
        margin-left: 10px;
    }

    .window-btn {
        width: 10px;
        height: 10px;
    }
    
    .theme-switch {
        top: 10px;
        right: 10px;
        padding: 5px 10px;
        font-size: 0.8em;
    }
    
    .image-controls {
        flex-direction: column;
    }
    
    .image-control {
        width: 100%;
    }
    
    .weather-forecast {
        grid-template-columns: repeat(3, 1fr);
    }
    
    .calendar-grid {
        gap: 2px;
    }
    
    .calendar-day {
        padding: 5px;
        font-size: 0.9em;
    }
}

@media (max-width: 480px) {
    .editor-content {
        font-size: 12px;
    }

    .indent { margin-left: 1em; }
    .indent-2 { margin-left: 2em; }
    
    .weather-forecast {
        grid-template-columns: repeat(2, 1fr);
    }
    
    .weather-details {
        grid-template-columns: 1fr;
    }
}
    </style>
</head>
<body>
    <!-- 关闭后的界面 -->
    <div class="shutdown-screen" id="shutdownScreen">
        <div class="shutdown-text">
            <p>藤原的个人终端已关闭</p>
            <p>感谢您的使用</p>
        </div>
        <button class="restart-btn" id="restartBtn">重新启动</button>
        <div class="terminal-signature">藤原终端 v2.0</div>
    </div>
    
    <div class="editor" id="mainEditor">
        <div class="editor-header">
            <span class="window-btn close" data-tooltip="关闭" id="closeBtn"></span>
            <span class="window-btn minimize" data-tooltip="最小化" id="minimizeBtn"></span>
            <span class="window-btn maximize" data-tooltip="最大化" id="maximizeBtn"></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 class="command-history" id="commandHistory">
                <div class="history-title">命令历史记录</div>
                <div class="history-list" id="historyList"></div>
            </div>
            
            <!-- 输入行 -->
            <div class="input-line">
                <input type="text" id="userInput" placeholder="输入命令..." autocomplete="off">
            </div>
        </div>
    </div>
    
    <!-- 命令面板 -->
    <div class="command-palette" id="commandPalette">
        <div class="command-header">
            <input type="text" class="command-search" id="commandSearch" placeholder="搜索命令...">
            <button class="image-btn" id="closeCommandPalette" style="margin-left: 10px; padding: 6px 12px;">关闭</button>
        </div>
        <div class="command-list" id="commandList">
            <!-- 命令将通过JS动态添加 -->
        </div>
    </div>

    <!-- 隐藏的文件输入元素 -->
    <input type="file" id="fileInput" accept="image/*" style="display: none;">

    <script>
        // 主题切换功能
        // 创建隐藏的主题切换元素(如果不存在)
        let themeSwitch = document.getElementById('themeSwitch');
        let themeText;
        if (!themeSwitch) {
            themeSwitch = document.createElement('div');
            themeSwitch.id = 'themeSwitch';
            themeSwitch.style.display = 'none';
            themeText = document.createElement('span');
            themeText.id = 'themeText';
            themeSwitch.appendChild(themeText);
            document.body.appendChild(themeSwitch);
        } else {
            themeText = document.getElementById('themeText');
        }
        const body = document.body;
        
        // 检查本地存储中的主题设置
        const currentTheme = localStorage.getItem('theme') || 'dark';
        body.setAttribute('data-theme', currentTheme);
        themeText.textContent = currentTheme === 'dark' ? '切换主题' : '夜间模式';
        
        themeSwitch.addEventListener('click', () => {
            const currentTheme = body.getAttribute('data-theme');
            const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
            body.setAttribute('data-theme', newTheme);
            localStorage.setItem('theme', newTheme);
            themeText.textContent = newTheme === 'dark' ? '切换主题' : '夜间模式';
        });
        
        // 设置当前年份
        const currentYear = new Date().getFullYear();
        document.getElementById('year').textContent = currentYear;
        
        // 终端交互功能
        const editorContent = document.getElementById('editorContent');
        const userInput = document.getElementById('userInput');
        const inputLine = document.querySelector('.input-line');
        const fileInput = document.getElementById('fileInput');
        const commandPalette = document.getElementById('commandPalette');
        const commandSearch = document.getElementById('commandSearch');
        const commandList = document.getElementById('commandList');
        const commandHistory = document.getElementById('commandHistory');
        const historyList = document.getElementById('historyList');
        const closeBtn = document.getElementById('closeBtn');
        const minimizeBtn = document.getElementById('minimizeBtn');
        const maximizeBtn = document.getElementById('maximizeBtn');
        const shutdownScreen = document.getElementById('shutdownScreen');
        const restartBtn = document.getElementById('restartBtn');
        const closeCommandPalette = document.getElementById('closeCommandPalette');
        const mainEditor = document.getElementById('mainEditor');
        
        // 窗口控制功能
        closeBtn.addEventListener('click', () => {
            // 显示关闭界面
            shutdownScreen.classList.add('active');
            mainEditor.style.opacity = '0';
            mainEditor.style.pointerEvents = 'none';
        });
        
        minimizeBtn.addEventListener('click', () => {
            // 最小化效果 - 缩小并隐藏
            mainEditor.style.transform = 'scale(0.8)';
            mainEditor.style.opacity = '0';
            mainEditor.style.pointerEvents = 'none';
            
            // 3秒后恢复
            setTimeout(() => {
                mainEditor.style.transform = 'scale(1)';
                mainEditor.style.opacity = '1';
                mainEditor.style.pointerEvents = 'all';
            }, 3000);
        });
        
        maximizeBtn.addEventListener('click', () => {
            // 切换全屏
            if (!document.fullscreenElement) {
                mainEditor.requestFullscreen().catch(err => {
                    addAILine(`全屏模式错误: ${err.message}`);
                });
            } else {
                document.exitFullscreen();
            }
        });
        
        // 重启按钮功能
        restartBtn.addEventListener('click', () => {
            shutdownScreen.classList.remove('active');
            mainEditor.style.opacity = '1';
            mainEditor.style.pointerEvents = 'all';
        });
        
        // 命令面板关闭按钮
        closeCommandPalette.addEventListener('click', () => {
            commandPalette.style.display = 'none';
            userInput.focus();
        });
        
        // 命令历史记录
        let commandHistoryArray = JSON.parse(localStorage.getItem('commandHistory') || '[]');
        let historyIndex = -1;
        
        // 更新命令历史记录UI
        function updateHistoryUI() {
            historyList.innerHTML = '';
            commandHistoryArray.slice().reverse().forEach((cmd, index) => {
                const item = document.createElement('div');
                item.className = 'history-item';
                item.textContent = cmd;
                item.addEventListener('click', () => {
                    userInput.value = cmd;
                    userInput.focus();
                });
                historyList.appendChild(item);
            });
        }
        
        // 保存命令到历史记录
        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));
                updateHistoryUI();
            }
            historyIndex = -1;
        }
        
        // 可用命令列表
        const commands = [
            // 基础命令
            { id: 'help', name: '帮助', description: '显示帮助信息', shortcut: '?', category: '基础' },
            { id: 'clear', name: '清空终端', description: '清除终端内容', shortcut: 'Ctrl+L', category: '基础' },
            { id: 'history', name: '命令历史', description: '显示命令历史记录', shortcut: 'H', category: '基础' },
            { id: 'theme', name: '切换主题', description: '切换深色/浅色主题', shortcut: 'T', category: '基础' },
            
            // 工具命令
            { id: 'video', name: '解析视频', description: '解析并播放视频', args: 'URL', category: '工具' },
            { id: 'ai', name: 'AI助手', description: '与AI助手对话', args: 'message', category: '工具' },
            { id: 'base64', name: 'Base64编解码', description: '进行Base64编码或解码', args: 'encode/decode text', category: '工具' },
            { id: 'image', name: '图片转换', description: '转换图片格式', args: 'format', category: '工具' },
            
            // 新增功能
            { id: 'calendar', name: '日历', description: '显示日历和事件', shortcut: 'C', category: '新功能' },
            { id: 'weather', name: '天气', description: '查看天气预报', args: '城市名', shortcut: 'W', category: '新功能' },
            { id: 'todo', name: '待办事项', description: '管理待办事项', args: 'add/list/done/remove', category: '新功能' }
        ];
        
        // 初始化命令面板
        function initCommandPalette() {
            commandList.innerHTML = '';
            
            // 按类别分组命令
            const categories = [...new Set(commands.map(cmd => cmd.category))];
            
            categories.forEach(category => {
                const categoryCommands = commands.filter(cmd => cmd.category === category);
                
                // 创建类别标题
                const categoryTitle = document.createElement('div');
                categoryTitle.className = 'command-category';
                categoryTitle.textContent = category;
                commandList.appendChild(categoryTitle);
                
                // 添加该类别下的命令
                categoryCommands.forEach(cmd => {
                    const item = document.createElement('div');
                    item.className = 'command-item';
                    item.dataset.id = cmd.id;
                    item.dataset.category = cmd.category;
                    
                    const icon = document.createElement('svg');
                    icon.className = 'command-icon';
                    icon.setAttribute('width', '16');
                    icon.setAttribute('height', '16');
                    icon.setAttribute('viewBox', '0 0 24 24');
                    icon.setAttribute('fill', 'none');
                    icon.setAttribute('stroke', 'currentColor');
                    icon.setAttribute('stroke-width', '2');
                    icon.setAttribute('stroke-linecap', 'round');
                    icon.setAttribute('stroke-linejoin', 'round');
                    
                    // 根据命令ID设置不同的图标
                    let iconPath;
                    switch(cmd.id) {
                        case 'help':
                            iconPath = '<circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line>';
                            break;
                        case 'clear':
                            iconPath = '<polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>';
                            break;
                        case 'video':
                            iconPath = '<rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"></rect><line x1="7" y1="2" x2="7" y2="22"></line><line x1="17" y1="2" x2="17" y2="22"></line><line x1="2" y1="12" x2="22" y2="12"></line><line x1="2" y1="7" x2="7" y2="7"></line><line x1="2" y1="17" x2="7" y2="17"></line><line x1="17" y1="17" x2="22" y2="17"></line><line x1="17" y1="7" x2="22" y2="7"></line>';
                            break;
                        case 'ai':
                            iconPath = '<circle cx="12" cy="12" r="10"></circle><polygon points="10 8 16 12 10 16 10 8"></polygon>';
                            break;
                        case 'base64':
                            iconPath = '<polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline>';
                            break;
                        case 'image':
                            iconPath = '<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>';
                            break;
                        case 'history':
                            iconPath = '<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>';
                            break;
                        case 'theme':
                            iconPath = '<circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>';
                            break;
                        case 'calendar':
                            iconPath = '<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>';
                            break;
                        case 'weather':
                            iconPath = '<path d="M17 18a5 5 0 0 0-10 0"></path><line x1="12" y1="9" x2="12" y2="2"></line><line x1="4.22" y1="10.22" x2="5.64" y2="11.64"></line><line x1="1" y1="18" x2="3" y2="18"></line><line x1="21" y1="18" x2="23" y2="18"></line><line x1="18.36" y1="11.64" x2="19.78" y2="10.22"></line><line x1="23" y1="22" x2="1" y2="22"></line><polyline points="8 6 12 2 16 6"></polyline>';
                            break;
                        case 'todo':
                            iconPath = '<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>';
                            break;
                        default:
                            iconPath = '<circle cx="12" cy="12" r="10"></circle>';
                    }
                    
                    icon.innerHTML = iconPath;
                    
                    const content = document.createElement('div');
                    content.style.flex = '1';
                    
                    const title = document.createElement('div');
                    title.textContent = cmd.name;
                    
                    const description = document.createElement('div');
                    description.textContent = cmd.description;
                    description.style.fontSize = '0.8em';
                    description.style.color = 'var(--line-color)';
                    
                    content.appendChild(title);
                    content.appendChild(description);
                    
                    const shortcut = document.createElement('div');
                    shortcut.className = 'command-shortcut';
                    shortcut.textContent = cmd.shortcut || '';
                    
                    item.appendChild(icon);
                    item.appendChild(content);
                    item.appendChild(shortcut);
                    
                    item.addEventListener('click', () => {
                        executeCommandFromPalette(cmd);
                    });
                    
                    commandList.appendChild(item);
                });
            });
        }
        
        // 执行从命令面板选择的命令
        function executeCommandFromPalette(cmd) {
            commandPalette.style.display = 'none';
            
            switch(cmd.id) {
                case 'help':
                case 'clear':
                case 'history':
                case 'calendar':
                case 'todo':
                    userInput.value = cmd.id;
                    break;
                case 'video':
                case 'ai':
                case 'base64':
                case 'image':
                case 'weather':
                    userInput.value = cmd.id + ' ';
                    break;
                case 'theme':
                    // 直接执行主题切换
                    themeSwitch.click();
                    return;
                default:
                    return;
            }
            
            userInput.focus();
            if (['help', 'clear', 'history', 'calendar', 'todo'].includes(cmd.id)) {
                // 直接执行命令
                const event = new KeyboardEvent('keypress', {'key': 'Enter'});
                userInput.dispatchEvent(event);
            }
        }
        
        // 过滤命令面板
        function filterCommands(query) {
            const items = commandList.querySelectorAll('.command-item');
            const categories = commandList.querySelectorAll('.command-category');
            query = query.toLowerCase();
            
            let firstVisible = null;
            let visibleCategories = new Set();
            
            // 首先隐藏所有类别
            categories.forEach(category => {
                category.style.display = 'none';
            });
            
            // 然后检查每个命令项
            items.forEach(item => {
                const cmd = commands.find(c => c.id === item.dataset.id);
                const matchesName = cmd.name.toLowerCase().includes(query);
                const matchesId = cmd.id.toLowerCase().includes(query);
                const matchesDesc = cmd.description.toLowerCase().includes(query);
                const matchesCategory = cmd.category.toLowerCase().includes(query);
                
                if (matchesName || matchesId || matchesDesc || matchesCategory) {
                    item.style.display = 'flex';
                    visibleCategories.add(cmd.category);
                    
                    if (!firstVisible) {
                        firstVisible = item;
                        item.classList.add('selected');
                    } else {
                        item.classList.remove('selected');
                    }
                } else {
                    item.style.display = 'none';
                    item.classList.remove('selected');
                }
            });
            
            // 显示有可见命令的类别
            categories.forEach(category => {
                if (visibleCategories.has(category.textContent)) {
                    category.style.display = 'block';
                }
            });
            
            // 如果没有查询,显示所有类别
            if (!query) {
                categories.forEach(category => {
                    category.style.display = 'block';
                });
            }
        }
        
        // 初始化键盘事件
        function initKeyboardEvents() {
            // 命令面板快捷键
            document.addEventListener('keydown', (e) => {
                // Ctrl+K 打开命令面板
                if (e.ctrlKey && e.key === 'k') {
                    e.preventDefault();
                    commandPalette.style.display = 'block';
                    commandSearch.value = '';
                    filterCommands('');
                    commandSearch.focus();
                    return;
                }
                
                // Ctrl+L 清屏
                if (e.ctrlKey && e.key === 'l') {
                    e.preventDefault();
                    clearTerminal();
                    return;
                }
                
                // Esc 关闭命令面板
                if (e.key === 'Escape') {
                    commandPalette.style.display = 'none';
                    userInput.focus();
                    return;
                }
                
                // 命令面板导航
                if (commandPalette.style.display === 'block') {
                    const items = Array.from(commandList.querySelectorAll('.command-item')).filter(
                        item => item.style.display !== 'none'
                    );
                    
                    if (items.length > 0) {
                        const currentIndex = items.findIndex(item => item.classList.contains('selected'));
                        
                        if (e.key === 'ArrowDown') {
                            e.preventDefault();
                            if (currentIndex < items.length - 1) {
                                items[currentIndex].classList.remove('selected');
                                items[currentIndex + 1].classList.add('selected');
                                items[currentIndex + 1].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                            }
                        } else if (e.key === 'ArrowUp') {
                            e.preventDefault();
                            if (currentIndex > 0) {
                                items[currentIndex].classList.remove('selected');
                                items[currentIndex - 1].classList.add('selected');
                                items[currentIndex - 1].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                            }
                        } else if (e.key === 'Enter') {
                            e.preventDefault();
                            const selectedItem = commandList.querySelector('.command-item.selected');
                            if (selectedItem) {
                                const cmdId = selectedItem.dataset.id;
                                const cmd = commands.find(c => c.id === cmdId);
                                executeCommandFromPalette(cmd);
                            }
                        }
                    }
                }
                
                // 命令历史记录导航
                if (document.activeElement === userInput) {
                    if (e.key === 'ArrowUp' && commandHistoryArray.length > 0) {
                        e.preventDefault();
                        
                        if (historyIndex < commandHistoryArray.length - 1) {
                            historyIndex++;
                            userInput.value = commandHistoryArray[commandHistoryArray.length - 1 - historyIndex];
                        }
                    } else if (e.key === 'ArrowDown' && historyIndex > -1) {
                        e.preventDefault();
                        
                        historyIndex--;
                        if (historyIndex === -1) {
                            userInput.value = '';
                        } else {
                            userInput.value = commandHistoryArray[commandHistoryArray.length - 1 - historyIndex];
                        }
                    }
                }
            });
            
            // 命令面板搜索
            commandSearch.addEventListener('input', () => {
                filterCommands(commandSearch.value);
            });
        }
        
        // 帮助信息
        const helpText = `
可用命令:

基础命令:
- help: 显示帮助信息
- clear: 清空终端
- history: 显示命令历史记录
- theme: 切换深色/浅色主题

工具命令:
- video [url]: 解析并播放视频
  例如: video https://v.qq.com/x/cover/mzc00200mp8er9d.html
- ai [message]: 与AI助手对话
  例如: ai 你好
- base64 [encode/decode] [text]: 进行Base64编码/解码
  例如: base64 encode 你好世界
- image [format]: 转换图片格式 (支持: jpg, png, webp, bmp)
  例如: image png

新功能:
- calendar: 显示日历和事件管理
- weather [城市名]: 查看天气预报
  例如: weather 北京
- todo [add/list/done/remove]: 管理待办事项
  例如: todo add 完成项目报告

快捷键:
- Ctrl+K: 打开命令面板
- Ctrl+L: 清空终端
- 上/下箭头: 浏览命令历史
`;
        
        // 打字机效果函数
        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 {
                        // 移除光标
                        const cursor = element.querySelector('.cursor');
                        if (cursor) cursor.remove();
                        resolve();
                    }
                };
                
                // 添加光标
                const cursorSpan = document.createElement('span');
                cursorSpan.className = 'cursor';
                element.appendChild(cursorSpan);
                
                typing();
            });
        }
        
        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);
            // 将AI回复插入到输入行之前
            editorContent.insertBefore(line, inputLine);
            editorContent.scrollTop = editorContent.scrollHeight;
            
            // 应用打字机效果
            await typeWriterEffect(lineContent, text);
            return line;
        }
        
        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.insertBefore(line, inputLine);
            editorContent.scrollTop = editorContent.scrollHeight;
            return line;
        }
        
        // 修复清除终端内容函数
        function clearTerminal() {
            const lines = document.querySelectorAll('.line');
            const commandHistoryElem = document.getElementById('commandHistory');
            const calendarContainer = document.querySelector('.calendar-container');
            const weatherContainer = document.querySelector('.weather-container');
            
            lines.forEach(line => {
                if (!line.classList.contains('input-line')) {
                    line.remove();
                }
            });
            
            // 重新添加命令历史(如果显示)
            if (commandHistoryElem && commandHistoryElem.style.display === 'block') {
                editorContent.insertBefore(commandHistoryElem, inputLine);
            }

            // 保留日历(如果显示)
            if (calendarContainer) {
                editorContent.insertBefore(calendarContainer, inputLine);
            }
            
            // 保留天气(如果显示)
            if (weatherContainer) {
                editorContent.insertBefore(weatherContainer, inputLine);
            }
        }
        
        // 创建视频播放器
        function createVideoPlayer(videoUrl) {
            // 移除现有的视频播放器
            const existingPlayer = document.querySelector('.video-container');
            if (existingPlayer) {
                existingPlayer.remove();
            }
            
            const videoContainer = document.createElement('div');
            videoContainer.className = 'video-container';
            
            const videoElement = document.createElement('video');
            videoElement.controls = true;
            videoElement.src = videoUrl;
            
            const videoInfo = document.createElement('div');
            videoInfo.className = 'video-info';
            videoInfo.textContent = '视频播放器 (按空格键暂停/播放)';
            
            const videoCommands = document.createElement('div');
            videoCommands.className = 'video-commands';
            
            const fullscreenBtn = document.createElement('div');
            fullscreenBtn.className = 'video-command';
            fullscreenBtn.textContent = '全屏';
            fullscreenBtn.addEventListener('click', () => {
                if (videoElement.requestFullscreen) {
                    videoElement.requestFullscreen();
                } else if (videoElement.webkitRequestFullscreen) {
                    videoElement.webkitRequestFullscreen();
                } else if (videoElement.msRequestFullscreen) {
                    videoElement.msRequestFullscreen();
                }
            });
            
            const playbackSpeedBtn = document.createElement('div');
            playbackSpeedBtn.className = 'video-command';
            playbackSpeedBtn.textContent = '1.0x 速度';
            playbackSpeedBtn.addEventListener('click', () => {
                const speeds = [0.5, 0.75, 1.0, 1.25, 1.5, 2.0];
                const currentIndex = speeds.indexOf(videoElement.playbackRate);
                const nextIndex = (currentIndex + 1) % speeds.length;
                videoElement.playbackRate = speeds[nextIndex];
                playbackSpeedBtn.textContent = `${speeds[nextIndex]}x 速度`;
            });
            
            const closeBtn = document.createElement('div');
            closeBtn.className = 'video-command';
            closeBtn.textContent = '关闭';
            closeBtn.addEventListener('click', () => {
                videoContainer.remove();
            });
            
            videoCommands.appendChild(fullscreenBtn);
            videoCommands.appendChild(playbackSpeedBtn);
            videoCommands.appendChild(closeBtn);
            
            videoContainer.appendChild(videoElement);
            videoContainer.appendChild(videoInfo);
            videoContainer.appendChild(videoCommands);
            
            // 将视频播放器插入到输入行之前
            editorContent.insertBefore(videoContainer, inputLine);
            editorContent.scrollTop = editorContent.scrollHeight;
            
            // 自动播放视频
            videoElement.play().catch(e => {
                addAILine('视频自动播放失败,请点击播放按钮手动播放');
            });
            
            // 添加键盘控制
            document.addEventListener('keydown', (e) => {
                if (e.code === 'Space' && document.activeElement !== userInput) {
                    e.preventDefault();
                    if (videoElement.paused) {
                        videoElement.play();
                    } else {
                        videoElement.pause();
                    }
                }
            });
        }
        
        // 解析视频
        async function parseVideo(url) {
            try {
                // 验证URL格式
                if (!/^https?:\/\/.+/.test(url)) {
                    addAILine('错误:请提供有效的URL地址');
                    return;
                }
                
                const loadingLine = await addAILine('正在解析视频,请稍候...');
                
                // 使用影视解析接口
                const apiUrl = `https://www.yemu.xyz/?url=${encodeURIComponent(url)}`;
                
                // 创建iframe来加载解析后的视频
                const iframe = document.createElement('iframe');
                iframe.src = apiUrl;
                iframe.style.width = '100%';
                iframe.style.height = '450px';
                iframe.style.border = 'none';
                iframe.style.borderRadius = '8px';
                iframe.style.marginTop = '15px';
                iframe.style.boxShadow = 'var(--box-shadow)';
                
                // 移除现有的视频播放器
                const existingPlayer = document.querySelector('.video-container');
                if (existingPlayer) {
                    existingPlayer.remove();
                }
                
                const videoContainer = document.createElement('div');
                videoContainer.className = 'video-container';
                videoContainer.appendChild(iframe);
                
                // 添加关闭按钮
                const closeBtn = document.createElement('div');
                closeBtn.className = 'video-command';
                closeBtn.textContent = '关闭视频';
                closeBtn.style.margin = '10px auto';
                closeBtn.style.textAlign = 'center';
                closeBtn.addEventListener('click', () => {
                    videoContainer.remove();
                });
                
                videoContainer.appendChild(closeBtn);
                
                // 将视频播放器插入到输入行之前
                editorContent.insertBefore(videoContainer, inputLine);
                editorContent.scrollTop = editorContent.scrollHeight;
                
                // 更新加载提示
                loadingLine.querySelector('.line-content').textContent = '藤原: 视频已加载,如果无法播放,请尝试其他解析接口';
                
            } catch (error) {
                addAILine(`视频解析失败: ${error.message}`);
            }
        }
        
        // 创建图片转换器界面
        function createImageConverter(targetFormat) {
            // 移除现有的图片转换器
            const existingConverter = document.querySelector('.image-converter');
            if (existingConverter) {
                existingConverter.remove();
            }
            
            const converter = document.createElement('div');
            converter.className = 'image-converter';
            
            const previewContainer = document.createElement('div');
            previewContainer.className = 'image-preview-container';
            
            const previewText = document.createElement('div');
            previewText.textContent = '请选择要转换的图片';
            previewText.className = 'ai-output';
            
            const previewImage = document.createElement('img');
            previewImage.className = 'image-preview';
            previewImage.style.display = 'none';
            
            previewContainer.appendChild(previewText);
            previewContainer.appendChild(previewImage);
            
            const controls = document.createElement('div');
            controls.className = 'image-controls';
            
            // 图片质量控制
            const qualityControl = document.createElement('div');
            qualityControl.className = 'image-control';
            
            const qualityLabel = document.createElement('label');
            qualityLabel.textContent = '图片质量 (0-100)';
            qualityLabel.htmlFor = 'imageQuality';
            
            const qualityInput = document.createElement('input');
            qualityInput.type = 'range';
            qualityInput.id = 'imageQuality';
            qualityInput.min = '0';
            qualityInput.max = '100';
            qualityInput.value = '80';
            
            const qualityValue = document.createElement('span');
            qualityValue.textContent = '80';
            qualityValue.style.marginLeft = '5px';
            qualityValue.style.fontSize = '0.8em';
            
            qualityInput.addEventListener('input', () => {
                qualityValue.textContent = qualityInput.value;
            });
            
            qualityControl.appendChild(qualityLabel);
            qualityControl.appendChild(qualityInput);
            qualityControl.appendChild(qualityValue);
            
            // 图片宽度控制
            const widthControl = document.createElement('div');
            widthControl.className = 'image-control';
            
            const widthLabel = document.createElement('label');
            widthLabel.textContent = '宽度 (像素)';
            widthLabel.htmlFor = 'imageWidth';
            
            const widthInput = document.createElement('input');
            widthInput.type = 'number';
            widthInput.id = 'imageWidth';
            widthInput.placeholder = '自动';
            
            widthControl.appendChild(widthLabel);
            widthControl.appendChild(widthInput);
            
            // 图片高度控制
            const heightControl = document.createElement('div');
            heightControl.className = 'image-control';
            
            const heightLabel = document.createElement('label');
            heightLabel.textContent = '高度 (像素)';
            heightLabel.htmlFor = 'imageHeight';
            
            const heightInput = document.createElement('input');
            heightInput.type = 'number';
            heightInput.id = 'imageHeight';
            heightInput.placeholder = '自动';
            
            heightControl.appendChild(heightLabel);
            heightControl.appendChild(heightInput);
            
            // 图片格式选择
            const formatControl = document.createElement('div');
            formatControl.className = 'image-control';
            
            const formatLabel = document.createElement('label');
            formatLabel.textContent = '目标格式';
            formatLabel.htmlFor = 'imageFormat';
            
            const formatSelect = document.createElement('select');
            formatSelect.id = 'imageFormat';
            
            const formats = ['jpg', 'png', 'webp', 'bmp'];
            formats.forEach(format => {
                const option = document.createElement('option');
                option.value = format;
                option.textContent = format.toUpperCase();
                if (format === targetFormat) option.selected = true;
                formatSelect.appendChild(option);
            });
            
            formatControl.appendChild(formatLabel);
            formatControl.appendChild(formatSelect);
            
            controls.appendChild(qualityControl);
            controls.appendChild(widthControl);
            controls.appendChild(heightControl);
            controls.appendChild(formatControl);
            
            // 操作按钮
            const actions = document.createElement('div');
            actions.className = 'image-actions';
            
            const selectBtn = document.createElement('button');
            selectBtn.className = 'image-btn';
            selectBtn.textContent = '选择图片';
            selectBtn.addEventListener('click', () => {
                fileInput.click();
            });
            
            const convertBtn = document.createElement('button');
            convertBtn.className = 'image-btn';
            convertBtn.textContent = '转换图片';
            convertBtn.addEventListener('click', () => {
                if (!previewImage.src) {
                    addAILine('请先选择要转换的图片');
                    return;
                }
                convertImage(previewImage, formatSelect.value, qualityInput.value, widthInput.value, heightInput.value);
            });
            
            const downloadBtn = document.createElement('button');
            downloadBtn.className = 'image-btn';
            downloadBtn.textContent = '下载图片';
            downloadBtn.style.display = 'none';
            downloadBtn.id = 'downloadBtn';
            
            const downloadLink = document.createElement('a');
            downloadLink.className = 'image-download-link';
            downloadLink.id = 'downloadLink';
            downloadLink.download = `converted-image.${formatSelect.value}`;
            
            actions.appendChild(selectBtn);
            actions.appendChild(convertBtn);
            actions.appendChild(downloadBtn);
            actions.appendChild(downloadLink);
            
            converter.appendChild(previewContainer);
            converter.appendChild(controls);
            converter.appendChild(actions);
            
            // 将图片转换器插入到输入行之前
            editorContent.insertBefore(converter, inputLine);
            editorContent.scrollTop = editorContent.scrollHeight;
            
            // 文件选择处理
            fileInput.onchange = (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.style.display = 'block';
                    previewText.textContent = '预览:';
                    previewText.className = 'ai-output';
                    
                    // 显示原始图片信息
                    const img = new Image();
                    img.onload = function() {
                        previewText.textContent = `预览 (原始: ${img.width}×${img.height}, ${formatToHumanReadable(file.size)})`;
                    };
                    img.src = event.target.result;
                };
                reader.readAsDataURL(file);
            };
            
            // 当格式改变时更新下载链接的扩展名
            formatSelect.addEventListener('change', () => {
                const downloadLink = document.getElementById('downloadLink');
                if (downloadLink) {
                    downloadLink.download = `converted-image.${formatSelect.value}`;
                }
            });
        }
        
        // 转换图片
        function convertImage(imgElement, format, quality, width, height) {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            
            // 计算新的尺寸
            let newWidth = parseInt(width) || imgElement.naturalWidth;
            let newHeight = parseInt(height) || imgElement.naturalHeight;
            
            // 保持宽高比
            if (width && !height) {
                const ratio = imgElement.naturalHeight / imgElement.naturalWidth;
                newHeight = Math.round(newWidth * ratio);
            } else if (height && !width) {
                const ratio = imgElement.naturalWidth / imgElement.naturalHeight;
                newWidth = Math.round(newHeight * ratio);
            }
            
            canvas.width = newWidth;
            canvas.height = newHeight;
            
            // 绘制图像到画布
            ctx.drawImage(imgElement, 0, 0, newWidth, newHeight);
            
            // 根据格式转换
            let mimeType;
            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/bmp';
                    break;
                default:
                    mimeType = 'image/jpeg';
            }
            
            
            // 转换质量
            let qualityValue = parseInt(quality) / 100;
            if (isNaN(qualityValue)) qualityValue = 0.8;
            
            // 转换为DataURL
            canvas.toBlob((blob) => {
                const url = URL.createObjectURL(blob);
                const downloadLink = document.getElementById('downloadLink');
                const downloadBtn = document.getElementById('downloadBtn');
                
                if (downloadLink && downloadBtn) {
                    downloadLink.href = url;
                    downloadLink.download = `converted-image.${format}`;
                    
                    // 显示下载按钮
                    downloadBtn.style.display = 'inline-block';
                    downloadBtn.onclick = () => {
                        downloadLink.click();
                        addAILine(`图片已转换完成 (${newWidth}×${newHeight}, ${formatToHumanReadable(blob.size)})`);
                    };
                }
                
                // 更新预览
                const previewImage = document.querySelector('.image-preview');
                if (previewImage) {
                    previewImage.src = url;
                }
                
                // 添加成功消息
                addAILine(`图片已成功转换为 ${format.toUpperCase()} 格式!点击"下载图片"按钮保存结果。`);
            }, mimeType, qualityValue);
        }
        
        // 将字节大小转换为易读格式
        function formatToHumanReadable(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
        
        // 显示命令历史
        function toggleCommandHistory() {
            if (commandHistory.style.display === 'none' || !commandHistory.style.display) {
                commandHistory.style.display = 'block';
                updateHistoryUI();
            } else {
                commandHistory.style.display = 'none';
            }
        }
        
        // 创建日历组件
        function createCalendar() {
            // 移除现有的日历
            const existingCalendar = document.querySelector('.calendar-container');
            if (existingCalendar) {
                existingCalendar.remove();
                return;
            }
            
            const now = new Date();
            let currentMonth = now.getMonth();
            let currentYear = now.getFullYear();
            let selectedDate = now;
            
            const calendarContainer = document.createElement('div');
            calendarContainer.className = 'calendar-container';
            
            // 日历头部
            const calendarHeader = document.createElement('div');
            calendarHeader.className = 'calendar-header';
            
            const calendarTitle = document.createElement('div');
            calendarTitle.className = 'calendar-title';
            
            const calendarNav = document.createElement('div');
            calendarNav.className = 'calendar-nav';
            
            const prevBtn = document.createElement('button');
            prevBtn.className = 'calendar-btn';
            prevBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>';
            prevBtn.addEventListener('click', () => {
                currentMonth--;
                if (currentMonth < 0) {
                    currentMonth = 11;
                    currentYear--;
                }
                renderCalendar();
            });
            
            const nextBtn = document.createElement('button');
            nextBtn.className = 'calendar-btn';
            nextBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
            nextBtn.addEventListener('click', () => {
                currentMonth++;
                if (currentMonth > 11) {
                    currentMonth = 0;
                    currentYear++;
                }
                renderCalendar();
            });
            
            const todayBtn = document.createElement('button');
            todayBtn.className = 'calendar-btn';
            todayBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>';
            todayBtn.addEventListener('click', () => {
                const today = new Date();
                currentMonth = today.getMonth();
                currentYear = today.getFullYear();
                selectedDate = today;
                renderCalendar();
            });
            
            calendarNav.appendChild(prevBtn);
            calendarNav.appendChild(todayBtn);
            calendarNav.appendChild(nextBtn);
            
            calendarHeader.appendChild(calendarTitle);
            calendarHeader.appendChild(calendarNav);
            
            // 日历网格
            const calendarGrid = document.createElement('div');
            calendarGrid.className = 'calendar-grid';
            
            // 星期标题
            const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
            weekdays.forEach(day => {
                const weekdayElem = document.createElement('div');
                weekdayElem.className = 'calendar-weekday';
                weekdayElem.textContent = day;
                calendarGrid.appendChild(weekdayElem);
            });
            
            // 日历事件区域
            const calendarEvents = document.createElement('div');
            calendarEvents.className = 'calendar-events';
            
            const eventsTitle = document.createElement('div');
            eventsTitle.className = 'calendar-events-title';
            eventsTitle.textContent = '今日事件';
            
            calendarEvents.appendChild(eventsTitle);
            
            // 添加到容器
            calendarContainer.appendChild(calendarHeader);
            calendarContainer.appendChild(calendarGrid);
            calendarContainer.appendChild(calendarEvents);
            
            // 将日历插入到输入行之前
            editorContent.insertBefore(calendarContainer, inputLine);
            
            // 渲染日历函数
            function renderCalendar() {
                // 更新标题
                const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
                calendarTitle.textContent = `${monthNames[currentMonth]} ${currentYear}`;
                
                // 清除日期
                const days = calendarGrid.querySelectorAll('.calendar-day');
                days.forEach(day => day.remove());
                
                // 获取当月第一天
                const firstDay = new Date(currentYear, currentMonth, 1);
                // 获取当月最后一天
                const lastDay = new Date(currentYear, currentMonth + 1, 0);
                
                // 获取上个月的最后几天
                const prevMonthLastDay = new Date(currentYear, currentMonth, 0).getDate();
                const firstDayIndex = firstDay.getDay(); // 0 = 星期日
                
                // 获取当月的天数
                const lastDate = lastDay.getDate();
                
                // 获取今天的日期
                const today = new Date();
                
                // 填充上个月的日期
                for (let i = firstDayIndex; i > 0; i--) {
                    const dayElem = document.createElement('div');
                    dayElem.className = 'calendar-day other-month';
                    dayElem.textContent = prevMonthLastDay - i + 1;
                    calendarGrid.appendChild(dayElem);
                }
                
                // 填充当月的日期
                for (let i = 1; i <= lastDate; i++) {
                    const dayElem = document.createElement('div');
                    dayElem.className = 'calendar-day';
                    dayElem.textContent = i;
                    
                    // 检查是否是今天
                    if (i === today.getDate() && currentMonth === today.getMonth() && currentYear === today.getFullYear()) {
                        dayElem.classList.add('today');
                    }
                    
                    // 检查是否是选中的日期
                    if (i === selectedDate.getDate() && currentMonth === selectedDate.getMonth() && currentYear === selectedDate.getFullYear()) {
                        dayElem.classList.add('selected');
                    }
                    
                    // 检查是否是生日(11月1日)
                    if (i === 1 && currentMonth === 10) { // 10 表示 11 月(0-11)
                        dayElem.classList.add('birthday');
                        dayElem.setAttribute('title', '藤原生日');
                    }
                    
                    // 点击日期事件
                    dayElem.addEventListener('click', () => {
                        // 移除之前选中的日期
                        const selectedDays = calendarGrid.querySelectorAll('.calendar-day.selected');
                        selectedDays.forEach(day => day.classList.remove('selected'));
                        
                        // 选中当前日期
                        dayElem.classList.add('selected');
                        selectedDate = new Date(currentYear, currentMonth, i);
                        
                        // 更新事件显示
                        updateEvents();
                    });
                    
                    calendarGrid.appendChild(dayElem);
                }
                
                // 填充下个月的日期
                const daysNeeded = 42 - (firstDayIndex + lastDate);
                for (let i = 1; i <= daysNeeded; i++) {
                    const dayElem = document.createElement('div');
                    dayElem.className = 'calendar-day other-month';
                    dayElem.textContent = i;
                    calendarGrid.appendChild(dayElem);
                }
                
                // 更新事件显示
                updateEvents();
            }
            
            // 更新事件显示 - 修复此函数
            function updateEvents() {
                // 清除现有事件和按钮
                calendarEvents.innerHTML = '';
                
                // 重新添加标题
                const eventsTitle = document.createElement('div');
                eventsTitle.className = 'calendar-events-title';
                eventsTitle.textContent = `${selectedDate.getMonth() + 1}月${selectedDate.getDate()}日 事件`;
                calendarEvents.appendChild(eventsTitle);
                
                // 格式化选中日期
                const dateStr = `${selectedDate.getFullYear()}-${(selectedDate.getMonth() + 1).toString().padStart(2, '0')}-${selectedDate.getDate().toString().padStart(2, '0')}`;
                
                // 从本地存储获取事件
                const allEvents = JSON.parse(localStorage.getItem('calendarEvents') || '{}');
                const dayEvents = allEvents[dateStr] || [];
                
                // 检查是否是生日(11月1日)
                if (selectedDate.getMonth() === 10 && selectedDate.getDate() === 1) {
                    const birthdayEvent = document.createElement('div');
                    birthdayEvent.className = 'calendar-event birthday-event';
                    
                    const eventDot = document.createElement('div');
                    eventDot.className = 'calendar-event-dot';
                    
                    const eventContent = document.createElement('div');
                    eventContent.style.flex = '1';
                    eventContent.textContent = '藤原生日';
                    
                    const eventTime = document.createElement('div');
                    eventTime.className = 'calendar-event-time';
                    eventTime.textContent = '全天';
                    
                    birthdayEvent.appendChild(eventDot);
                    birthdayEvent.appendChild(eventContent);
                    birthdayEvent.appendChild(eventTime);
                    
                    calendarEvents.appendChild(birthdayEvent);
                }
                
                // 显示其他事件
                if (dayEvents.length === 0 && !(selectedDate.getMonth() === 10 && selectedDate.getDate() === 1)) {
                    const noEvent = document.createElement('div');
                    noEvent.className = 'calendar-event';
                    noEvent.textContent = '今日没有事件';
                    calendarEvents.appendChild(noEvent);
                } else {
                    dayEvents.forEach(event => {
                        const eventElem = document.createElement('div');
                        eventElem.className = 'calendar-event';
                        
                        const eventDot = document.createElement('div');
                        eventDot.className = 'calendar-event-dot';
                        
                        const eventContent = document.createElement('div');
                        eventContent.style.flex = '1';
                        eventContent.textContent = event.title;
                        
                        const eventTime = document.createElement('div');
                        eventTime.className = 'calendar-event-time';
                        eventTime.textContent = event.time || '';
                        
                        eventElem.appendChild(eventDot);
                        eventElem.appendChild(eventContent);
                        eventElem.appendChild(eventTime);
                        
                        calendarEvents.appendChild(eventElem);
                    });
                }
                
                // 添加事件按钮
                const addEventBtn = document.createElement('button');
                addEventBtn.className = 'image-btn';
                addEventBtn.style.marginTop = '15px';
                addEventBtn.textContent = '添加事件';
                addEventBtn.addEventListener('click', () => {
                    const eventTitle = prompt('请输入事件标题:');
                    if (eventTitle) {
                        const eventTime = prompt('请输入事件时间 (可选):');
                        
                        // 保存事件
                        const allEvents = JSON.parse(localStorage.getItem('calendarEvents') || '{}');
                        const dateStr = `${selectedDate.getFullYear()}-${(selectedDate.getMonth() + 1).toString().padStart(2, '0')}-${selectedDate.getDate().toString().padStart(2, '0')}`;
                        
                        if (!allEvents[dateStr]) {
                            allEvents[dateStr] = [];
                        }
                        
                        allEvents[dateStr].push({
                            title: eventTitle,
                            time: eventTime || ''
                        });
                        
                        localStorage.setItem('calendarEvents', JSON.stringify(allEvents));
                        
                        // 更新显示
                        updateEvents();
                    }
                });
                
                calendarEvents.appendChild(addEventBtn);
            }
            
            // 初始渲染
            renderCalendar();
        }
        
        // 创建天气组件
        async function createWeather(city = '北京') {
            // 移除现有的天气组件
            const existingWeather = document.querySelector('.weather-container');
            if (existingWeather) {
                existingWeather.remove();
            }
            
            const weatherContainer = document.createElement('div');
            weatherContainer.className = 'weather-container';
            
            // 天气头部
            const weatherHeader = document.createElement('div');
            weatherHeader.className = 'weather-header';
            
            const weatherLocation = document.createElement('div');
            weatherLocation.className = 'weather-location';
            weatherLocation.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg> ${city}`;
            
            const weatherRefresh = document.createElement('button');
            weatherRefresh.className = 'weather-refresh';
            weatherRefresh.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><polyline points="23 20 23 14 17 14"></polyline><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"></path></svg>';
            weatherRefresh.addEventListener('click', () => {
                fetchWeatherData(city);
            });
            
            weatherHeader.appendChild(weatherLocation);
            weatherHeader.appendChild(weatherRefresh);
            
            // 天气内容区域
            const weatherContent = document.createElement('div');
            weatherContent.innerHTML = '<div class="ai-output">正在获取天气数据...</div>';
            
            // 天气搜索
            const weatherSearch = document.createElement('div');
            weatherSearch.className = 'weather-search';
            
            const searchInput = document.createElement('input');
            searchInput.type = 'text';
            searchInput.placeholder = '输入城市名称';
            searchInput.value = city;
            
            const searchButton = document.createElement('button');
            searchButton.textContent = '搜索';
            searchButton.addEventListener('click', () => {
                const newCity = searchInput.value.trim();
                if (newCity) {
                    fetchWeatherData(newCity);
                }
            });
            
            // 回车搜索
            searchInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    const newCity = searchInput.value.trim();
                    if (newCity) {
                        fetchWeatherData(newCity);
                    }
                }
            });
            
            weatherSearch.appendChild(searchInput);
            weatherSearch.appendChild(searchButton);
            
            // 添加到容器
            weatherContainer.appendChild(weatherHeader);
            weatherContainer.appendChild(weatherContent);
            weatherContainer.appendChild(weatherSearch);
            
            // 将天气组件插入到输入行之前
            editorContent.insertBefore(weatherContainer, inputLine);
            
            // 获取天气数据
            async function fetchWeatherData(cityName) {
                try {
                    weatherContent.innerHTML = '<div class="ai-output">正在获取天气数据...</div>';
                    weatherLocation.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg> ${cityName}`;
                    
                    // 模拟天气数据获取
                    // 在实际应用中,这里应该调用真实的天气API
                    await new Promise(resolve => setTimeout(resolve, 1000));
                    
                    // 模拟天气数据
                    const weatherData = {
                        city: cityName,
                        current: {
                            temp: Math.floor(Math.random() * 15) + 15,
                            condition: ['晴', '多云', '阴', '小雨', '中雨'][Math.floor(Math.random() * 5)],
                            humidity: Math.floor(Math.random() * 30) + 40,
                            wind: Math.floor(Math.random() * 5) + 1,
                            feelsLike: Math.floor(Math.random() * 15) + 15,
                            pressure: Math.floor(Math.random() * 100) + 1000
                        },
                        forecast: [
                            {
                                date: '今天',
                                high: Math.floor(Math.random() * 10) + 20,
                                low: Math.floor(Math.random() * 10) + 10,
                                condition: ['晴', '多云', '阴', '小雨', '中雨'][Math.floor(Math.random() * 5)]
                            },
                            {
                                date: '明天',
                                high: Math.floor(Math.random() * 10) + 20,
                                low: Math.floor(Math.random() * 10) + 10,
                                condition: ['晴', '多云', '阴', '小雨', '中雨'][Math.floor(Math.random() * 5)]
                            },
                            {
                                date: '后天',
                                high: Math.floor(Math.random() * 10) + 20,
                                low: Math.floor(Math.random() * 10) + 10,
                                condition: ['晴', '多云', '阴', '小雨', '中雨'][Math.floor(Math.random() * 5)]
                            },
                            {
                                date: '周四',
                                high: Math.floor(Math.random() * 10) + 20,
                                low: Math.floor(Math.random() * 10) + 10,
                                condition: ['晴', '多云', '阴', '小雨', '中雨'][Math.floor(Math.random() * 5)]
                            },
                            {
                                date: '周五',
                                high: Math.floor(Math.random() * 10) + 20,
                                low: Math.floor(Math.random() * 10) + 10,
                                condition: ['晴', '多云', '阴', '小雨', '中雨'][Math.floor(Math.random() * 5)]
                            }
                        ]
                    };
                    
                    // 渲染天气数据
                    renderWeatherData(weatherData);
                } catch (error) {
                    weatherContent.innerHTML = `<div class="ai-output">获取天气数据失败: ${error.message}</div>`;
                }
            }
            
            // 渲染天气数据
            function renderWeatherData(data) {
                // 获取天气图标
                function getWeatherIcon(condition) {
                    switch(condition) {
                        case '晴':
                            return '<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>';
                        case '多云':
                            return '<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"></path></svg>';
                        case '阴':
                            return '<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"></path></svg>';
                        case '小雨':
                            return '<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 16.2A4.5 4.5 0 0 0 17.5 8h-1.8A7 7 0 1 0 4 14.9"></path><path d="M16 14v6"></path><path d="M8 14v6"></path><path d="M12 16v6"></path></svg>';
                        case '中雨':
                            return '<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 16.2A4.5 4.5 0 0 0 17.5 8h-1.8A7 7 0 1 0 4 14.9"></path><path d="M16 14v6"></path><path d="M8 14v6"></path><path d="M12 16v6"></path></svg>';
                        default:
                            return '<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>';
                    }
                }
                
                // 构建当前天气HTML
                const currentWeatherHTML = `
                    <div class="weather-current">
                        <div class="weather-icon">${getWeatherIcon(data.current.condition)}</div>
                        <div class="weather-temp">${data.current.temp}°</div>
                        <div class="weather-desc">
                            <div>${data.current.condition}</div>
                            <div>体感温度: ${data.current.feelsLike}°</div>
                        </div>
                    </div>
                    
                    <div class="weather-details">
                        <div class="weather-detail">
                            <div class="weather-detail-icon">
                                <svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"></path>
                                </svg>
                            </div>
                            <div>
                                <div>湿度</div>
                                <div class="weather-detail-value">${data.current.humidity}%</div>
                            </div>
                        </div>
                        <div class="weather-detail">
                            <div class="weather-detail-icon">
                                <svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <path d="M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2"></path>
                                </svg>
                            </div>
                            <div>
                                <div>风速</div>
                                <div class="weather-detail-value">${data.current.wind} m/s</div>
                            </div>
                        </div>
                        <div class="weather-detail">
                            <div class="weather-detail-icon">
                                <svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <path d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0z"></path>
                                </svg>
                            </div>
                            <div>
                                <div>气压</div>
                                <div class="weather-detail-value">${data.current.pressure} hPa</div>
                            </div>
                        </div>
                        <div class="weather-detail">
                            <div class="weather-detail-icon">
                                <svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <circle cx="12" cy="12" r="10"></circle>
                                    <line x1="12" y1="8" x2="12" y2="12"></line>
                                    <line x1="12" y1="16" x2="12.01" y2="16"></line>
                                </svg>
                            </div>
                            <div>
                                <div>更新时间</div>
                                <div class="weather-detail-value">${new Date().toLocaleTimeString()}</div>
                            </div>
                        </div>
                    </div>
                `;
                
                // 构建天气预报HTML
                let forecastHTML = '<div class="weather-forecast">';
                
                data.forecast.forEach(day => {
                    forecastHTML += `
                        <div class="forecast-day">
                            <div class="forecast-date">${day.date}</div>
                            <div class="forecast-icon">${getWeatherIcon(day.condition)}</div>
                            <div class="forecast-temp">
                                <div class="forecast-high">${day.high}°</div>
                                <div class="forecast-low">${day.low}°</div>
                            </div>
                        </div>
                    `;
                });
                
                forecastHTML += '</div>';
                
                // 更新天气内容
                weatherContent.innerHTML = currentWeatherHTML + forecastHTML;
            }
            
            // 初始获取天气数据
            fetchWeatherData(city);
        }
        
        // 待办事项功能
        function manageTodo(action, text) {
            // 从本地存储获取待办事项
            const todos = JSON.parse(localStorage.getItem('todos') || '[]');
            
            switch(action) {
                case 'add':
                    if (!text) {
                        addAILine('请提供待办事项内容');
                        return;
                    }
                    todos.push({
                        id: Date.now(),
                        text: text,
                        completed: false,
                        date: new Date().toISOString()
                    });
                    localStorage.setItem('todos', JSON.stringify(todos));
                    addAILine(`已添加待办事项: ${text}`);
                    break;
                    
                case 'list':
                    if (todos.length === 0) {
                        addAILine('没有待办事项');
                    } else {
                        let todoList = '待办事项列表:\n';
                        todos.forEach((todo, index) => {
                            todoList += `${index + 1}. [${todo.completed ? '✓' : ' '}] ${todo.text}\n`;
                        });
                        addAILine(todoList);
                    }
                    break;
                    
                case 'done':
                    const index = parseInt(text) - 1;
                    if (isNaN(index) || index < 0 || index >= todos.length) {
                        addAILine('无效的待办事项编号');
                        return;
                    }
                    todos[index].completed = true;
                    localStorage.setItem('todos', JSON.stringify(todos));
                    addAILine(`已完成待办事项: ${todos[index].text}`);
                    break;
                    
                case 'remove':
                    const removeIndex = parseInt(text) - 1;
                    if (isNaN(removeIndex) || removeIndex < 0 || removeIndex >= todos.length) {
                        addAILine('无效的待办事项编号');
                        return;
                    }
                    const removedTodo = todos.splice(removeIndex, 1)[0];
                    localStorage.setItem('todos', JSON.stringify(todos));
                    addAILine(`已删除待办事项: ${removedTodo.text}`);
                    break;
                    
                default:
                    addAILine('使用方法: todo [add/list/done/remove] [内容/编号]');
            }
        }
        
        // 处理用户命令
        function processCommand(command) {
            const parts = command.split(' ');
            const cmd = parts[0].toLowerCase();
            const args = parts.slice(1).join(' ');
            
            // 保存命令到历史记录
            saveToHistory(command);
            
            switch(cmd) {
                case 'help':
                    addAILine(helpText);
                    break;
                    
                case 'clear':
                    clearTerminal();
                    break;
                    
                case 'video':
                    if (!args) {
                        addAILine('请提供视频URL,例如: video https://v.qq.com/x/cover/mzc00200mp8er9d.html');
                    } else {
                        parseVideo(args);
                    }
                    break;
                    
                case 'ai':
                    if (!args) {
                        addAILine('请输入您想对AI说的话');
                    } else {
                        sendMessage(args);
                    }
                    break;
                    
                case 'base64':
                    const base64Args = args.split(' ');
                    const action = base64Args[0];
                    const text = base64Args.slice(1).join(' ');
                    
                    if (action === 'encode') {
                        if (!text) {
                            addAILine('请提供要编码的文本');
                        } else {
                            addAILine(utf8_to_b64(text));
                        }
                    } else if (action === 'decode') {
                        if (!text) {
                            addAILine('请提供要解码的Base64字符串');
                        } else {
                            try {
                                addAILine(b64_to_utf8(text));
                            } catch (e) {
                                addAILine('解码失败:无效的Base64字符串');
                            }
                        }
                    } else {
                        addAILine('使用方法: base64 [encode/decode] [text]');
                    }
                    break;
                    
                case 'image':
                    if (!args) {
                        addAILine('请指定目标图片格式,例如: image png');
                    } else {
                        const validFormats = ['jpg', 'jpeg', 'png', 'webp', 'bmp'];
                        if (validFormats.includes(args.toLowerCase())) {
                            createImageConverter(args.toLowerCase());
                        } else {
                            addAILine(`不支持的目标格式: ${args}。支持格式: ${validFormats.join(', ')}`);
                        }
                    }
                    break;
                    
                case 'history':
                    toggleCommandHistory();
                    break;
                    
                case 'theme':
                    themeSwitch.click();
                    break;
                    
                case 'calendar':
                    createCalendar();
                    break;
                    
                case 'weather':
                    createWeather(args || '北京');
                    break;
                    
                case 'todo':
                    const todoArgs = args.split(' ');
                    const todoAction = todoArgs[0];
                    const todoText = todoArgs.slice(1).join(' ');
                    manageTodo(todoAction, todoText);
                    break;
                    
                default:
                    if (command.startsWith('http://') || command.startsWith('https://')) {
                        // 如果输入的是URL,直接尝试解析
                        parseVideo(command);
                    } else if (command) {
                        // 如果没有匹配命令,直接发送给AI
                        sendMessage(command);
                    }
            }
        }
        
        // Base64编码函数 - 正确处理UTF-8字符
        function utf8_to_b64(str) {
            return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
                return String.fromCharCode('0x' + p1);
            }));
        }
        
        // Base64解码函数 - 正确处理UTF-8字符
        function b64_to_utf8(str) {
            return decodeURIComponent(atob(str).split('').map(function(c) {
                return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
            }).join(''));
        }
        
        async function sendMessage(message) {
            if (!message) return;
            
            addUserLine(message);
            
            // 显示加载状态
            const loadingLine = document.createElement('div');
            loadingLine.className = 'line';
            
            const loadingContent = document.createElement('div');
            loadingContent.className = 'line-content ai-output';
            loadingContent.innerHTML = '<span class="typing-animation">藤原: 思考中...</span>';
            
            loadingLine.appendChild(loadingContent);
            editorContent.insertBefore(loadingLine, inputLine);
            editorContent.scrollTop = editorContent.scrollHeight;
            
            try {
                const response = await fetch('https://cn.apihz.cn/api/ai/wxtiny.php', {
                    method: 'POST',
                    headers: { 
                        'Content-Type': 'application/x-www-form-urlencoded',
                        'Accept': 'application/json'
                    },
                    body: `id=10003788&key=ffa8afb46dce4916c5a74fd73c8de9f6&words=${encodeURIComponent(message)}`
                });
                
                // 移除加载状态
                loadingLine.remove();
                
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                
                const data = await response.json();
                
                if (data.code === 200) {
                    // 确保AI响应正确处理中文
                    await addAILine(data.msg);
                } else {
                    addAILine(`错误: ${data.msg || '未知错误'}`);
                }
            } catch (error) {
                // 移除加载状态
                loadingLine.remove();
                addAILine(`请求失败: ${error.message}`);
            }
        }
        
        userInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                const command = userInput.value.trim();
                if (command) {
                    processCommand(command);
                    userInput.value = '';
                }
            }
        });
        
        // 初始化
        initCommandPalette();
        initKeyboardEvents();
        updateHistoryUI();
        
        // 自动聚焦输入框
        userInput.focus();
        
        // 添加欢迎消息
        setTimeout(() => {
            addAILine('欢迎来到藤原的个人终端!输入 "help" 获取可用命令。');
        }, 500);
    </script>
</body>
</html>

        
预览
控制台