电脑DIY组装报价系统 用MiMo V2 Pro 写html ,再用opencode(选MiMo 作模型) 当录入口

说明:本来想用opencode +SKILL 来完成 电脑DIY组装报价系统 但是他变化的因素有点大,老是提出配置不对,输出结果要变化多次,知道是因为他收集数据 新的程度有限导致的,所以 就用html 固定他的输入结果,其它变化和录入 交给opencode

代码:index.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>电脑DIY组装报价系统</title>
    <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700&family=Noto+Sans+SC:wght@400;500;600&display=swap" rel="stylesheet">
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        
        :root {
            --bg: #0d0d12;
            --card: #15151d;
            --card-hover: #1a1a25;
            --border: #252535;
            --cyan: #00e5ff;
            --purple: #a855f7;
            --pink: #ec4899;
            --green: #22c55e;
            --orange: #f97316;
            --text: #e5e5e5;
            --text2: #b0b0b0;
            --muted: #71717a;
            --input-bg: #0a0a0f;
            --shadow: rgba(0,0,0,0.3);
        }

        [data-theme="light"] {
            --bg: #f0f2f5;
            --card: #ffffff;
            --card-hover: #f8f9fa;
            --border: #e2e8f0;
            --cyan: #0891b2;
            --purple: #7c3aed;
            --pink: #db2777;
            --green: #16a34a;
            --orange: #ea580c;
            --text: #1a1a2e;
            --text2: #4a5568;
            --muted: #94a3b8;
            --input-bg: #f8fafc;
            --shadow: rgba(0,0,0,0.08);
        }

        body {
            font-family: 'Noto Sans SC', sans-serif;
            background: var(--bg);
            color: var(--text);
            min-height: 100vh;
            transition: background 0.3s, color 0.3s;
        }

        body::before {
            content: '';
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background: 
                radial-gradient(ellipse at 10% 20%, rgba(0,229,255,0.05) 0%, transparent 50%),
                radial-gradient(ellipse at 90% 80%, rgba(168,85,247,0.05) 0%, transparent 50%);
            pointer-events: none;
            z-index: 0;
        }

        [data-theme="light"] body::before {
            background: 
                radial-gradient(ellipse at 10% 20%, rgba(8,145,178,0.06) 0%, transparent 50%),
                radial-gradient(ellipse at 90% 80%, rgba(124,58,237,0.06) 0%, transparent 50%);
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 16px;
            position: relative;
            z-index: 1;
        }

        /* 头部 */
        header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 0;
            border-bottom: 1px solid var(--border);
            margin-bottom: 16px;
        }

        .header-left {
            display: flex;
            align-items: center;
            gap: 16px;
        }

        .logo {
            font-family: 'Orbitron', sans-serif;
            font-size: 1.4rem;
            font-weight: 700;
            background: linear-gradient(135deg, var(--cyan), var(--purple));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .subtitle {
            font-size: 0.75rem;
            color: var(--muted);
        }

        .header-right {
            display: flex;
            align-items: center;
            gap: 20px;
        }

        .stats {
            display: flex;
            gap: 20px;
        }

        .stat { text-align: center; }

        .stat-label {
            font-size: 0.65rem;
            color: var(--muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .stat-value {
            font-family: 'Orbitron', sans-serif;
            font-size: 1rem;
            font-weight: 700;
        }

        .stat-value.cyan { color: var(--cyan); }
        .stat-value.green { color: var(--green); }

        /* 主题切换 */
        .theme-toggle {
            position: relative;
            width: 56px;
            height: 28px;
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: 14px;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            padding: 0 4px;
        }

        .theme-toggle:hover { border-color: var(--cyan); }

        .theme-toggle-ball {
            width: 20px;
            height: 20px;
            background: linear-gradient(135deg, var(--cyan), var(--purple));
            border-radius: 50%;
            transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
        }

        [data-theme="light"] .theme-toggle-ball { transform: translateX(28px); }

        .theme-icons {
            position: absolute;
            width: 100%;
            display: flex;
            justify-content: space-between;
            padding: 0 6px;
            font-size: 0.75rem;
            pointer-events: none;
        }

        .theme-icon-moon { opacity: 1; }
        .theme-icon-sun { opacity: 0.5; }
        [data-theme="light"] .theme-icon-moon { opacity: 0.5; }
        [data-theme="light"] .theme-icon-sun { opacity: 1; }

        /* 预设方案 */
        .presets {
            display: flex;
            gap: 10px;
            margin-bottom: 16px;
        }

        .preset-btn {
            flex: 1;
            padding: 10px 14px;
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: 10px;
            color: var(--text);
            cursor: pointer;
            display: flex;
            align-items: center;
            gap: 10px;
            transition: all 0.2s;
        }

        .preset-btn:hover {
            border-color: var(--cyan);
            transform: translateY(-2px);
            box-shadow: 0 4px 15px var(--shadow);
        }

        .preset-btn .icon { font-size: 1.4rem; }
        .preset-btn .info { text-align: left; }
        .preset-btn .name { font-weight: 600; font-size: 0.85rem; }
        .preset-btn .price { font-size: 0.75rem; color: var(--cyan); font-family: 'Orbitron'; margin-top: 2px; }

        /* 主布局 */
        .main {
            display: grid;
            grid-template-columns: 1fr 320px;
            gap: 16px;
        }

        @media (max-width: 900px) {
            .main { grid-template-columns: 1fr; }
            .presets { flex-wrap: wrap; }
            .header-left { flex-direction: column; align-items: flex-start; gap: 4px; }
            .stats { gap: 14px; }
        }

        /* 配件列表 */
        .components {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 10px;
        }

        @media (max-width: 700px) {
            .components { grid-template-columns: 1fr; }
        }

        .comp-card {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 5px 12px 5px 12px;
            transition: all 0.2s;
        }

        .comp-card:hover {
            border-color: var(--cyan);
            box-shadow: 0 2px 10px var(--shadow);
        }

        .comp-card.selected {
            border-color: var(--green);
            background: linear-gradient(135deg, rgba(34,197,94,0.08), transparent);
        }

        .comp-header {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 8px;
        }

        .comp-icon {
            width: 32px;
            height: 32px;
            background: linear-gradient(135deg, rgba(0,229,255,0.15), rgba(168,85,247,0.15));
            border-radius: 6px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1rem;
        }

        [data-theme="light"] .comp-icon {
            background: linear-gradient(135deg, rgba(8,145,178,0.12), rgba(124,58,237,0.12));
        }

        .comp-name { font-weight: 600; font-size: 0.85rem; }

        .comp-badge {
            margin-left: auto;
            font-size: 0.6rem;
            padding: 2px 8px;
            border-radius: 10px;
            background: rgba(236,72,153,0.15);
            color: var(--pink);
        }

        [data-theme="light"] .comp-badge {
            background: rgba(219,39,119,0.1);
        }

        .comp-row {
            display: flex;
            gap: 6px;
        }

        .comp-select {
            flex: 1;
            padding: 8px 10px;
            background: var(--input-bg);
            border: 1px solid var(--border);
            border-radius: 6px;
            color: var(--text);
            font-size: 0.78rem;
            font-family: inherit;
            cursor: pointer;
            transition: all 0.2s;
        }

        .comp-select:focus {
            outline: none;
            border-color: var(--cyan);
            box-shadow: 0 0 0 3px rgba(0,229,255,0.1);
        }

        /* 添加按钮 */
        .btn-add {
            width: 34px;
            height: 34px;
            background: linear-gradient(135deg, var(--orange), var(--pink));
            border: none;
            border-radius: 6px;
            color: #fff;
            font-size: 1.1rem;
            cursor: pointer;
            transition: all 0.2s;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
        }

        .btn-add:hover {
            transform: scale(1.1);
            box-shadow: 0 2px 10px rgba(249,115,22,0.4);
        }

        .btn-del-custom {
            width: 34px;
            height: 34px;
            background: rgba(236,72,153,0.2);
            border: 1px solid rgba(236,72,153,0.3);
            border-radius: 6px;
            color: var(--pink);
            font-size: 0.9rem;
            cursor: pointer;
            transition: all 0.2s;
            display: none;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
        }

        .btn-del-custom.show { display: flex; }
        .btn-del-custom:hover { background: rgba(236,72,153,0.4); }

        .comp-price {
            margin-top: 6px;
            font-family: 'Orbitron';
            font-size: 0.82rem;
            color: var(--green);
            text-align: right;
            min-height: 1.2em;
            font-weight: 600;
        }

        /* 新增表单 */
        .add-form {
            margin-top: 8px;
            padding: 10px;
            background: var(--input-bg);
            border-radius: 8px;
            border: 1px dashed var(--orange);
            display: none;
            animation: slideDown 0.2s ease;
        }

        .add-form.show { display: block; }

        @keyframes slideDown {
            from { opacity: 0; transform: translateY(-10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .add-form-row {
            display: flex;
            gap: 6px;
            margin-bottom: 8px;
        }

        .add-form-row:last-child { margin-bottom: 0; }

        .add-input {
            flex: 1;
            padding: 7px 10px;
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: 5px;
            color: var(--text);
            font-size: 0.75rem;
            font-family: inherit;
        }

        .add-input:focus { outline: none; border-color: var(--orange); }
        .add-input::placeholder { color: var(--muted); }
        .add-input.name { flex: 2; }
        .add-input.price { flex: 1; }
        .add-input.watt { flex: 1; }

        .add-btns {
            display: flex;
            gap: 6px;
        }

        .btn-confirm {
            flex: 1;
            padding: 7px;
            background: linear-gradient(135deg, var(--orange), var(--pink));
            border: none;
            border-radius: 5px;
            color: #fff;
            font-size: 0.75rem;
            font-weight: 600;
            font-family: inherit;
            cursor: pointer;
            transition: all 0.2s;
        }

        .btn-confirm:hover { transform: translateY(-1px); }

        .btn-cancel {
            padding: 7px 12px;
            background: transparent;
            border: 1px solid var(--border);
            border-radius: 5px;
            color: var(--text);
            font-size: 0.75rem;
            font-family: inherit;
            cursor: pointer;
            transition: all 0.2s;
        }

        .btn-cancel:hover { border-color: var(--pink); color: var(--pink); }

        /* 报价面板 */
        .quote-panel {
            position: sticky;
            top: 16px;
        }

        .quote-card {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: 12px;
            padding: 16px;
        }

        .quote-title {
            font-size: 0.9rem;
            font-weight: 600;
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .config-list {
            max-height: 300px;
            overflow-y: auto;
            margin-bottom: 12px;
        }

        .config-list::-webkit-scrollbar { width: 4px; }
        .config-list::-webkit-scrollbar-track { background: var(--input-bg); border-radius: 2px; }
        .config-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

        .config-item {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px;
            background: var(--input-bg);
            border-radius: 6px;
            margin-bottom: 6px;
            font-size: 0.78rem;
        }

        .config-item:hover { background: var(--card-hover); }

        .config-item-type {
            font-size: 0.62rem;
            color: var(--cyan);
            min-width: 36px;
            font-weight: 600;
            text-transform: uppercase;
        }

        .config-item-name {
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            color: var(--text2);
        }

        .config-item-custom {
            font-size: 0.6rem;
            padding: 1px 4px;
            background: rgba(249,115,22,0.2);
            color: var(--orange);
            border-radius: 3px;
            margin-left: 4px;
        }

        .config-item-price {
            font-family: 'Orbitron';
            font-size: 0.72rem;
            color: var(--green);
            font-weight: 600;
        }

        .config-item-remove {
            background: none;
            border: none;
            color: var(--pink);
            cursor: pointer;
            opacity: 0.5;
            font-size: 0.8rem;
            transition: opacity 0.2s;
            padding: 2px;
        }

        .config-item-remove:hover { opacity: 1; }

        .empty-msg {
            text-align: center;
            padding: 24px;
            color: var(--muted);
            font-size: 0.78rem;
            line-height: 1.6;
        }

        .empty-msg-icon {
            font-size: 2rem;
            margin-bottom: 8px;
            opacity: 0.5;
        }

        /* 价格 */
        .divider {
            height: 1px;
            background: var(--border);
            margin: 12px 0;
        }

        .price-row {
            display: flex;
            justify-content: space-between;
            font-size: 0.78rem;
            margin-bottom: 6px;
        }

        .price-row .label { color: var(--muted); }
        .price-row .value { font-family: 'Orbitron'; font-weight: 500; }

        .total-row {
            font-size: 0.95rem;
            font-weight: 600;
            margin-top: 8px;
            padding-top: 8px;
            border-top: 1px solid var(--border);
        }

        .total-row .value {
            font-size: 1.15rem;
            background: linear-gradient(135deg, var(--cyan), var(--green));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        /* 功耗提示 */
        .watt-warning {
            background: rgba(255,170,0,0.1);
            border: 1px solid rgba(255,170,0,0.3);
            border-radius: 8px;
            padding: 10px 12px;
            margin-top: 12px;
            font-size: 0.75rem;
            color: #ffaa00;
            display: none;
        }

        .watt-warning.show { display: flex; align-items: center; gap: 8px; }

        [data-theme="light"] .watt-warning {
            background: rgba(234,179,8,0.1);
            border-color: rgba(234,179,8,0.3);
            color: #ca8a04;
        }

        /* 按钮组 */
        .btns {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 8px;
            margin-top: 12px;
        }

        .btns-full {
            grid-column: span 2;
        }

        .btn {
            padding: 10px;
            border: none;
            border-radius: 8px;
            font-size: 0.78rem;
            font-weight: 600;
            font-family: inherit;
            cursor: pointer;
            transition: all 0.2s;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 4px;
        }

        .btn-primary {
            background: linear-gradient(135deg, var(--cyan), var(--purple));
            color: #fff;
        }

        .btn-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 15px rgba(0,229,255,0.3); }

        .btn-secondary {
            background: transparent;
            border: 1px solid var(--border);
            color: var(--text);
        }

        .btn-secondary:hover { border-color: var(--cyan); background: rgba(0,229,255,0.05); }

        .btn-danger {
            background: rgba(236,72,153,0.1);
            border: 1px solid rgba(236,72,153,0.3);
            color: var(--pink);
        }

        .btn-danger:hover { background: rgba(236,72,153,0.2); }

        .btn-outline {
            background: transparent;
            border: 1px solid var(--border);
            color: var(--text);
        }

        .btn-outline:hover { border-color: var(--green); background: rgba(34,197,94,0.05); }

        /* 管理自定义配件 */
        .manage-section {
            margin-top: 12px;
            padding-top: 12px;
            border-top: 1px solid var(--border);
        }

        .manage-title {
            font-size: 0.75rem;
            color: var(--muted);
            margin-bottom: 8px;
            display: flex;
            align-items: center;
            gap: 6px;
        }

        .manage-list {
            max-height: 120px;
            overflow-y: auto;
        }

        .manage-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 6px 8px;
            background: var(--input-bg);
            border-radius: 5px;
            margin-bottom: 4px;
            font-size: 0.72rem;
        }

        .manage-item-info {
            display: flex;
            align-items: center;
            gap: 8px;
            flex: 1;
            overflow: hidden;
        }

        .manage-item-type {
            font-size: 0.6rem;
            color: var(--orange);
            background: rgba(249,115,22,0.15);
            padding: 1px 5px;
            border-radius: 3px;
        }

        .manage-item-name {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            color: var(--text2);
        }

        .manage-item-price {
            color: var(--green);
            font-family: 'Orbitron';
            font-size: 0.7rem;
            margin-left: 8px;
        }

        .manage-item-del {
            background: none;
            border: none;
            color: var(--pink);
            cursor: pointer;
            opacity: 0.6;
            font-size: 0.8rem;
            padding: 2px 6px;
        }

        .manage-item-del:hover { opacity: 1; }

        .manage-empty {
            text-align: center;
            padding: 12px;
            color: var(--muted);
            font-size: 0.72rem;
        }

        /* Toast */
        .toast {
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%) translateY(60px);
            background: var(--card);
            border: 1px solid var(--green);
            border-radius: 10px;
            padding: 12px 24px;
            font-size: 0.85rem;
            z-index: 100;
            opacity: 0;
            transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
            box-shadow: 0 10px 30px var(--shadow);
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .toast.show {
            transform: translateX(-50%) translateY(0);
            opacity: 1;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <div class="header-left">
                <div class="logo">BUILDER PRO</div>
                <div class="subtitle">电脑DIY组装报价系统</div>
            </div>
            <div class="header-right">
                <div class="stats">
                    <div class="stat">
                        <div class="stat-label">配件</div>
                        <div class="stat-value cyan" id="count">0</div>
                    </div>
                    <div class="stat">
                        <div class="stat-label">功耗</div>
                        <div class="stat-value cyan" id="watt">0W</div>
                    </div>
                    <div class="stat">
                        <div class="stat-label">总价</div>
                        <div class="stat-value green" id="total-stat">¥0</div>
                    </div>
                </div>
                <div class="theme-toggle" onclick="toggleTheme()" title="切换主题">
                    <div class="theme-icons">
                        <span class="theme-icon-moon">🌙</span>
                        <span class="theme-icon-sun">☀️</span>
                    </div>
                    <div class="theme-toggle-ball"></div>
                </div>
            </div>
        </header>

        <div class="presets">
            <button class="preset-btn" onclick="loadPreset('office')">
                <span class="icon">💼</span>
                <div class="info">
                    <div class="name">办公机1</div>
                    <div class="price">¥780</div>
                </div>
            </button>
            <button class="preset-btn" onclick="loadPreset('office1')">
                <span class="icon">💼</span>
                <div class="info">
                    <div class="name">办公机2</div>
                    <div class="price">¥1,980</div>
                </div>
            </button>
            <button class="preset-btn" onclick="loadPreset('office2')">
                <span class="icon">💼</span>
                <div class="info">
                    <div class="name">办公机3</div>
                    <div class="price">¥2,650</div>
                </div>
            </button>
            <button class="preset-btn" onclick="loadPreset('gaming')">
                <span class="icon">🎮</span>
                <div class="info">
                    <div class="name">电竞游戏</div>
                    <div class="price">¥14,339</div>
                </div>
            </button>
            <button class="preset-btn" onclick="loadPreset('pro')">
                <span class="icon">🎨</span>
                <div class="info">
                    <div class="name">专业创作</div>
                    <div class="price">¥29,689</div>
                </div>
            </button>
        </div>

        <div class="main">
            <div class="components">
                <div class="comp-card" id="card-cpu">
                    <div class="comp-header">
                        <div class="comp-icon">🔲</div>
                        <div class="comp-name">处理器 CPU</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-cpu" onchange="update('cpu')">
                            <option value="">-- 选择处理器 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('cpu')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-cpu" onclick="deleteCustom('cpu')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-cpu">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-cpu" placeholder="配件名称(如:i9-14900K)">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-cpu" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-cpu" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('cpu')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('cpu')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-cpu"></div>
                </div>

                <div class="comp-card" id="card-mb">
                    <div class="comp-header">
                        <div class="comp-icon">🟩</div>
                        <div class="comp-name">主板</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-mb" onchange="update('mb')">
                            <option value="">-- 选择主板 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('mb')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-mb" onclick="deleteCustom('mb')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-mb">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-mb" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-mb" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-mb" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('mb')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('mb')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-mb"></div>
                </div>

                <div class="comp-card" id="card-ram">
                    <div class="comp-header">
                        <div class="comp-icon">📏</div>
                        <div class="comp-name">内存 RAM</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-ram" onchange="update('ram')">
                            <option value="">-- 选择内存 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('ram')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-ram" onclick="deleteCustom('ram')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-ram">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-ram" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-ram" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-ram" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('ram')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('ram')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-ram"></div>
                </div>

                <div class="comp-card" id="card-gpu">
                    <div class="comp-header">
                        <div class="comp-icon">🎴</div>
                        <div class="comp-name">显卡 GPU</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-gpu" onchange="update('gpu')">
                            <option value="">-- 选择显卡 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('gpu')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-gpu" onclick="deleteCustom('gpu')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-gpu">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-gpu" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-gpu" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-gpu" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('gpu')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('gpu')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-gpu"></div>
                </div>

                <div class="comp-card" id="card-ssd">
                    <div class="comp-header">
                        <div class="comp-icon">💾</div>
                        <div class="comp-name">存储</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-ssd" onchange="update('ssd')">
                            <option value="">-- 选择存储 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('ssd')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-ssd" onclick="deleteCustom('ssd')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-ssd">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-ssd" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-ssd" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-ssd" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('ssd')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('ssd')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-ssd"></div>
                </div>

                <div class="comp-card" id="card-psu">
                    <div class="comp-header">
                        <div class="comp-icon">⚡</div>
                        <div class="comp-name">电源 PSU</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-psu" onchange="update('psu')">
                            <option value="">-- 选择电源 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('psu')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-psu" onclick="deleteCustom('psu')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-psu">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-psu" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-psu" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-psu" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('psu')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('psu')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-psu"></div>
                </div>

                <div class="comp-card" id="card-case">
                    <div class="comp-header">
                        <div class="comp-icon">🖥️</div>
                        <div class="comp-name">机箱</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-case" onchange="update('case')">
                            <option value="">-- 选择机箱 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('case')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-case" onclick="deleteCustom('case')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-case">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-case" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-case" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-case" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('case')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('case')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-case"></div>
                </div>

                <div class="comp-card" id="card-cooler">
                    <div class="comp-header">
                        <div class="comp-icon">❄️</div>
                        <div class="comp-name">散热器</div>
                        <span class="comp-badge">必选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-cooler" onchange="update('cooler')">
                            <option value="">-- 选择散热器 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('cooler')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-cooler" onclick="deleteCustom('cooler')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-cooler">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-cooler" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-cooler" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-cooler" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('cooler')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('cooler')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-cooler"></div>
                </div>

                <div class="comp-card" id="card-monitor">
                    <div class="comp-header">
                        <div class="comp-icon">🖥️</div>
                        <div class="comp-name">显示器</div>
                        <span class="comp-badge">可选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-monitor" onchange="update('monitor')">
                            <option value="">-- 选择显示器 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('monitor')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-monitor" onclick="deleteCustom('monitor')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-monitor">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-monitor" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-monitor" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-monitor" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('monitor')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('monitor')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-monitor"></div>
                </div>

                <div class="comp-card" id="card-kbm">
                    <div class="comp-header">
                        <div class="comp-icon">⌨️</div>
                        <div class="comp-name">键盘鼠标</div>
                        <span class="comp-badge">可选</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-kbm" onchange="update('kbm')">
                            <option value="">-- 选择键鼠套装 --</option>
                        </select>
                        <button class="btn-add" onclick="toggleAddForm('kbm')" title="添加自定义">+</button>
                        <button class="btn-del-custom" id="del-kbm" onclick="deleteCustom('kbm')" title="删除自定义">✕</button>
                    </div>
                    <div class="add-form" id="form-kbm">
                        <div class="add-form-row">
                            <input class="add-input name" id="name-kbm" placeholder="配件名称">
                        </div>
                        <div class="add-form-row">
                            <input class="add-input price" id="price-kbm" type="number" placeholder="价格">
                            <input class="add-input watt" id="watt-kbm" type="number" placeholder="功耗(W)">
                        </div>
                        <div class="add-btns">
                            <button class="btn-confirm" onclick="confirmAdd('kbm')">确认添加</button>
                            <button class="btn-cancel" onclick="toggleAddForm('kbm')">取消</button>
                        </div>
                    </div>
                    <div class="comp-price" id="price-kbm"></div>
                </div>

                <div class="comp-card" id="card-giftKbm">
                    <div class="comp-header">
                        <div class="comp-icon">🎁</div>
                        <div class="comp-name">赠送键鼠</div>
                        <span class="comp-badge" style="background:rgba(34,197,94,0.15);color:var(--green);">免费</span>
                    </div>
                    <div class="comp-row">
                        <select class="comp-select" id="sel-giftKbm" onchange="update('giftKbm')">
                            <option value="">-- 选择赠送键鼠 --</option>
                        </select>
                    </div>
                    <div class="comp-price" id="price-giftKbm"></div>
                </div>
            </div>

            <div class="quote-panel">
                <div class="quote-card">
                    <div class="quote-title">📋 配置清单</div>
                    <div class="config-list" id="configList">
                        <div class="empty-msg">
                            <div class="empty-msg-icon">🔧</div>
                            请从左侧选择配件<br>或点击快速方案
                        </div>
                    </div>
                    <div class="divider"></div>
                    <div class="price-row">
                        <span class="label">配件小计</span>
                        <span class="value" id="subtotal">¥0</span>
                    </div>
                    <div class="price-row">
                        <span class="label">装机服务</span>
                        <input type="number" id="fee" value="300" min="0" style="width:80px;background:var(--input-bg);border:1px solid var(--border);border-radius:4px;color:var(--green);font-family:'Orbitron';font-size:0.78rem;text-align:right;padding:4px 6px;" onchange="render()" oninput="render()">
                    </div>
                    <div class="price-row">
                        <span class="label">说明</span>
                        <input type="text" id="note" placeholder="如:赠送配件" style="width:120px;background:var(--input-bg);border:1px solid var(--border);border-radius:4px;color:var(--text);font-size:0.75rem;text-align:right;padding:4px 6px;">
                    </div>
                    <div class="price-row total-row">
                        <span class="label">总计</span>
                        <span class="value" id="total">¥0</span>
                    </div>
                    <div class="watt-warning" id="wattWarning">
                        ⚠️ <span>功耗较高,建议选择更大功率电源</span>
                    </div>
                    <div class="btns">
                        <button class="btn btn-primary" onclick="exportConfig('full')">📤 详细导出</button>
                        <button class="btn btn-outline" onclick="exportConfig('simple')">📄 简洁导出</button>
                        <button class="btn btn-secondary" onclick="copyConfig('full')">📋 详细复制</button>
                        <button class="btn btn-secondary" onclick="copyConfig('simple')">📝 简洁复制</button>
                        <button class="btn btn-danger btns-full" onclick="clearAll()">🗑️ 清空配置</button>
                    </div>

                    <div class="manage-section" id="manageSection">
                        <div class="manage-title">🔧 自定义配件管理</div>
                        <div class="manage-list" id="manageList">
                            <div class="manage-empty">暂无自定义配件</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="toast" id="toast">
        <span id="toastIcon">✅</span>
        <span id="toastMsg"></span>
    </div>

    <script src="data.js"></script>
    <script>
        const selected = { cpu: null, mb: null, ram: null, gpu: null, ssd: null, psu: null, case: null, cooler: null, monitor: null, kbm: null, giftKbm: null };
        const names = { cpu: 'CPU', mb: '主板', ram: '内存', gpu: '显卡', ssd: '存储', psu: '电源', case: '机箱', cooler: '散热', monitor: '显示器', kbm: '键鼠', giftKbm: '赠送键鼠' };
        const typeNames = { cpu: '处理器', mb: '主板', ram: '内存', ssd: '存储', psu: '电源', case: '机箱', cooler: '散热器', monitor: '显示器', kbm: '键盘鼠标', giftKbm: '赠送键鼠' };
        const presets = {
            office: { cpu:'cpu1', mb:'mb1', ram:'ram1',ssd:'ssd1', psu:'psu1', case:'case1', cooler:'cl1', monitor:'mon1', giftKbm:'gkbm1' },
            office1: { cpu:'cpu1', mb:'mb1', ram:'ram1',ssd:'ssd1', psu:'psu1', case:'case1', cooler:'cl1', monitor:'mon1', giftKbm:'gkbm1' },
            office2: { cpu:'cpu2', mb:'mb2', ram:'ram2',ssd:'ssd2', psu:'psu1', case:'case1', cooler:'cl1', monitor:'mon1',giftKbm:'gkbm1'},
            gaming: { cpu:'cpu3', mb:'mb3', ram:'ram5', gpu:'gpu4', ssd:'ssd3', psu:'psu4', case:'case3', cooler:'cl5', monitor:'mon5', kbm:'kbm5' },
            pro: { cpu:'cpu5', mb:'mb8', ram:'ram7', gpu:'gpu6', ssd:'ssd5', psu:'psu6', case:'case6', cooler:'cl8', monitor:'mon7', kbm:'kbm7' }
        };

        let customParts = JSON.parse(localStorage.getItem('customParts') || '{}');
        let customIdCounter = parseInt(localStorage.getItem('customIdCounter') || '1000');

        function toggleTheme() {
            const body = document.body;
            const isLight = body.getAttribute('data-theme') === 'light';
            body.setAttribute('data-theme', isLight ? 'dark' : 'light');
            localStorage.setItem('theme', isLight ? 'dark' : 'light');
            toast(isLight ? '🌙 已切换深色主题' : '☀️ 已切换浅色主题');
        }

        function initTheme() {
            document.body.setAttribute('data-theme', localStorage.getItem('theme') || 'dark');
        }

        function toggleAddForm(type) {
            const form = document.getElementById('form-' + type);
            form.classList.toggle('show');
            if (form.classList.contains('show')) {
                document.getElementById('name-' + type).focus();
            }
        }

        function confirmAdd(type) {
            const name = document.getElementById('name-' + type).value.trim();
            const price = parseInt(document.getElementById('price-' + type).value);
            const watt = parseInt(document.getElementById('watt-' + type).value) || 0;

            if (!name) { toast('请输入配件名称', '⚠️'); return; }
            if (!price || price <= 0) { toast('请输入有效价格', '⚠️'); return; }

            const id = 'custom_' + (++customIdCounter);
            localStorage.setItem('customIdCounter', customIdCounter);

            if (!customParts[type]) customParts[type] = [];
            customParts[type].push({ id, name, price, watt });
            localStorage.setItem('customParts', JSON.stringify(customParts));

            addOptionToSelect(type, id, name, price, watt);
            document.getElementById('sel-' + type).value = id;
            update(type);

            document.getElementById('name-' + type).value = '';
            document.getElementById('price-' + type).value = '';
            document.getElementById('watt-' + type).value = '';
            toggleAddForm(type);
            updateManageList();
            toast('已添加: ' + name);
        }

        function addOptionToSelect(type, id, name, price, watt) {
            const select = document.getElementById('sel-' + type);
            const option = document.createElement('option');
            option.value = id;
            option.dataset.p = price;
            option.dataset.w = watt;
            option.dataset.custom = 'true';
            option.textContent = name + ' - ¥' + price.toLocaleString();
            select.appendChild(option);
        }

        function deleteCustom(type) {
            const select = document.getElementById('sel-' + type);
            const currentValue = select.value;

            if (!currentValue || !currentValue.startsWith('custom_')) {
                toast('请先选择一个自定义配件', '⚠️');
                return;
            }

            if (customParts[type]) {
                customParts[type] = customParts[type].filter(p => p.id !== currentValue);
                if (customParts[type].length === 0) delete customParts[type];
                localStorage.setItem('customParts', JSON.stringify(customParts));
            }

            const option = select.querySelector(`option[value="${currentValue}"]`);
            if (option) {
                const name = option.text.split(' - ')[0];
                option.remove();
                toast('已删除: ' + name);
            }

            select.value = '';
            update(type);
            updateManageList();
        }

        function updateDelButton(type) {
            const select = document.getElementById('sel-' + type);
            const delBtn = document.getElementById('del-' + type);
            delBtn.classList.toggle('show', select.value && select.value.startsWith('custom_'));
        }

        function initCustomParts() {
            Object.entries(customParts).forEach(([type, parts]) => {
                parts.forEach(part => addOptionToSelect(type, part.id, part.name, part.price, part.watt));
            });
            updateManageList();
        }

        function updateManageList() {
            const list = document.getElementById('manageList');
            const allCustom = [];
            Object.entries(customParts).forEach(([type, parts]) => {
                parts.forEach(part => allCustom.push({ ...part, type }));
            });

            if (allCustom.length === 0) {
                list.innerHTML = '<div class="manage-empty">暂无自定义配件</div>';
            } else {
                list.innerHTML = allCustom.map(item => `
                    <div class="manage-item">
                        <div class="manage-item-info">
                            <span class="manage-item-type">${typeNames[item.type]}</span>
                            <span class="manage-item-name">${item.name}</span>
                            <span class="manage-item-price">¥${item.price.toLocaleString()}</span>
                        </div>
                        <button class="manage-item-del" onclick="deleteFromManage('${item.type}', '${item.id}')">✕</button>
                    </div>
                `).join('');
            }
        }

        function deleteFromManage(type, id) {
            if (customParts[type]) {
                customParts[type] = customParts[type].filter(p => p.id !== id);
                if (customParts[type].length === 0) delete customParts[type];
                localStorage.setItem('customParts', JSON.stringify(customParts));
            }

            const select = document.getElementById('sel-' + type);
            const option = select.querySelector(`option[value="${id}"]`);
            if (option) {
                if (select.value === id) { select.value = ''; update(type); }
                option.remove();
            }

            updateManageList();
            toast('已删除配件');
        }

        function update(type) {
            const sel = document.getElementById('sel-' + type);
            const card = document.getElementById('card-' + type);
            const priceEl = document.getElementById('price-' + type);

            if (sel.value) {
                const opt = sel.options[sel.selectedIndex];
                selected[type] = {
                    id: sel.value,
                    name: opt.text.split(' - ')[0],
                    price: +opt.dataset.p,
                    watt: +opt.dataset.w,
                    isCustom: sel.value.startsWith('custom_')
                };
                priceEl.textContent = selected[type].price > 0 ? '¥' + selected[type].price.toLocaleString() : '免费';
                card.classList.add('selected');
            } else {
                selected[type] = null;
                priceEl.textContent = '';
                card.classList.remove('selected');
            }

            if (type !== 'giftKbm') updateDelButton(type);
            render();
        }

        function render() {
            const list = document.getElementById('configList');
            const items = Object.entries(selected).filter(([_, v]) => v);

            if (!items.length) {
                list.innerHTML = '<div class="empty-msg"><div class="empty-msg-icon">🔧</div>请从左侧选择配件<br>或点击快速方案</div>';
            } else {
                list.innerHTML = items.map(([t, c]) => `
                    <div class="config-item">
                        <span class="config-item-type">${names[t]}</span>
                        <span class="config-item-name">${c.name}${c.isCustom ? '<span class="config-item-custom">自定义</span>' : ''}${t === 'giftKbm' ? '<span class="config-item-custom" style="background:rgba(34,197,94,0.15);color:var(--green);">赠送</span>' : ''}</span>
                        <span class="config-item-price">${c.price > 0 ? '¥' + c.price.toLocaleString() : '免费'}</span>
                        <button class="config-item-remove" onclick="remove('${t}')">✕</button>
                    </div>
                `).join('');
            }

            const sub = items.reduce((s, [_, c]) => s + c.price, 0);
            const fee = parseInt(document.getElementById('fee').value) || 0;
            const totalWatt = items.reduce((s, [_, c]) => s + c.watt, 0);

            document.getElementById('subtotal').textContent = '¥' + sub.toLocaleString();
            document.getElementById('total').textContent = '¥' + (sub + fee).toLocaleString();
            document.getElementById('count').textContent = items.length;
            document.getElementById('watt').textContent = totalWatt + 'W';
            document.getElementById('total-stat').textContent = '¥' + (sub + fee).toLocaleString();

            const warning = document.getElementById('wattWarning');
            if (totalWatt > 500) {
                warning.classList.add('show');
                warning.querySelector('span').textContent = `总功耗 ${totalWatt}W,建议选择 ${Math.ceil(totalWatt * 1.3 / 100) * 100}W 以上电源`;
            } else {
                warning.classList.remove('show');
            }
        }

        function remove(type) {
            document.getElementById('sel-' + type).value = '';
            update(type);
            toast('已移除 ' + names[type]);
        }

        function clearAll() {
            Object.keys(selected).forEach(t => {
                document.getElementById('sel-' + t).value = '';
                selected[t] = null;
                document.getElementById('card-' + t).classList.remove('selected');
                document.getElementById('price-' + t).textContent = '';
                if (t !== 'giftKbm') updateDelButton(t);
            });
            render();
            toast('已清空配置');
        }

        function loadPreset(name) {
            clearAll();
            const p = presets[name];
            Object.entries(p).forEach(([t, v]) => {
                document.getElementById('sel-' + t).value = v;
                update(t);
            });
            toast('已加载 ' + {office:'办公',office1:'办公1',office2:'办公2',gaming:'游戏',pro:'创作'}[name] + ' 方案');
        }

        function copyConfig(mode) {
            const items = Object.entries(selected).filter(([_, v]) => v);
            if (!items.length) return toast('请先选择配件', '⚠️');

            const sub = items.reduce((s, [_, c]) => s + c.price, 0);
            const fee = parseInt(document.getElementById('fee').value) || 0;
            const note = document.getElementById('note').value.trim();

            let txt = '【电脑配置单】\n';
            if (mode === 'full') {
                items.forEach(([t, c]) => txt += `${names[t]}: ${c.name} ${c.price > 0 ? '¥' + c.price : '免费'}${c.isCustom ? ' [自定义]' : ''}${t === 'giftKbm' ? ' [赠送]' : ''}\n`);
                txt += `─────────\n小计: ¥${sub.toLocaleString()}\n服务费: ¥${fee}\n总计: ¥${(sub + fee).toLocaleString()}${note ? `\n说明: ${note}` : ''}`;
            } else {
                items.forEach(([t, c]) => txt += `${names[t]}: ${c.name}${c.isCustom ? ' [自定义]' : ''}${t === 'giftKbm' ? ' [赠送]' : ''}\n`);
                txt += `─────────\n总计: ¥${(sub + fee).toLocaleString()}${note ? `\n说明: ${note}` : ''}`;
            }

            if (navigator.clipboard && navigator.clipboard.writeText) {
                navigator.clipboard.writeText(txt).then(() => toast(mode === 'full' ? '详细配置已复制' : '简洁配置已复制'));
            } else {
                const textarea = document.createElement('textarea');
                textarea.value = txt;
                textarea.style.position = 'fixed';
                textarea.style.opacity = '0';
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);
                toast(mode === 'full' ? '详细配置已复制' : '简洁配置已复制');
            }
        }

        function exportConfig(mode) {
            const items = Object.entries(selected).filter(([_, v]) => v);
            if (!items.length) return toast('请先选择配件', '⚠️');

            const sub = items.reduce((s, [_, c]) => s + c.price, 0);
            const fee = parseInt(document.getElementById('fee').value) || 0;
            const note = document.getElementById('note').value.trim();

            let html;
            if (mode === 'full') {
                html = `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>配置单</title><style>body{font-family:sans-serif;max-width:600px;margin:40px auto;padding:20px}h1{text-align:center;border-bottom:2px solid #0891b2;padding-bottom:10px}table{width:100%;border-collapse:collapse;margin:20px 0}th,td{padding:10px;text-align:left;border-bottom:1px solid #ddd}th{background:#f5f5f5}.r{text-align:right;font-weight:bold;color:#16a34a}.t{font-size:1.2em;color:#db2777}.custom{font-size:0.8em;color:#ea580c;margin-left:4px}.gift{font-size:0.8em;color:#22c55e;margin-left:4px}</style></head><body><h1>🖥️ 电脑配置单</h1><p style="text-align:center;color:#666">开平蓝动力电脑 报价表 ${new Date().toLocaleDateString()}</p><table><tr><th>配件</th><th>型号</th><th class="r">价格</th></tr>`;
                items.forEach(([t, c]) => {
                    html += `<tr><td>${names[t]}</td><td>${c.name}${c.isCustom ? '<span class="custom">[自定义]</span>' : ''}${t === 'giftKbm' ? '<span class="gift">[赠送]</span>' : ''}</td><td class="r">${c.price > 0 ? '¥' + c.price.toLocaleString() : '免费'}</td></tr>`;
                });
                html += `<tr><td colspan="2">小计</td><td class="r">¥${sub.toLocaleString()}</td></tr><tr><td colspan="2">服务费</td><td class="r">¥${fee}</td></tr><tr><td colspan="2" class="t">总计</td><td class="r t">¥${(sub + fee).toLocaleString()}</td></tr>${note ? `<tr><td colspan="3">说明:${note}</td></tr>` : ''}`;
            } else {
                html = `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>配置单</title><style>body{font-family:sans-serif;max-width:600px;margin:40px auto;padding:20px}h1{text-align:center;border-bottom:2px solid #0891b2;padding-bottom:10px}table{width:100%;border-collapse:collapse;margin:20px 0}th,td{padding:10px;text-align:left;border-bottom:1px solid #ddd}th{background:#f5f5f5}.r{text-align:right;font-weight:bold;color:#16a34a}.t{font-size:1.2em;color:#db2777}.custom{font-size:0.8em;color:#ea580c;margin-left:4px}.gift{font-size:0.8em;color:#22c55e;margin-left:4px}</style></head><body><h1>🖥️ 电脑配置单</h1><p style="text-align:center;color:#666">开平蓝动力电脑 报价表 ${new Date().toLocaleDateString()}</p><table><tr><th>配件</th><th>型号</th></tr>`;
                items.forEach(([t, c]) => {
                    html += `<tr><td>${names[t]}</td><td>${c.name}${c.isCustom ? '<span class="custom">[自定义]</span>' : ''}${t === 'giftKbm' ? '<span class="gift">[赠送]</span>' : ''}</td></tr>`;
                });
                html += `<tr><td class="t">总计</td><td class="r t">¥${(sub + fee).toLocaleString()}</td></tr>${note ? `<tr><td colspan="2">说明:${note}</td></tr>` : ''}`;
            }

            html += `</table></body></html>`;

            const a = document.createElement('a');
            a.href = URL.createObjectURL(new Blob([html], {type:'text/html'}));
            a.download = '配置单_' + (mode === 'full' ? '详细_' : '简洁_') + new Date().toISOString().slice(0,10) + '.html';
            a.click();
            toast(mode === 'full' ? '详细配置单已导出' : '简洁配置单已导出');
        }

        function toast(msg, icon = '✅') {
            const t = document.getElementById('toast');
            document.getElementById('toastMsg').textContent = msg;
            document.getElementById('toastIcon').textContent = icon;
            t.classList.add('show');
            setTimeout(() => t.classList.remove('show'), 2000);
        }

        function initPartsData() {
            const partTypes = ['cpu', 'mb', 'ram', 'gpu', 'ssd', 'psu', 'case', 'cooler', 'monitor', 'kbm', 'giftKbm'];
            partTypes.forEach(type => {
                const select = document.getElementById('sel-' + type);
                if (select && partsData[type]) {
                    partsData[type].forEach(part => {
                        const option = document.createElement('option');
                        option.value = part.id;
                        option.dataset.p = part.price;
                        option.dataset.w = part.watt;
                        option.textContent = part.name + (part.price > 0 ? ' - ¥' + part.price.toLocaleString() : ' - 免费');
                        select.appendChild(option);
                    });
                }
            });
        }

        initPartsData();
        initTheme();
        initCustomParts();

        document.querySelectorAll('.add-input').forEach(input => {
            input.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') confirmAdd(input.id.split('-')[1]);
            });
        });
    </script>
</body>
</html>

数据data.js

html 复制代码
const partsData = {
    cpu: [
        { id: 'cpu1', name: 'Intel i5-8500 (6核6线程)', price: 390, watt: 65 },
        { id: 'cpu2', name: 'Intel i3-10105 (4核8线程)', price: 610, watt: 65 },
        { id: 'cpu3', name: 'i5-13600KF (14核20线程)', price: 1599, watt: 125 },
        { id: 'cpu4', name: 'i7-13700KF (16核24线程)', price: 2499, watt: 125 },
        { id: 'cpu5', name: 'i9-13900KF (24核32线程)', price: 3999, watt: 150 },
        { id: 'cpu6', name: 'R5 5600 (6核12线程)', price: 699, watt: 65 },
        { id: 'cpu7', name: 'R5 7600X (6核12线程)', price: 1299, watt: 105 },
        { id: 'cpu8', name: 'R7 7700X (8核16线程)', price: 1999, watt: 105 },
        { id: 'cpu9', name: 'R9 7900X (12核24线程)', price: 3299, watt: 170 },
        { id: 'cpu10', name: 'Intel i5-8500 (6核6线程)', price: 390, watt: 65 },
        { id: 'cpu11', name: 'i3-12100 散片 (4核8线程)', price: 965, watt: 65 }
    ],
    mb: [
        { id: 'mb1', name: '昂达 9D3-DVH', price: 305, watt: 50 },
        { id: 'mb2', name: '昂达 H510E (支持10代U)', price: 300, watt: 50 },
        { id: 'mb3', name: '华硕 B760M-PLUS WiFi D5', price: 1299, watt: 60 },
        { id: 'mb4', name: '微星 Z790 EDGE WiFi', price: 1999, watt: 70 },
        { id: 'mb5', name: '华硕 B550M-K', price: 549, watt: 50 },
        { id: 'mb6', name: '微星 B550M MORTAR WiFi', price: 899, watt: 50 },
        { id: 'mb7', name: '华硕 B650M-PLUS WiFi', price: 1599, watt: 60 },
        { id: 'mb8', name: '华硕 X670E-E WiFi', price: 2999, watt: 80 },
        { id: 'mb9', name: '昂达 9D3-DVH', price: 305, watt: 50 },
        { id: 'mb10', name: '铭瑄 H610 M-R', price: 325, watt: 50 }
    ],
    ram: [
        { id: 'ram1', name: '昂达 DDR3 8G', price: 150, watt: 5 },
        { id: 'ram2', name: '威刚 DDR4 8G 3200', price: 490, watt: 5 },
        { id: 'ram3', name: '32GB(16×2) DDR4 3600', price: 599, watt: 5 },
        { id: 'ram4', name: '16GB(8×2) DDR5 5200', price: 399, watt: 6 },
        { id: 'ram5', name: '32GB(16×2) DDR5 5600', price: 699, watt: 6 },
        { id: 'ram6', name: '32GB(16×2) DDR5 6000', price: 1299, watt: 8 },
        { id: 'ram7', name: '64GB(32×2) DDR5 6000', price: 1999, watt: 10 }
    ],
    gpu: [
        { id: 'gpu1', name: 'RTX 3050 8GB', price: 899, watt: 130 },
        { id: 'gpu2', name: 'RTX 4060 8GB', price: 1799, watt: 170 },
        { id: 'gpu3', name: 'RTX 4060 Ti 8GB', price: 2999, watt: 200 },
        { id: 'gpu4', name: 'RTX 4070 12GB', price: 4499, watt: 285 },
        { id: 'gpu5', name: 'RTX 4070 Ti SUPER 16GB', price: 5999, watt: 320 },
        { id: 'gpu6', name: 'RTX 4080 SUPER 16GB', price: 9999, watt: 450 },
        { id: 'gpu7', name: 'RTX 4090 24GB', price: 13999, watt: 450 },
        { id: 'gpu8', name: 'RX 7600 8GB', price: 1599, watt: 150 },
        { id: 'gpu9', name: 'RX 7800 XT 16GB', price: 3299, watt: 263 },
        { id: 'gpu10', name: 'RX 7900 XTX 24GB', price: 5499, watt: 300 }
    ],
    ssd: [
        { id: 'ssd1', name: '昂达 256G SATA固态', price: 295, watt: 5 },
        { id: 'ssd2', name: '三星 980 1TB NVMe', price: 499, watt: 5 },
        { id: 'ssd3', name: '三星 980 PRO 1TB PCIe4', price: 799, watt: 7 },
        { id: 'ssd4', name: '三星 990 PRO 2TB PCIe4', price: 1299, watt: 7 },
        { id: 'ssd5', name: '三星 990 PRO 4TB PCIe4', price: 2499, watt: 10 },
        { id: 'hdd1', name: '西数蓝盘 1TB 机械', price: 299, watt: 8 },
        { id: 'hdd2', name: '西数蓝盘 2TB 机械', price: 499, watt: 8 },
        { id: 'ssd7', name: '威刚 580 240G 固态', price: 368, watt: 3 },
        { id: 'ssd8', name: '威刚 M.2 256G 固态', price: 420, watt: 3 }
    ],
    psu: [
        { id: 'psu1', name: '小牛 300W', price: 70, watt: 0 },
        { id: 'psu2', name: '航嘉 450W', price: 165, watt: 0 },
        { id: 'psu3', name: '海韵 650W 金牌', price: 549, watt: 0 },
        { id: 'psu4', name: '海韵 750W 金牌', price: 699, watt: 0 },
        { id: 'psu5', name: '海韵 850W 金牌', price: 899, watt: 0 },
        { id: 'psu6', name: '海韵 1000W 钛金', price: 1199, watt: 0 },
        { id: 'psu7', name: '海韵 1300W 钛金', price: 1599, watt: 0 },
        { id: 'psu8', name: '小牛 300W', price: 70, watt: 0 }
    ],
    case: [
        { id: 'case1', name: '小机箱', price: 40, watt: 0 },
        { id: 'case2', name: '中机箱', price: 75, watt: 0 },
        { id: 'case3', name: '游戏机箱', price: 95, watt: 0 },
        { id: 'case4', name: '联力 O11D EVO', price: 799, watt: 0 },
        { id: 'case5', name: '追风者 P600S', price: 1299, watt: 0 },
        { id: 'case6', name: '华硕 ROG Helios', price: 1999, watt: 0 },
        { id: 'case7', name: '小机箱', price: 30, watt: 0 }
    ],
    cooler: [
        { id: 'cl1', name: '青鸟3 散热器', price: 14, watt: 3 },
        { id: 'cl2', name: '4铜管 散热器', price: 85, watt: 3 },
        { id: 'cl3', name: '猫头鹰 NH-U12S', price: 299, watt: 3 },
        { id: 'cl4', name: '利民 FC140 双塔', price: 399, watt: 5 },
        { id: 'cl5', name: '九州风神 240水冷', price: 349, watt: 8 },
        { id: 'cl6', name: 'NZXT X53 240水冷', price: 599, watt: 10 },
        { id: 'cl7', name: '华硕 LC II 360水冷', price: 899, watt: 12 },
        { id: 'cl8', name: 'NZXT Z73 360水冷', price: 1499, watt: 15 }
    ],
    monitor: [
        { id: 'mon1', name: 'AOC 24B36HE 24', price: 415, watt: 25 },
        { id: 'mon2', name: '联想 27寸 显示器', price: 515, watt: 35 },
        { id: 'mon3', name: '戴尔 S2722QC 27" 4K IPS', price: 1499, watt: 40 },
        { id: 'mon4', name: '华硕 VG28UQL1A 28" 4K 144Hz', price: 1999, watt: 45 },
        { id: 'mon5', name: 'LG 27GP850 27" 2K 180Hz NanoIPS', price: 2999, watt: 50 },
        { id: 'mon6', name: '三星 玄龙骑士 G7 32" 2K 240Hz', price: 3999, watt: 60 },
        { id: 'mon7', name: '华硕 ROG PG32UQ 32" 4K 144Hz', price: 5999, watt: 80 },
        { id: 'mon8', name: 'LG 42C3 42" OLED 4K 120Hz', price: 9999, watt: 100 }
    ],
    kbm: [
        { id: 'kbm1', name: '双飞燕 有线键鼠', price: 55, watt: 2 },
        { id: 'kbm2', name: '罗技 MK270 无线键鼠套装', price: 149, watt: 3 },
        { id: 'kbm3', name: '雷蛇 噬魂金蝎 有线游戏套装', price: 249, watt: 5 },
        { id: 'kbm4', name: '罗技 G213+G102 游戏键鼠', price: 399, watt: 5 },
        { id: 'kbm5', name: '雷蛇 黑寡妇蜘蛛V3+毒蝰迷你', price: 599, watt: 8 },
        { id: 'kbm6', name: '海盗船 K70 RGB MK.2+M65 Pro', price: 899, watt: 10 },
        { id: 'kbm7', name: '罗技 G915 TKL+G Pro X Superlight', price: 1299, watt: 12 },
        { id: 'kbm8', name: '雷蛇 猎魂光蛛V2+毒蝰V2 Pro', price: 1999, watt: 15 }
    ],
    giftKbm: [
        { id: 'gkbm1', name: '赠送: 有线键鼠套装', price: 0, watt: 2 },
        { id: 'gkbm2', name: '赠送: 键鼠套装+鼠标垫+排插+小音箱', price: 0, watt: 2 },
        { id: 'gkbm3', name: '赠送: 游戏键鼠套装', price: 0, watt: 3 },
        { id: 'gkbm4', name: '赠送: 机械键盘+游戏鼠标', price: 0, watt: 5 }
    ]
};
相关推荐
放下华子我只抽RuiKe52 小时前
NLP自然语言处理硬核实战笔记
前端·人工智能·机器学习·自然语言处理·开源·集成学习·easyui
工程师老罗2 小时前
lvgl有哪些布局?
前端·javascript·html
好家伙VCC2 小时前
# 发散创新:用Selenium实现自动化测试的智能断言与异常处理策略在现代Web应用开发中,*
java·前端·python·selenium
关中老四2 小时前
【原生JS甘特图MZGantt 】如何给父任务设置独立进度条
前端·javascript·甘特图
英俊潇洒美少年2 小时前
react 18 的fiber算法
前端·算法·react.js
xiegwei2 小时前
android Compose 图片星星评分组件
android·前端·elementui
小鹿软件办公3 小时前
Firefox 149 正式推送:多任务处理升级,五大新功能详解
前端·firefox
evering3 小时前
遍历备份 Chrome | Edge 浏览器插件目录
前端·chrome·crx
WiChP3 小时前
【V0.1B4】从零开始的2D游戏引擎开发之路
前端·javascript·游戏引擎