装机配置单系统 html 单文件版

27 阅读18分钟

图:

image.png

代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>装机配置单</title>
    <script src="https://cdn.sheetjs.com/xlsx-0.19.3/package/dist/xlsx.full.min.js"></script>
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ccc;
            padding: 4px;
            text-align: left;
        }
        th {
            background-color: #f0f0f0;
        }
        th:nth-child(2), td:nth-child(2) {
            width: 80px;
            min-width: 60px;
            max-width: 120px;
        }
        th:nth-child(3), td:nth-child(3),
        th:nth-child(7), td:nth-child(7) {
            width: 280px;
            min-width: 160px;
            max-width: 380px;
        }
        .total-row {
            background-color: #e6f3ff;
        }
        input {
            width: 90%;
            padding: 4px;
            border: 1px solid #ddd;
        }
        .calculate-btn {
            margin: 20px 0;
            padding: 10px 20px;
            background-color: #4CAF50;
            color: white;
            border: none;
            cursor: pointer;
        }
        .calculate-btn:hover {
            background-color: #45a049;
        }
        .export-btn {
            background-color: #2196F3;
        }
        .export-btn:hover {
            background-color: #1976D2;
        }
        .delete-btn {
            background-color: #f44336;
            color: white;
            border: none;
            padding: 4px 8px;
            cursor: pointer;
            margin-right: 5px;
        }
        .delete-btn:hover {
            background-color: #da190b;
        }
        @media print {
            .calculate-btn, .delete-btn {
                display: none;
            }
            
            body {
                margin: 0;
                padding: 20px;
            }
            
            table {
                width: 100%;
                border-collapse: collapse;
            }
            
            th, td {
                border: 1px solid #000;
                padding: 8px;
            }
            
            input {
                border: none;
                width: 100%;
                padding: 0;
            }
            
            thead {
                display: table-header-group;
            }
            
            tr {
                page-break-inside: avoid;
            }
            .print-hide {
                display: none !important;
            }
        }
        .print-btn {
            background-color: #607D8B;
        }
        .print-btn:hover {
            background-color: #455A64;
        }
        select {
            width: 90%;
            padding: 4px;
            border: 1px solid #ddd;
        }
        .custom-input-container {
            display: none;
            margin-top: 5px;
        }
        
        .custom-input-container.show {
            display: block;
        }
        
        .custom-input {
            width: 85%;
            padding: 4px;
            border: 1px solid #ddd;
        }
        .amount1[value]:not([value="0"]):not([value=""]),
        .amount2[value]:not([value="0"]):not([value=""]) {
            color: red;
        }
        .second-column {
            display: none;
        }
        .show-second-column .second-column {
            display: table-cell;
        }
    </style>
    <style>
        @page {
            margin: 0;
        }
    </style>
</head>
<body>
    <h2>1.装机配置单</h2>
    <p>日期: <input type="date" id="date"></p>
    <div id="topTotalInfo" style="font-weight:bold;margin-bottom:10px;"></div>
    <p class="print-hide">
        <label>
            <input type="checkbox" id="showSecondColumn" onchange="toggleSecondColumn()">
            显示第二列配置
        </label>
    </p>
    <table id="configTable">
        <tr>
            <th>操作</th>
            <th>配件名称</th>
            <th>品牌型号[1]</th>
            <th>数量[1]</th>
            <th>单价[1]</th>
            <th>金额[1]</th>
            <th class="second-column">品牌型号[2]</th>
            <th class="second-column">数量[2]</th>
            <th class="second-column">单价[2]</th>
            <th class="second-column">金额[2]</th>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="CPU"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="主板"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="内存"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="硬盘"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="SSD固态盘"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="显卡"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="机箱"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="电源"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="显示器"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="键鼠套装"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="键盘"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="鼠标"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="散热器"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="音箱"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr>
            <td><button class="delete-btn" onclick="deleteRow(this)">删除</button></td>
            <td><input type="text" value="光存储"></td>
            <td><input type="text" value=""></td>
            <td><input type="number" class="qty1" value="0"></td>
            <td><input type="number" class="price1" value="0"></td>
            <td><input type="number" class="amount1" readonly></td>
            <td class="second-column"><input type="text" value=""></td>
            <td class="second-column"><input type="number" class="qty2" value="0"></td>
            <td class="second-column"><input type="number" class="price2" value="0"></td>
            <td class="second-column"><input type="number" class="amount2" readonly></td>
        </tr>
        <tr class="total-row">
            <td colspan="3">数量[1]:<span id="qty_total1">0</span></td>
            <td colspan="2"></td>
            <td>合计[1]:<span id="total1">0</span></td>
            <td class="second-column" colspan="2">数量[2]:<span id="qty_total2">0</span></td>
            <td class="second-column"></td>
            <td class="second-column">合计[2]:<span id="total2">0</span></td>
        </tr>
    </table>

    <button class="calculate-btn export-btn" onclick="exportToExcel()">导出Excel</button>
    <button class="calculate-btn print-btn" onclick="printTable()">打印表格</button>
    <button class="calculate-btn" onclick="showInfoModal()">显示信息</button>
    <button class="calculate-btn" onclick="showInfoModalNoPrice()">显示信息(无单价金额)</button>
    <button class="calculate-btn" onclick="showInfoModalOrder()">显示信息(订货用)</button>
    <button class="calculate-btn print-btn" onclick="printTableNoPrice()">打印(无单价金额)</button>

    <!-- 信息弹窗 -->
    <div id="infoModal" style="display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.3);z-index:9999;align-items:center;justify-content:center;">
        <div style="background:#fff;padding:20px;border-radius:8px;min-width:600px;max-width:1000px;max-height:90vh;box-shadow:0 2px 8px #888;display:flex;flex-direction:column;align-items:stretch;">
            <h3 style="margin-top:0;">配置信息</h3>
            <textarea id="infoTextArea" style="width:100%;height:500px;resize:vertical;margin-bottom:12px;font-size:16px;font-family:monospace;white-space:pre;overflow:auto;" wrap="off"></textarea>
            <button onclick="closeInfoModal()" style="align-self:flex-end;padding:6px 18px;">关闭</button>
        </div>
    </div>

    <script>
        // 扩展配件选项数组,包含所有配件
        const partOptions = {
            CPU: {
                option1: [
                    {model: "I3 8100", price: 150},
                    {model: "I3 12100", price: 620},
                    {model: "I3 12100F", price: 470},
                    {model: "I3 13100", price: 625},
                    {model: "I3 13100F", price: 305},
                    {model: "I5 12400", price: 835},
                    {model: "I5 12400F", price: 645},
                    {model: "I5 13400F", price: 905},
                    {model: "i7-13700F散片", price: 1610},
                    {model: "i7-13700散片", price: 2050},
                    {model: "I5 12600KF散片", price: 935},
                    {model: "AMD锐龙 R5 5600", price: 545},
                    {model: "R5 7500F散片", price: 875},
                    {model: "R5 9600X散片", price: 1270},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "Intel酷睿 i3-10100", price: 520},
                    {model: "Intel酷睿 i3-12100", price: 585},
                    {model: "Intel酷睿 i5-12400", price: 735},
                    {model: "其他", price: 0}
                ]
            },
            主板: {
                option1: [
                    {model: "昂达94D-DVH", price: 295},
                    {model: "技嘉H610M", price: 465},
                    {model: "技嘉B760M-H D4", price: 515},
                    {model: "技嘉B760M D2H DDR4", price: 550},
                    {model: "技嘉 A520M K V2 D4", price: 310},
                    {model: "铭瑄MS 挑战者B760M D4", price: 520},
                    {model: "铭瑄MS 挑战者B650M WIFI D5", price: 590},
                    {model: "铭瑄MS B550M GAMING WIFI ICE D4", price: 590},
                    {model: "技嘉B650M H", price: 550},
                    {model: "铭瑄H610M-R", price: 335},
                    {model: "昂达H610E-V D4", price: 295},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "华硕PRIME H610M-K(HDMI)", price: 499},
                    {model: "其他", price: 0}
                ]
            },
            内存: {
                option1: [
                    {model: "金百达 3200 DDR4 16G 银", price: 545},
                    {model: "金百达 DDR4 3600 16G 银", price: 235},
                    {model: "阿斯加特 弗雷 3200 DDR4 16G", price: 195},
                    {model: "金百达DDR5-16G6000银爵马甲", price: 365},
                    {model: "金百达DDR5-32G6000银爵马甲", price: 670},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "威刚DDR4 16GB", price: 565},
                    {model: "其他", price: 0}
                ]
            },
            硬盘: {
                option1: [
                    {model: "西部数据蓝盘 1TB", price: 585},
                    {model: "西部数据蓝盘 2TB", price: 595},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "西部数据蓝盘 2TB", price: 595},
                    {model: "其他", price: 0}
                ]
            },
            "SSD固态盘": {
                option1: [
                    {model: "金士顿 m.2 512G", price: 450},
                    {model: "西数SN5000 1TB M.2", price: 470},
                    {model: "昂达M.2 512G", price: 360},
                    {model: "梵想 SSD 512G", price: 360},
                    {model: "威刚 m.2 512G", price: 425},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "闪迪 240 SSD", price: 159},
                    {model: "其他", price: 0}
                ]
            },
            显卡: {
                option1: [
                    {model: "七彩虹GT1030", price: 459},
                    {model: "铭瑄MS GTX1050TI TF 4G单风扇", price: 815},
                    {model: "七彩虹战斧RTX3060 DUO 12GD6", price: 1880},
                    {model: "七彩虹战斧3050 DUO 8G", price: 1380},
                    {model: "七彩虹GT730 2G", price: 295},
                    {model: "七彩虹GT730 4G", price: 315},
                    {model: "昂达GT730 2G", price: 265},
                    {model: "铭瑄R5 220 1G", price: 125},
                    {model: "铭瑄MS GTX1050TI TF 4G单风扇", price: 815},
                    {model: "七彩虹RTX 5060 8G", price: 2480},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "七彩虹GT1030", price: 459},
                    {model: "其他", price: 0}
                ]
            },
            机箱: {
                option1: [
                    {model: "金河田 游戏机箱", price: 95},
                    {model: "金河田 觉醒侧透", price: 90},
                    {model: "金刚之星", price: 75},
                    {model: "华硕机箱", price: 95},
                    {model: "小机箱", price: 40},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "金河田", price: 75},
                    {model: "其他", price: 0}
                ]
            },
            电源: {
                option1: [
                    {model: "长城300W", price: 115},
                    {model: "航嘉300W", price: 115},
                    {model: "航嘉ECO650 650W", price: 230},
                    {model: "航嘉ECO500 500W", price: 210},
                    {model: "OX 300W", price: 70},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "300W电源", price: 75},
                    {model: "其他", price: 0}
                ]
            },
            显示器: {
                option1: [
                    {model: "联想 27寸 显示器", price: 485},
                    {model: "联想 24寸 显示器", price: 385},
                    {model: "AOC 24寸 显示器", price: 410},
                    {model: "AOC aoc 32寸 Q32V3S/BS 显示器", price: 1185},
                    {model: "AOC 24寸 显示器", price: 410},
                    {model: "AOC 27寸 27B36H显示器", price: 515},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "联想 24寸 显示器", price: 599},
                    {model: "其他", price: 0}
                ]
            },
            键鼠套装: {
                option1: [
                    {model: "双飞燕键鼠套装", price: 75},
                    {model: "普通键鼠套装", price: 30},
                    {model: "DT键鼠套装", price: 38},
                    {model: "游戏无线键鼠套装", price: 125},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "无线光电套装", price: 69},
                    {model: "其他", price: 0}
                ]
            },
            键盘: {
                option1: [
                    {model: "双飞燕键盘", price: 25},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "无线键盘", price: 49},
                    {model: "其他", price: 0}
                ]
            },
            鼠标: {
                option1: [
                    {model: "双飞燕鼠标", price: 15},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "无线鼠标", price: 29},
                    {model: "其他", price: 0}
                ]
            },
            散热器: {
                option1: [
                    {model: "超频三散热器", price: 15},
                    {model: "双铜管散热器", price: 21},
                    {model: "四铜管散热器", price: 37},
                    {model: "六铜管散热器", price: 65},
                    {model: "大水牛寒战240 水冷散热器", price: 159},
                    {model: "大水牛寒战120 水冷散热器", price: 109},
                    {model: "六铜管散热器", price: 65},
                    {model: "利民AE240 双排水冷 工包", price: 180},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "九州风神散热器", price: 39},
                    {model: "其他", price: 0}
                ]
            },
            音箱: {
                option1: [
                    {model: "普通音箱", price: 30},
                    {model: "小音箱", price: 15},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "无线网卡", price: 39},
                    {model: "其他", price: 0}
                ]
            },
            光存储: {
                option1: [
                    {model: "DVD刻录机", price: 100},
                    {model: "DVD光驱", price: 90},
                    {model: "其他", price: 0}
                ],
                option2: [
                    {model: "DVD刻录机", price: 100},
                    {model: "其他", price: 0}
                ]
            }
        };

        // 处理型号选择变化 - 修改为选择型号后自动设置数量为1
        function handleModelChange(select, priceClass) {
            const selectedOption = select.options[select.selectedIndex];
            const row = select.closest('tr');
            const priceInput = row.querySelector('.' + priceClass);
            const customContainer = select.parentNode.querySelector('.custom-input-container');
            
            // 获取对应的数量输入框
            const qtyClass = priceClass === 'price1' ? 'qty1' : 'qty2';
            const qtyInput = row.querySelector('.' + qtyClass);
            
            if (selectedOption.value === "其他") {
                customContainer.classList.add('show');
                priceInput.value = 0;
                // 如果是"其他"选项,不自动设置数量
            } else {
                if (customContainer) {
                    customContainer.classList.remove('show');
                }
                if (selectedOption.dataset.price) {
                    priceInput.value = selectedOption.dataset.price;
                }
                
                // 只有当有实际选择型号且数量为0时,才自动设置为1
                if (selectedOption.value && selectedOption.value !== "" && 
                    (!qtyInput.value || qtyInput.value == "0")) {
                    qtyInput.value = 1;
                }
            }
            
            calculateTotals();
        }

        // 自定义输入处理
        function handleCustomInput(input, select) {
            select.value = "其他";
            // 自定义输入时,如果数量为0,自动设置为1
            const row = input.closest('tr');
            const isSecondColumn = input.closest('td:nth-child(7)') !== null;
            const qtyClass = isSecondColumn ? 'qty2' : 'qty1';
            const qtyInput = row.querySelector('.' + qtyClass);
            
            if (input.value && (!qtyInput.value || qtyInput.value == "0")) {
                qtyInput.value = 1;
            }
            
            calculateTotals();
        }

        // 生成选择框HTML
        function createSelectHtml(options, priceClass, index) {
            return `
                <select onchange="handleModelChange(this, '${priceClass}')" style="width: 90%;">
                    <option value="" selected>请选择型号</option>
                    ${options.map(item => 
                        `<option value="${item.model}" data-price="${item.price}">${item.model}</option>`
                    ).join('')}
                </select>
                <div class="custom-input-container">
                    <input type="text" 
                           class="custom-input" 
                           placeholder="请输入型号"
                           oninput="handleCustomInput(this, this.parentNode.previousElementSibling)">
                </div>
            `;
        }

        // 初始化表格
        document.addEventListener('DOMContentLoaded', function() {
            const rows = document.querySelectorAll('#configTable tr:not(:first-child)');
            rows.forEach(row => {
                const partNameInput = row.querySelector('td:nth-child(2) input');
                if (partNameInput && partOptions[partNameInput.value]) {
                    const td3 = row.querySelector('td:nth-child(3)');
                    const td7 = row.querySelector('td:nth-child(7)');
                    
                    const originalModel1 = row.querySelector('td:nth-child(3) input')?.value || '';
                    const originalModel2 = row.querySelector('td:nth-child(7) input')?.value || '';
                    const originalPrice1 = row.querySelector('.price1')?.value || '0';
                    const originalPrice2 = row.querySelector('.price2')?.value || '0';
                    const originalQty1 = row.querySelector('.qty1')?.value || '0';
                    const originalQty2 = row.querySelector('.qty2')?.value || '0';
                    
                    td3.innerHTML = createSelectHtml(partOptions[partNameInput.value].option1, 'price1', 1);
                    td7.innerHTML = createSelectHtml(partOptions[partNameInput.value].option2, 'price2', 2);
                    
                    // 设置第一列的值
                    const select1 = td3.querySelector('select');
                    if (select1) {
                        const option1 = Array.from(select1.options).find(opt => opt.value === originalModel1);
                        if (option1) {
                            select1.value = originalModel1;
                            // 如果原来有值,恢复原来的数量
                            if (originalModel1 && originalQty1 !== undefined) {
                                row.querySelector('.qty1').value = originalQty1;
                            }
                        } else if (originalModel1) {
                            select1.value = "其他";
                            const customInput1 = td3.querySelector('.custom-input');
                            customInput1.value = originalModel1;
                            td3.querySelector('.custom-input-container').classList.add('show');
                            // 如果原来有值,恢复原来的数量
                            if (originalModel1 && originalQty1 !== undefined) {
                                row.querySelector('.qty1').value = originalQty1;
                            }
                        }
                    }
                    
                    // 设置第二列的值
                    const select2 = td7.querySelector('select');
                    if (select2) {
                        const option2 = Array.from(select2.options).find(opt => opt.value === originalModel2);
                        if (option2) {
                            select2.value = originalModel2;
                            // 如果原来有值,恢复原来的数量
                            if (originalModel2 && originalQty2 !== undefined) {
                                row.querySelector('.qty2').value = originalQty2;
                            }
                        } else if (originalModel2) {
                            select2.value = "其他";
                            const customInput2 = td7.querySelector('.custom-input');
                            customInput2.value = originalModel2;
                            td7.querySelector('.custom-input-container').classList.add('show');
                            // 如果原来有值,恢复原来的数量
                            if (originalModel2 && originalQty2 !== undefined) {
                                row.querySelector('.qty2').value = originalQty2;
                            }
                        }
                    }
                    
                    // 设置价格
                    const price1Input = row.querySelector('.price1');
                    const price2Input = row.querySelector('.price2');
                    if (price1Input) price1Input.value = originalPrice1;
                    if (price2Input) price2Input.value = originalPrice2;
                }
            });
            
            calculateTotals();

            // 页面加载时设置日期为当前系统日期
            const dateInput = document.getElementById('date');
            if (dateInput) {
                const today = new Date();
                const yyyy = today.getFullYear();
                const mm = String(today.getMonth() + 1).padStart(2, '0');
                const dd = String(today.getDate()).padStart(2, '0');
                dateInput.value = `${yyyy}-${mm}-${dd}`;
            }

            // 监听数量输入框变化,允许用户手动修改数量
            const table = document.getElementById('configTable');
            table.addEventListener('input', function(e) {
                if (e.target.matches('.qty1, .qty2, .price1, .price2')) {
                    calculateTotals();
                }
            });
        });

        // 更新配件选项
        function updatePartOptions(select) {
            const row = select.closest('tr');
            const partName = select.value;
            
            if (partOptions[partName]) {
                const td3 = row.querySelector('td:nth-child(3)');
                const td7 = row.querySelector('td:nth-child(7)');
                
                td3.innerHTML = createSelectHtml(partOptions[partName].option1, 'price1', 1);
                td7.innerHTML = createSelectHtml(partOptions[partName].option2, 'price2', 2);
                
                // 重置价格和数量
                row.querySelector('.price1').value = '0';
                row.querySelector('.price2').value = '0';
                row.querySelector('.qty1').value = '0';
                row.querySelector('.qty2').value = '0';
                
                calculateTotals();
            }
        }

        // 修改calculateTotals函数
        function calculateTotals() {
            let total1 = 0;
            let total2 = 0;
            let qtyTotal1 = 0;
            let qtyTotal2 = 0;
            
            const rows = document.querySelectorAll('#configTable tr:not(:first-child):not(:last-child)');
            
            rows.forEach(row => {
                // 第一列计算
                const qty1 = parseFloat(row.querySelector('.qty1')?.value) || 0;
                const price1 = parseFloat(row.querySelector('.price1')?.value) || 0;
                const amount1 = qty1 * price1;
                const amount1Input = row.querySelector('.amount1');
                if (amount1Input) {
                    amount1Input.value = amount1.toFixed(2);
                    amount1Input.style.color = amount1 > 0 ? 'red' : '';
                    total1 += amount1;
                    qtyTotal1 += qty1;
                }

                // 第二列计算
                const qty2 = parseFloat(row.querySelector('.qty2')?.value) || 0;
                const price2 = parseFloat(row.querySelector('.price2')?.value) || 0;
                const amount2 = qty2 * price2;
                const amount2Input = row.querySelector('.amount2');
                if (amount2Input) {
                    amount2Input.value = amount2.toFixed(2);
                    amount2Input.style.color = amount2 > 0 ? 'red' : '';
                    total2 += amount2;
                    qtyTotal2 += qty2;
                }
            });

            document.getElementById('total1').textContent = total1.toFixed(2);
            document.getElementById('total2').textContent = total2.toFixed(2);
            document.getElementById('qty_total1').textContent = qtyTotal1;
            document.getElementById('qty_total2').textContent = qtyTotal2;
            // 更新顶部合计信息
            let topInfo = `数量[1]:${qtyTotal1}`;
            topInfo += `&nbsp;&nbsp;合计[1]:${total1.toFixed(2)}`;
            if (document.getElementById('showSecondColumn').checked) {
                topInfo += `&nbsp;&nbsp;数量[2]:${qtyTotal2}`;
                topInfo += `&nbsp;&nbsp;合计[2]:${total2.toFixed(2)}`;
            }
            document.getElementById('topTotalInfo').innerHTML = topInfo;
        }

        // 在删除行时也要重新计算
        function deleteRow(btn) {
            const row = btn.parentNode.parentNode;
            if (confirm('确定要删除这一行吗?')) {
                row.parentNode.removeChild(row);
                calculateTotals();
            }
        }

        // 添加切换第二列显示的函数
        function toggleSecondColumn() {
            const table = document.getElementById('configTable');
            const showSecond = document.getElementById('showSecondColumn').checked;
            if (showSecond) {
                table.classList.add('show-second-column');
            } else {
                table.classList.remove('show-second-column');
            }
        }

        // 修改导出Excel函数
        function exportToExcel() {
            calculateTotals();

            const data = [];
            const table = document.getElementById('configTable');
            const rows = table.getElementsByTagName('tr');
            const showSecond = document.getElementById('showSecondColumn').checked;

            data.push(['装机配置单']);
            data.push(['日期: ' + document.getElementById('date').value]);
            data.push([]);

            // 添加表头
            const headers = [];
            const headerCells = rows[0].getElementsByTagName('th');
            for (let i = 1; i < headerCells.length; i++) {
                if (!showSecond && i >= 6) continue; // 如果不显示第二列,跳过第二列的表头
                headers.push(headerCells[i].textContent);
            }
            data.push(headers);

            // 添加数据行
            for (let i = 1; i < rows.length - 1; i++) {
                const rowData = [];
                const cells = rows[i].getElementsByTagName('td');
                
                // 配件名称
                rowData.push(cells[1].querySelector('input')?.value || cells[1].querySelector('select')?.value || '');
                
                // 品牌型号[1]
                const model1Select = cells[2].querySelector('select');
                const model1Custom = cells[2].querySelector('.custom-input');
                rowData.push(model1Select?.value === '其他' ? model1Custom?.value : model1Select?.value || '');
                
                // 数量[1]、单价[1]、金额[1]
                rowData.push(cells[3].querySelector('input')?.value || '');
                rowData.push(cells[4].querySelector('input')?.value || '');
                rowData.push(cells[5].querySelector('input')?.value || '');
                
                if (showSecond) {
                    // 品牌型号[2]
                    const model2Select = cells[6].querySelector('select');
                    const model2Custom = cells[6].querySelector('.custom-input');
                    rowData.push(model2Select?.value === '其他' ? model2Custom?.value : model2Select?.value || '');
                    
                    // 数量[2]、单价[2]、金额[2]
                    rowData.push(cells[7].querySelector('input')?.value || '');
                    rowData.push(cells[8].querySelector('input')?.value || '');
                    rowData.push(cells[9].querySelector('input')?.value || '');
                }
                
                data.push(rowData);
            }

            // 添加合计行
            const totalRow = [
                '数量[1]:' + document.getElementById('qty_total1').textContent,
                '合计[1]:' + document.getElementById('total1').textContent
            ];
            
            if (showSecond) {
                totalRow.push('');
                totalRow.push('数量[2]:' + document.getElementById('qty_total2').textContent);
                totalRow.push('合计[2]:' + document.getElementById('total2').textContent);
            }
            
            data.push(totalRow);

            const ws = XLSX.utils.aoa_to_sheet(data);
            const wb = XLSX.utils.book_new();
            XLSX.utils.book_append_sheet(wb, ws, "配置清单");

            XLSX.writeFile(wb, "装机配置单_" + document.getElementById('date').value + ".xlsx");
        }

        // 修改打印表格的样式
        function printTable() {
            alert('打印前请在浏览器打印设置中关闭"页眉和页脚"选项,以获得最佳打印效果。');
            calculateTotals();
            
            // 在打印前临时保存选择框的值
            const selects = document.querySelectorAll('#configTable select');
            selects.forEach(select => {
                if (select.value === '其他') {
                    const customInput = select.parentNode.querySelector('.custom-input');
                    if (customInput) {
                        select.setAttribute('data-print-value', customInput.value);
                    }
                } else {
                    select.setAttribute('data-print-value', select.value);
                }
            });

            // ====== 打印前处理:操作列变序号,删除按钮变行号 ======
            const table = document.getElementById('configTable');
            const headerOp = table.querySelector('tr th:first-child');
            const oldHeaderOp = headerOp.textContent;
            headerOp.textContent = '序号';
            const rows = table.querySelectorAll('tr');
            const oldBtnHtml = [];
            for (let i = 1; i < rows.length - 1; i++) { // 不处理表头和合计行
                const td = rows[i].querySelector('td:first-child');
                oldBtnHtml[i] = td.innerHTML;
                td.innerHTML = i;
            }

            // 添加打印样式
            const style = document.createElement('style');
            style.textContent = `
                @media print {
                    .calculate-btn, .delete-btn, .custom-input-container {
                        display: none !important;
                    }
                    select {
                        border: none !important;
                        -webkit-appearance: none !important;
                        -moz-appearance: none !important;
                        appearance: none !important;
                        padding: 0 !important;
                    }
                    select::before {
                        content: attr(data-print-value) !important;
                    }
                    .second-column {
                        display: ${document.getElementById('showSecondColumn').checked ? 'table-cell' : 'none'} !important;
                    }
                }
            `;
            document.head.appendChild(style);

            window.print();

            // 打印后还原表头和按钮
            headerOp.textContent = oldHeaderOp;
            for (let i = 1; i < rows.length - 1; i++) {
                const td = rows[i].querySelector('td:first-child');
                td.innerHTML = oldBtnHtml[i];
            }
            // 打印后移除样式
            document.head.removeChild(style);
        }

        // 打印(无单价金额)
        function printTableNoPrice() {
            alert('打印前请在浏览器打印设置中关闭"页眉和页脚"选项,以获得最佳打印效果。');
            calculateTotals();
            const table = document.getElementById('configTable');
            const showSecond = document.getElementById('showSecondColumn').checked;
            // 在打印前临时保存选择框的值
            const selects = document.querySelectorAll('#configTable select');
            selects.forEach(select => {
                if (select.value === '其他') {
                    const customInput = select.parentNode.querySelector('.custom-input');
                    if (customInput) {
                        select.setAttribute('data-print-value', customInput.value);
                    }
                } else {
                    select.setAttribute('data-print-value', select.value);
                }
            });
            // ====== 打印前处理:操作列变序号,删除按钮变行号 ======
            const headerOp = table.querySelector('tr th:first-child');
            const oldHeaderOp = headerOp.textContent;
            headerOp.textContent = '序号';
            const rows = table.querySelectorAll('tr');
            const oldBtnHtml = [];
            for (let i = 1; i < rows.length - 1; i++) { // 不处理表头和合计行
                const td = rows[i].querySelector('td:first-child');
                oldBtnHtml[i] = td.innerHTML;
                td.innerHTML = i;
            }
            // ====== 隐藏单价和金额相关列 ======
            const ths = table.querySelectorAll('th');
            if (ths[4]) ths[4].style.display = 'none';
            if (ths[5]) ths[5].style.display = 'none';
            if (showSecond) {
                if (ths[8]) ths[8].style.display = 'none';
                if (ths[9]) ths[9].style.display = 'none';
            }
            for (let i = 1; i < rows.length; i++) {
                const cells = rows[i].querySelectorAll('td');
                if (cells[4]) cells[4].style.display = 'none';
                if (cells[5]) cells[5].style.display = 'none';
                if (showSecond) {
                    if (cells[8]) cells[8].style.display = 'none';
                    if (cells[9]) cells[9].style.display = 'none';
                }
            }
            // ====== 添加打印样式 ======
            const style = document.createElement('style');
            style.textContent = `
                @media print {
                    .calculate-btn, .delete-btn, .custom-input-container {
                        display: none !important;
                    }
                    select {
                        border: none !important;
                        -webkit-appearance: none !important;
                        -moz-appearance: none !important;
                        appearance: none !important;
                        padding: 0 !important;
                    }
                    select::before {
                        content: attr(data-print-value) !important;
                    }
                    .second-column {
                        display: ${showSecond ? 'table-cell' : 'none'} !important;
                    }
                    .total-row { display: none !important; }
                }
            `;
            document.head.appendChild(style);
            window.print();
            // 打印后还原表头和按钮
            headerOp.textContent = oldHeaderOp;
            for (let i = 1; i < rows.length - 1; i++) {
                const td = rows[i].querySelector('td:first-child');
                td.innerHTML = oldBtnHtml[i];
            }
            // 打印后还原单价和金额列
            if (ths[4]) ths[4].style.display = '';
            if (ths[5]) ths[5].style.display = '';
            if (showSecond) {
                if (ths[8]) ths[8].style.display = '';
                if (ths[9]) ths[9].style.display = '';
            }
            for (let i = 1; i < rows.length; i++) {
                const cells = rows[i].querySelectorAll('td');
                if (cells[4]) cells[4].style.display = '';
                if (cells[5]) cells[5].style.display = '';
                if (showSecond) {
                    if (cells[8]) cells[8].style.display = '';
                    if (cells[9]) cells[9].style.display = '';
                }
            }
            // 打印后移除样式
            document.head.removeChild(style);
        }

        // 显示信息弹窗
        function showInfoModal() {
            const table = document.getElementById('configTable');
            const rows = table.getElementsByTagName('tr');
            const showSecond = document.getElementById('showSecondColumn').checked;
            let text = '';
            text += '装机配置单\n';
            text += '日期: ' + document.getElementById('date').value + '\n\n';
            // 表头
            let headers = ['配件名称','品牌型号[1]','数量[1]','单价[1]','金额[1]'];
            if (showSecond) headers = headers.concat(['品牌型号[2]','数量[2]','单价[2]','金额[2]']);
            text += headers.join('\t') + '\n';
            // 数据行
            for (let i = 1; i < rows.length - 1; i++) {
                const cells = rows[i].getElementsByTagName('td');
                let rowData = [];
                // 配件名称
                rowData.push(cells[1].querySelector('input')?.value || cells[1].querySelector('select')?.value || '');
                // 品牌型号[1]
                const model1Select = cells[2].querySelector('select');
                const model1Custom = cells[2].querySelector('.custom-input');
                rowData.push(model1Select?.value === '其他' ? model1Custom?.value : model1Select?.value || '');
                // 数量[1]、单价[1]、金额[1]
                rowData.push(cells[3].querySelector('input')?.value || '');
                rowData.push(cells[4].querySelector('input')?.value || '');
                rowData.push(cells[5].querySelector('input')?.value || '');
                if (showSecond) {
                    // 品牌型号[2]
                    const model2Select = cells[6].querySelector('select');
                    const model2Custom = cells[6].querySelector('.custom-input');
                    rowData.push(model2Select?.value === '其他' ? model2Custom?.value : model2Select?.value || '');
                    // 数量[2]、单价[2]、金额[2]
                    rowData.push(cells[7].querySelector('input')?.value || '');
                    rowData.push(cells[8].querySelector('input')?.value || '');
                    rowData.push(cells[9].querySelector('input')?.value || '');
                }
                text += rowData.join('\t') + '\n';
            }
            // 合计行
            text += '\n数量[1]:' + document.getElementById('qty_total1').textContent;
            text += '\t合计[1]:' + document.getElementById('total1').textContent;
            if (showSecond) {
                text += '\t数量[2]:' + document.getElementById('qty_total2').textContent;
                text += '\t合计[2]:' + document.getElementById('total2').textContent;
            }
            document.getElementById('infoTextArea').value = text;
            document.getElementById('infoModal').style.display = 'flex';
        }
        function closeInfoModal() {
            document.getElementById('infoModal').style.display = 'none';
        }

        
        // 显示信息弹窗(无单价金额)- 修改为只显示有选型且数量大于0的项目
function showInfoModalNoPrice() {
    const table = document.getElementById('configTable');
    const rows = table.getElementsByTagName('tr');
    const showSecond = document.getElementById('showSecondColumn').checked;
    let text = '';
    text += '装机配置单\n';
    text += '日期: ' + document.getElementById('date').value + '\n\n';
    
    // 表头
    let headers = ['配件名称','品牌型号[1]','数量[1]'];
    if (showSecond) headers = headers.concat(['品牌型号[2]','数量[2]']);
    text += headers.join('\t') + '\n';
    
    // 数据行 - 只显示有型号且数量大于0的项目
    for (let i = 1; i < rows.length - 1; i++) {
        const cells = rows[i].getElementsByTagName('td');
        let rowData = [];
        
        // 配件名称
        const partName = cells[1].querySelector('input')?.value || cells[1].querySelector('select')?.value || '';
        
        // 获取第一列的型号和数量
        const model1Select = cells[2].querySelector('select');
        const model1Custom = cells[2].querySelector('.custom-input');
        const model1Value = model1Select?.value === '其他' ? model1Custom?.value : model1Select?.value || '';
        const qty1 = parseFloat(cells[3].querySelector('input')?.value) || 0;
        
        // 获取第二列的型号和数量(如果显示)
        let model2Value = '';
        let qty2 = 0;
        if (showSecond) {
            const model2Select = cells[6].querySelector('select');
            const model2Custom = cells[6].querySelector('.custom-input');
            model2Value = model2Select?.value === '其他' ? model2Custom?.value : model2Select?.value || '';
            qty2 = parseFloat(cells[7].querySelector('input')?.value) || 0;
        }
        
        // 如果两列都没有型号或数量为0,则不显示该行
        if ((!model1Value || qty1 <= 0) && (!model2Value || qty2 <= 0)) {
            continue;
        }
        
        // 添加配件名称
        rowData.push(partName);
        
        // 第一列数据
        if (model1Value && qty1 > 0) {
            rowData.push(model1Value);
            rowData.push(cells[3].querySelector('input')?.value || '');
        } else {
            // 如果第一列没有有效数据,留空
            rowData.push('');
            rowData.push('');
        }
        
        // 第二列数据(如果显示)
        if (showSecond) {
            if (model2Value && qty2 > 0) {
                rowData.push(model2Value);
                rowData.push(cells[7].querySelector('input')?.value || '');
            } else {
                // 如果第二列没有有效数据,留空
                rowData.push('');
                rowData.push('');
            }
        }
        
        text += rowData.join('\t') + '\n';
    }
    
    // 合计行
    text += '\n数量[1]:' + document.getElementById('qty_total1').textContent;
    text += '\t合计[1]:' + document.getElementById('total1').textContent;
    if (showSecond) {
        text += '\t数量[2]:' + document.getElementById('qty_total2').textContent;
        text += '\t合计[2]:' + document.getElementById('total2').textContent;
    }
    document.getElementById('infoTextArea').value = text;
    document.getElementById('infoModal').style.display = 'flex';
}

// 显示信息弹窗(订货用,仅品牌型号和数量)- 数量为1时不显示数量,数量大于1时才显示数量
function showInfoModalOrder() {
    const table = document.getElementById('configTable');
    const rows = table.getElementsByTagName('tr');
    const showSecond = document.getElementById('showSecondColumn').checked;
    let text = '';
    text += '装机订货清单\n';
    text += '日期: ' + document.getElementById('date').value + '\n\n';
    
    // 表头
    let headers = ['品牌型号[1]','数量[1]'];
    if (showSecond) headers = headers.concat(['品牌型号[2]','数量[2]']);
    text += headers.join('\t') + '\n';
    
    // 数据行 - 只显示有型号且数量大于0的项目
    for (let i = 1; i < rows.length - 1; i++) {
        const cells = rows[i].getElementsByTagName('td');
        let rowData = [];
        
        // 获取第一列的型号和数量
        const model1Select = cells[2].querySelector('select');
        const model1Custom = cells[2].querySelector('.custom-input');
        const model1Value = model1Select?.value === '其他' ? model1Custom?.value : model1Select?.value || '';
        const qty1 = parseFloat(cells[3].querySelector('input')?.value) || 0;
        
        // 获取第二列的型号和数量(如果显示)
        let model2Value = '';
        let qty2 = 0;
        if (showSecond) {
            const model2Select = cells[6].querySelector('select');
            const model2Custom = cells[6].querySelector('.custom-input');
            model2Value = model2Select?.value === '其他' ? model2Custom?.value : model2Select?.value || '';
            qty2 = parseFloat(cells[7].querySelector('input')?.value) || 0;
        }
        
        // 如果两列都没有型号或数量为0,则不显示该行
        if ((!model1Value || qty1 <= 0) && (!model2Value || qty2 <= 0)) {
            continue;
        }
        
        // 第一列数据
        if (model1Value && qty1 > 0) {
            rowData.push(model1Value); // 品牌型号总是显示
            // 数量:等于1时不显示(留空),大于1时才显示
            if (qty1 > 1) {
                rowData.push(cells[3].querySelector('input')?.value || '');
            } else {
                rowData.push(''); // 数量为1时不显示
            }
        } else {
            // 如果第一列没有有效数据,留空
            rowData.push('');
            rowData.push('');
        }
        
        // 第二列数据(如果显示)
        if (showSecond) {
            if (model2Value && qty2 > 0) {
                rowData.push(model2Value); // 品牌型号总是显示
                // 数量:等于1时不显示(留空),大于1时才显示
                if (qty2 > 1) {
                    rowData.push(cells[7].querySelector('input')?.value || '');
                } else {
                    rowData.push(''); // 数量为1时不显示
                }
            } else {
                // 如果第二列没有有效数据,留空
                rowData.push('');
                rowData.push('');
            }
        }
        
        text += rowData.join('\t') + '\n';
    }
    
    document.getElementById('infoTextArea').value = text;
    document.getElementById('infoModal').style.display = 'flex';
}
    </script>
</body>
</html>

装机配置单系统说明文档

一、系统概述

这是一个基于HTML、CSS和JavaScript的装机配置单管理系统,专为电脑装机店或DIY爱好者设计。系统提供了完整的配件选择、价格计算、数据导出和打印功能。

二、主要功能

1. 核心功能

  • 配件管理:预设了15种电脑配件(CPU、主板、内存、硬盘等)
  • 双配置方案:支持同一配件展示两种不同配置方案
  • 价格计算:自动计算各项金额和总金额
  • 配件数据库:内置了丰富的配件型号和参考价格

2. 数据操作

  • Excel导出:将配置单导出为Excel文件
  • 打印功能:支持完整打印和无单价打印两种模式
  • 信息显示:提供三种信息显示模式(完整、无单价、订货用)
  • 数据持久化:页面刷新时保留已填写的数据

3. 界面特性

  • 响应式设计:适配不同屏幕尺寸
  • 第二列切换:可选择性显示第二套配置方案
  • 颜色提示:非零金额以红色突出显示
  • 操作便捷:支持删除行、自动填充等操作

三、配件数据库

系统内置了两套配件选项:

第一套配置(option1)

  • CPU:涵盖Intel i3-i7、AMD Ryzen等15种型号
  • 主板:包括技嘉、铭瑄、昂达等品牌10种型号
  • 内存:金百达、阿斯加特等DDR4/DDR5内存
  • 其他配件:显卡、电源、显示器等均有详细选项

第二套配置(option2)

提供另一套配件选择,价格和型号与第一套有所区别

四、操作指南

1. 基本操作

  1. 选择日期:默认显示当前系统日期
  2. 填写配置
    • 在"品牌型号"列选择配件型号
    • 选择后数量自动设为1
    • 如需自定义型号,选择"其他"后输入
  3. 调整数量:可手动修改数量,系统自动计算金额

2. 特殊功能

  • 显示第二列:勾选复选框显示第二套配置方案
  • 删除行:点击"删除"按钮移除不需要的配件
  • 自动计算:修改数量或单价后自动更新总金额

3. 输出功能

  1. 导出Excel:生成包含所有数据的Excel文件
  2. 打印表格:完整打印配置单
  3. 打印(无单价金额):隐藏单价和金额的打印版
  4. 显示信息:三种查看模式:
    • 完整信息(含单价金额)
    • 无单价信息(仅显示配件和数量)
    • 订货信息(数量为1时不显示数量)

五、技术特点

1. 前端技术

  • HTML5:结构化页面内容
  • CSS3:响应式样式设计,支持打印样式
  • JavaScript(ES6):实现交互逻辑
  • SheetJS:Excel导出功能

2. 数据结构

partOptions = {
    "配件名称": {
        option1: [{model: "型号", price: 价格}, ...],
        option2: [{model: "型号", price: 价格}, ...]
    }
}

3. 智能特性

  • 自动填充:选择型号后自动设置数量为1
  • 数据恢复:页面刷新时保留已填写数据
  • 智能筛选:无单价打印时自动隐藏零值项
  • 打印优化:打印时自动隐藏操作按钮

六、使用场景

1. 装机报价

  • 为客户提供详细的配置清单和报价
  • 支持两套方案对比

2. 订货管理

  • 生成订货清单给供应商
  • 数量为1的配件不显示数量(默认理解为一个)

3. 内部记录

  • 保存历史配置方案
  • 导出Excel归档

七、注意事项

  1. 打印设置:打印前请关闭浏览器的"页眉页脚"选项
  2. 数据安全:数据存储在本地,刷新页面会保留
  3. 浏览器兼容:建议使用Chrome、Firefox等现代浏览器
  4. 配件更新:如需更新配件数据库,需修改JavaScript代码

八、扩展建议

如需扩展功能,可考虑:

  1. 添加配件分类管理
  2. 实现云端数据同步
  3. 增加客户信息管理
  4. 添加历史记录查询
  5. 支持配件图片展示

这个系统通过简洁的界面和强大的功能,为装机业务提供了完整的解决方案,从报价到订货再到记录管理,覆盖了装机业务的主要需求。