活动介绍

分析器错误消息: 服务器标记的格式不正确。 源错误: 行 31: <div class="d-grid"> 行 32: <lable id="ErrMsg" runat="server"></lable> 行 33: <asp:Button ID="SaveBtn"runat="server"Text="保存"class="btn btn-dark btn-block" /> 行

时间: 2023-12-05 17:29:05 浏览: 156
根据错误消息分析,第 31 行代码中的 `<div>` 标签格式可能存在问题。可能是标签的闭合不正确或者标签内部缺少必要的属性等。建议检查该行代码,并且检查前面的代码是否有未闭合的标签。另外,第 32 行代码中的 `lable` 标签应该是 `label` 标签的拼写错误,需要进行修改。最后,第 33 行代码中的 `ID` 属性应该改为 `Id`。修改后,代码应该如下所示: ``` <div class="d-grid"> <label id="ErrMsg" runat="server"></label> <asp:Button Id="SaveBtn" runat="server" Text="保存" class="btn btn-dark btn-block" /> </div> ```
相关问题

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>模块导航系统</title> <style> /* 全局样式 */ * { box-sizing: border-box; } /* 导航栏样式 - 优化 */ .navbar { background-color: transparent; position: relative; padding: 15px 0; margin-bottom: 30px; } .nav-container { width: 90%; max-width: 1200px; margin: 0 auto; display: flex; justify-content: center; /* 居中导航 */ } .nav-links { display: flex; list-style: none; gap: 15px; /* 按钮间距 */ } .nav-item { margin: 0 5px; } .nav-link { text-decoration: none; color: #0566a8; /* 蓝色文字 */ background: white; /* 白色背景 */ font-weight: 500; padding: 10px 25px; border-radius: 30px; /* 圆角 */ border: 2px solid #0566a8; /* 蓝色边框 */ transition: all 0.3s ease; display: inline-block; text-align: center; min-width: 120px; } .nav-link:hover { background: rgba(5, 102, 168, 0.1); } .nav-link.active { background: #0566a8; /* 蓝色背景 */ color: white; /* 白色文字 */ font-weight: 600; } /* 模块容器样式 */ .module-container { width: 90%; max-width: 1200px; margin: 40px auto; position: relative; min-height: 600px; overflow: hidden; } .module { position: absolute; top: 0; left: 0; width: 100%; opacity: 0; visibility: hidden; transform: translateY(20px); transition: opacity 0.6s ease, transform 0.6s ease, visibility 0.6s; z-index: 1; } .module.active { opacity: 1; visibility: visible; transform: translateY(0); z-index: 2; } /* 模块特定样式 */ .module-content { background-color: #fff; border-radius: 12px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.05); overflow: hidden; margin-bottom: 30px; } /* 响应式设计 */ @media (max-width: 768px) { .nav-container { flex-direction: column; align-items: flex-start; } .nav-links { margin-top: 15px; flex-wrap: wrap; } .nav-item { margin: 5px 15px 5px 0; } .module-container { margin: 20px auto; } } /* 模块1样式 */ #module1 .minimal-process { max-width: 100%; margin: 0; } /* 模块2样式 */ #module2 .fp-carousel-module { max-width: 100%; margin: 0; } /* 模块3样式 */ #module3 .luxemg-container { max-width: 100%; padding: 20px; } /* 模块4样式 */ #module4 .carousel-container { max-width: 100%; margin: 0; } </style> </head> <body> <!-- 导航栏 --> <nav class="navbar"> <div class="nav-container"> <ul class="nav-links"> <li class="nav-item"> <a href="#" class="nav-link active" data-target="module1">服务流程</a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-target="module2">3D轮播</a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-target="module3">材料展示</a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-target="module4">图片轮播</a> </li> </ul> </div> </nav> <!-- 模块容器 --> <div class="module-container"> <!-- 模块1:服务流程 --> <div id="module1" class="module active"> <div class="module-content"> <!-- 代码1的内容 --> <div class="minimal-process"> <div class="process-container"> <!-- 步骤 1 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/youxiang.png" alt="咨询"> </div> <div class="step-content"> <span class="step-number">1</span> <h3 class="step-title">Demand consultation</h3> <p class="step-desc">The customer sends a contact email to get the consultation.</p> </div> </div> <!-- 步骤 2 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/kefu.png" alt="设计"> </div> <div class="step-content"> <span class="step-number">2</span> <h3 class="step-title">Solution Design</h3> <p class="step-desc">The business manager conducts content docking with the customer.</p> </div> </div> <!-- 步骤 3 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/emptybox.png" alt="实施"> </div> <div class="step-content"> <span class="step-number">3</span> <h3 class="step-title">Professional implementation</h3> <p class="step-desc">We make a samptle according to the customer's requirements and confirm the details.</p> </div> </div> <!-- 步骤 4 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/woshou.png" alt="交付"> </div> <div class="step-content"> <span class="step-number">4</span> <h3 class="step-title">Successfully placed order</h3> <p class="step-desc">After the customer's confirmation,the customer pays the deposit and places the order.</p> </div> </div> </div> </div> </div> </div> <!-- 模块2:3D轮播 --> <div id="module2" class="module"> <div class="module-content"> <!-- 代码2的内容 --> <div class="fp-carousel-module"> <div class="fp-carousel-container"> <div class="fp-carousel-item fp-active" data-index="0"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-14_59_30_compressed.png" alt="Printing"> <div class="fp-description">Printing:Transfer your design onto paper or board using offset, digital or flexo presses.</div> </div> <div class="fp-carousel-item fp-next" data-index="1"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_02_51_compressed.png" alt="Surface Finishing"> <div class="fp-description">Surface Finishing:Enhance and protect the print by adding coatings or varnishes (e.g. UV, matte or gloss).</div> </div> <div class="fp-carousel-item fp-next-far" data-index="2"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_05_48_compressed.png"> <div class="fp-description">Lamination (Mounting):Bond the printed sheet to a sturdier substrate or apply a clear film for extra durability.</div> </div> <div class="fp-carousel-item fp-prev" data-index="3"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_11_40_compressed.png" alt="Die-Cutting"> <div class="fp-description">Die-Cutting:Use a custom metal die to cut out shapes, create windows or trim the edges precisely.</div> </div> <div class="fp-carousel-item fp-prev-far" data-index="4"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_21_01_compressed.png"> <div class="fp-description">Gluing & Assembly:Fold and glue the die-cut pieces together to form boxes, folders or other finished items.</div> </div> <div class="fp-carousel-item fp-prev-far" data-index="5"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_24_28_compressed.png" alt="Packing & Shipping"> <div class="fp-description">Packing & Shipping:Stack, bundle or carton the completed products, then palletize and dispatch them to the client.</div> </div> <div class="fp-nav-btn fp-prev-btn"> <div class="fp-arrow">❮</div> </div> <div class="fp-nav-btn fp-next-btn"> <div class="fp-arrow">❯</div> </div> </div> </div> </div> </div> <!-- 模块3:材料展示 --> <div id="module3" class="module"> <div class="module-content"> <!-- 代码3的内容 --> <div class="luxemg-container"> <!-- Paper board 部分 --> <h2 class="luxemg-section-title">Paper board</h2> <div class="luxemg-grid"> <!-- SBS C1S --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_59_47_compressed.png" alt="SBS C1S" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">SBS C1S</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-sbs-c1s">VIEW MORE</button> </div> </div> <!-- SBS C2S --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_45_42_compressed.png" alt="SBS C2S" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">SBS C2S</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-sbs-c2s">VIEW MORE</button> </div> </div> <!-- CCNB --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_44_52_compressed.png" alt="CCNB" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">CCNB</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-ccnb">VIEW MORE</button> </div> </div> <!-- UUK --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=UUK" alt="UUK" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">UUK</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-uuk">VIEW MORE</button> </div> </div> <!-- Metallic --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=Metallic" alt="Metallic" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Metallic</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-metallic">VIEW MORE</button> </div> </div> </div> <!-- Corrugated 部分 --> <h2 class="luxemg-section-title">Corrugated</h2> <!-- single wall部分 --> <h3 class="luxemg-subsection-title">single wall</h3> <div class="luxemg-grid"> <!-- A Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=A+Flute" alt="A Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">A Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-a-flute">VIEW MORE</button> </div> </div> <!-- C Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=C+Flute" alt="C Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">C Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-c-flute">VIEW MORE</button> </div> </div> <!-- B Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=B+Flute" alt="B Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">B Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-b-flute">VIEW MORE</button> </div> </div> <!-- E Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=E+Flute" alt="E Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">E Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-e-flute">VIEW MORE</button> </div> </div> <!-- F Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=F+Flute" alt="F Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">F Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-f-flute">VIEW MORE</button> </div> </div> </div> <!-- double wall部分 --> <h3 class="luxemg-subsection-title">double wall</h3> <div class="luxemg-grid"> <!-- B/C Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=B/C+Flute" alt="B/C Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">B/C Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-bc-flute">VIEW MORE</button> </div> </div> <!-- E/C Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=E/C+Flute" alt="E/C Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">E/C Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-ec-flute">VIEW MORE</button> </div> </div> <!-- E/B Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=E/B+Flute" alt="E/B Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">E/B Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-eb-flute">VIEW MORE</button> </div> </div> <!-- F/E Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=F/E+Flute" alt="F/E Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">F/E Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-fe-flute">VIEW MORE</button> </div> </div> </div> <!-- Print 部分 --> <h2 class="luxemg-section-title">Print</h2> <div class="luxemg-grid"> <!-- CMYK --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=CMYK" alt="CMYK" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">CMYK</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-cmyk">VIEW MORE</button> </div> </div> <!-- Pantone --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=Pantone" alt="Pantone" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Pantone</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-pantone">VIEW MORE</button> </div> </div> </div> </div> </div> </div> <!-- 模块4:图片轮播 --> <div id="module4" class="module"> <div class="module-content"> <!-- 代码4的内容 --> <div class="carousel-container"> <!-- 轮播轨道 --> <div class="carousel"> <!-- 轮播项1 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Lamination-Gloss_Matte1_compressed.png" alt="Lamination (Gloss/Matte)"> <div class="image-info"> <h3>Lamination (Gloss/Matte)</h3> <p>– Applying a thin plastic film over the printed sheet to enhance scratch resistance, moisture protection and overall durability. Gloss lamination yields a shiny surface, while matte lamination gives a low-sheen, soft-touch effect.</p> </div> </div> <!-- 轮播项2 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/UV-Coating-Spot_Overall_compressed.png" alt="UV Coating (Spot/Overall)"> <div class="image-info"> <h3>UV Coating (Spot/Overall)</h3> <p>– Spreading a liquid UV-curable varnish onto either selected areas (spot UV) or the entire sheet, then instantly curing it under UV light. Creates high gloss and tactile contrast.</p> </div> </div> <!-- 轮播项3 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Hot-Foil-Stamping_compressed.png" alt="Hot Foil Stamping"> <div class="image-info"> <h3>Hot Foil Stamping</h3> <p>– Transferring metallic or pigmented foil onto specific areas of the print using heat and pressure. Delivers a premium metallic sheen (gold, silver, colored foils) for logos or decorative accents.</p> </div> </div> <!-- 轮播项4 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Embossing-_-Debossing1_compressed.png" alt="Embossing / Debossing"> <div class="image-info"> <h3>Embossing / Debossing</h3> <p>– Pressing the paper between male and female dies to create a raised (emboss) or recessed (deboss) 3D relief. Adds tactile interest and a sense of depth.</p> </div> </div> <!-- 轮播项5 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Die-Cutting_compressed.png" alt="Die-Cutting"> <div class="image-info"> <h3>Die-Cutting</h3> <p>– Using a custom-made metal die to cut the printed sheet into precise shapes or create windows/slots. Essential for producing custom box shapes, hang-tabs, or intricate cut-outs.</p> </div> </div> <!-- 轮播项6 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Creasing-Folding-Crease_compressed.png" alt="Creasing (Folding Crease)"> <div class="image-info"> <h3>Creasing (Folding Crease)</h3> <p>– Impressing a crease line on the sheet to facilitate clean, accurate folds without cracking the coating or ink. Critical for boxes, folders, and other folded structures.</p> </div> </div> <!-- 轮播项7 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Spot-UV-Emboss-Combination_compressed.png" alt="Spot UV + Emboss Combination"> <div class="image-info"> <h3>Spot UV + Emboss Combination</h3> <p>– First applying spot UV coating, then embossing the same area to create a shiny, raised element. Enhances both visual shine and tactile relief simultaneously.</p> </div> </div> <!-- 轮播项8 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Laser-Finishing-Holographic-Etch-Combination_compressed.png" alt="Holographic Foil Stamping"> <div class="image-info"> <h3>Holographic Foil Stamping</h3> <p>— Laser-etch microscopic holographic patterns onto foil, then heat- or UV-cure to lock in vibrant, angle-shifting colors and subtle texture for a premium anti-counterfeiting finish.</p> </div> </div> </div> <!-- 控制按钮 --> <div class="carousel-controls"> <button class="control-btn" id="prevBtn">Previous</button> <button class="control-btn" id="nextBtn">next</button> <button class="control-btn" id="autoBtn">暂停轮播</button> </div> <!-- 指示器 --> <div class="indicator"> <div class="indicator-dot active" data-index="0"></div> <div class="indicator-dot" data-index="1"></div> <div class="indicator-dot" data-index="2"></div> <div class="indicator-dot" data-index="3"></div> </div> </div> </div> </div> </div> <!-- 模态框容器 --> <div id="luxemg-modal-container" class="luxemg-modal-container"> <div class="luxemg-modal-wrapper"> <div class="luxemg-modal-content"> <div class="luxemg-modal-header"> <h3 id="luxemg-modal-title" class="luxemg-modal-title">Material Details</h3> <button id="luxemg-close-modal" class="luxemg-close-btn">&times;</button> </div> <div class="luxemg-modal-body"> <div class="luxemg-modal-image-container"> <img id="luxemg-modal-image" class="luxemg-modal-img" src="" alt="Material"> </div> <div class="luxemg-modal-description"> <div id="luxemg-modal-description" class="luxemg-modal-desc"></div> </div> </div> </div> </div> </div> <!-- JavaScript --> <script> // 导航切换功能 document.addEventListener('DOMContentLoaded', function() { // 导航切换 const navLinks = document.querySelectorAll('.nav-link'); const modules = document.querySelectorAll('.module'); navLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); // 获取目标模块ID const targetId = this.getAttribute('data-target'); // 更新导航状态 navLinks.forEach(l => l.classList.remove('active')); this.classList.add('active'); // 切换模块 modules.forEach(module => { module.classList.remove('active'); }); document.getElementById(targetId).classList.add('active'); }); }); // 初始化模块2的轮播功能 initCarousel(document.querySelector('#module2 .fp-carousel-module')); // 初始化模块3的模态框功能 initLuxemgGallery(); // 初始化模块4的轮播功能 initModule4Carousel(); }); // 模块2的轮播功能 function initCarousel(module) { const container = module.querySelector('.fp-carousel-container'); const items = Array.from(module.querySelectorAll('.fp-carousel-item')); const prevBtn = module.querySelector('.fp-prev-btn'); const nextBtn = module.querySelector('.fp-next-btn'); let currentIndex = 0; let isAnimating = false; // 初始化位置 updatePositions(); // 事件绑定函数 const bindEvents = function() { // 图片点击事件 items.forEach(item => { item.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; if (this.classList.contains('fp-next') || this.classList.contains('fp-next-far')) { navigate(1); } else if (this.classList.contains('fp-prev') || this.classList.contains('fp-prev-far')) { navigate(-1); } // 动画结束后重置标志 setTimeout(() => isAnimating = false, 700); }); }); // 容器区域点击 container.addEventListener('click', function(e) { if (isAnimating) return; isAnimating = true; const rect = container.getBoundingClientRect(); const clickX = e.clientX - rect.left; if (clickX > rect.width * 3/4) { navigate(1); } else if (clickX < rect.width * 1/4) { navigate(-1); } setTimeout(() => isAnimating = false, 700); }); // 导航按钮 prevBtn.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; navigate(-1); setTimeout(() => isAnimating = false, 700); }); nextBtn.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; navigate(1); setTimeout(() => isAnimating = false, 700); }); // 键盘导航 document.addEventListener('keydown', function(e) { if (isAnimating) return; isAnimating = true; if (e.key === 'ArrowLeft') { navigate(-1); } else if (e.key === 'ArrowRight') { navigate(1); } setTimeout(() => isAnimating = false, 700); }); // 响应式调整 window.addEventListener('resize', function() { updatePositions(); }); }; // 导航函数 function navigate(direction) { currentIndex = (currentIndex + direction + items.length) % items.length; updatePositions(); } // 更新位置 function updatePositions() { items.forEach((item, index) => { item.classList.remove('fp-active', 'fp-prev', 'fp-next', 'fp-prev-far', 'fp-next-far', 'fp-hidden'); const position = (index - currentIndex + items.length) % items.length; if (position === 0) { item.classList.add('fp-active'); } else if (position === 1) { item.classList.add('fp-next'); } else if (position === 2) { item.classList.add('fp-next-far'); } else if (position === items.length - 1) { item.classList.add('fp-prev'); } else if (position === items.length - 2) { item.classList.add('fp-prev-far'); } else { item.classList.add('fp-hidden'); } }); } // 初始化事件绑定 bindEvents(); } // 模块3的模态框功能 function initLuxemgGallery() { // 材料详情数据 const luxemgMaterialDetails = { // Paper board "modal-sbs-c1s": { title: "SBS C1S", image: "https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_59_47_compressed.png", description: "<p>SBS C1S(Solid Bleached Sulfate – Coated One Side) is a premium-grade paperboard made from 100% virgin bleached wood pulp. It is coated on one side to provide an exceptionally smooth and white printing surface, while the reverse side remains uncoated for functional versatility.</p><p>Key Features:<br>- Bright White Appearance: Produced from fully bleached fibers for a clean, uniform, and high-end look.<br>- Coated One Side (C1S): One side has a clay coating for excellent printability; the reverse side is uncoated for better glue adhesion or writing.<br>- Excellent Print Surface: Ideal for offset, digital, and specialty printing methods; supports vibrant color reproduction and fine detail.<br>- High Stiffness and Strength: Offers good structural integrity, making it suitable for rigid packaging and die-cut designs.<br>- Environmentally Friendly: Recyclable, biodegradable, and available with FSC certification upon request.</p><p>Main Advantages:<br>✅ Preferred choice for premium packaging (cosmetics, personal care, high-end retail)<br>✅ Superior surface for specialty finishes like foil stamping, embossing, and spot UV<br>✅ Balanced combination of print quality and converting performance<br>✅ Consistent white core and surface enhance the perceived value of the final product<br>✅ Compatible with folding, scoring, gluing, and other post-press operations</p>" }, // ... 其他材料详情 }; // DOM元素引用 const luxemgModalContainer = document.getElementById('luxemg-modal-container'); const luxemgModalTitle = document.getElementById('luxemg-modal-title'); const luxemgModalImage = document.getElementById('luxemg-modal-image'); const luxemgModalDescription = document.getElementById('luxemg-modal-description'); const luxemgCloseModal = document.getElementById('luxemg-close-modal'); // 打开模态框函数 function openLuxemgModal(modalId) { const material = luxemgMaterialDetails[modalId]; const modalContent = luxemgModalContainer.querySelector('.luxemg-modal-content'); if (!material) { console.error("Material details not found for:", modalId); return; } // 填充模态框内容 luxemgModalTitle.textContent = material.title; luxemgModalImage.src = material.image; luxemgModalImage.alt = material.title; luxemgModalDescription.innerHTML = material.description; // 显示模态框 luxemgModalContainer.style.display = 'block'; // 强制重绘确保动画执行 void luxemgModalContainer.offsetWidth; // 应用显示动画 setTimeout(() => { luxemgModalContainer.style.opacity = '1'; modalContent.style.transform = 'scale(1)'; modalContent.style.opacity = '1'; }, 10); // 禁止背景滚动 document.body.style.overflow = 'hidden'; } // 关闭模态框函数 function closeLuxemgModal() { const modalContent = luxemgModalContainer.querySelector('.luxemg-modal-content'); luxemgModalContainer.style.opacity = '0'; modalContent.style.transform = 'scale(0.95)'; modalContent.style.opacity = '0'; setTimeout(() => { luxemgModalContainer.style.display = 'none'; document.body.style.overflow = ''; }, 300); } // 事件绑定函数 luxemgCloseModal.addEventListener('click', closeLuxemgModal); luxemgModalContainer.addEventListener('click', function(e) { if (e.target === this) closeLuxemgModal(); }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeLuxemgModal(); }); document.addEventListener('click', function(e) { if (e.target.classList.contains('luxemg-detail-btn')) { const modalId = e.target.getAttribute('data-luxemg-modal'); openLuxemgModal(modalId); } }); } // 模块4的轮播功能 function initModule4Carousel() { // 获取DOM元素 const carousel = document.querySelector('#module4 .carousel'); const items = document.querySelectorAll('#module4 .carousel-item'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const autoBtn = document.getElementById('autoBtn'); const dots = document.querySelectorAll('#module4 .indicator-dot'); // 初始化变量 let currentIndex = 0; let itemsPerView = calculateItemsPerView(); let autoPlayInterval; let isAutoPlay = true; // 计算当前视图显示的项目数 function calculateItemsPerView() { const width = window.innerWidth; if (width <= 500) return 1; if (width <= 700) return 2; if (width <= 900) return 3; return 4; } // 更新轮播位置 function updateCarousel() { // 计算每个项目的宽度百分比 const itemWidth = 100 / itemsPerView; // 计算偏移量 const offset = -currentIndex * itemWidth; // 应用转换效果 carousel.style.transform = `translateX(${offset}%)`; // 更新指示点状态 dots.forEach((dot, index) => { dot.classList.toggle('active', index === currentIndex); }); } // 下一张 function nextSlide() { // 计算最大索引 const maxIndex = items.length - itemsPerView; // 更新当前索引(循环) currentIndex = currentIndex >= maxIndex ? 0 : currentIndex + 1; updateCarousel(); } // 上一张 function prevSlide() { // 计算最大索引 const maxIndex = items.length - itemsPerView; // 更新当前索引(循环) currentIndex = currentIndex <= 0 ? maxIndex : currentIndex - 1; updateCarousel(); } // 自动轮播 function startAutoPlay() { if (isAutoPlay) { // 设置轮播间隔 autoPlayInterval = setInterval(nextSlide, 3000); // 更新按钮文本 autoBtn.textContent = 'stop'; } } // 停止自动轮播 function stopAutoPlay() { // 清除轮播间隔 clearInterval(autoPlayInterval); // 更新按钮文本 autoBtn.textContent = 'start'; } // 切换自动轮播状态 function toggleAutoPlay() { // 反转自动播放状态 isAutoPlay = !isAutoPlay; if (isAutoPlay) { startAutoPlay(); } else { stopAutoPlay(); } } // 初始化轮播 function init() { // 计算每屏显示数量 itemsPerView = calculateItemsPerView(); // 更新轮播位置 updateCarousel(); // 开始自动播放 startAutoPlay(); } // 事件监听器 nextBtn.addEventListener('click', () => { nextSlide(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); prevBtn.addEventListener('click', () => { prevSlide(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); autoBtn.addEventListener('click', toggleAutoPlay); // 为每个指示点添加点击事件 dots.forEach(dot => { dot.addEventListener('click', () => { // 获取并设置当前索引 currentIndex = parseInt(dot.getAttribute('data-index')); updateCarousel(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); }); // 窗口大小变化时重新计算 window.addEventListener('resize', () => { // 重新计算每屏显示数量 itemsPerView = calculateItemsPerView(); // 更新轮播位置 updateCarousel(); }); // 初始化轮播 init(); } </script> </body> </html> 将这个代码中的按钮都改成#0566a8色的字和微微圆角边框,代码四下方的原点增加到8个

<think>我们注意到原代码中已经有一些样式,但需要修改按钮的样式,将按钮文字颜色改为#0566a8,并添加微微圆角的边框。同时,模块4(图片轮播)下方的指示点(indicator dots)目前只有4个,但轮播项有8个,需要增加到8个。修改点:1.导航栏的按钮(.nav-link)已经符合要求(蓝色文字和圆角边框),但其他按钮(如模块3中的“VIEW MORE”按钮,模块4中的控制按钮)也需要修改。2.模块3中的“VIEW MORE”按钮:需要修改文字颜色为#0566a8,并添加圆角边框。3.模块4中的控制按钮(Previous,next,暂停轮播)需要修改文字颜色为#0566a8,并添加圆角边框。4.模块4的指示点(indicatordots)需要从4个增加到8个。步骤:1.为模块3的“VIEW MORE”按钮添加样式,使其文字颜色为#0566a8,背景白色,圆角边框,并设置圆角大小(例如border-radius:4px,或者按需求调整)。2.为模块4的控制按钮添加样式,同样文字颜色#0566a8,背景白色,圆角边框。3.在模块4的指示点部分,将指示点数量增加到8个(每个轮播项对应一个)。注意:原代码中模块4的指示点部分只有4个div,我们需要根据轮播项的数量(8个)来添加8个指示点。具体修改:一、模块3的按钮样式修改:在CSS中添加或修改以下样式:```css.luxemg-detail-btn{color:#0566a8;background:white;border:2pxsolid #0566a8;border-radius:4px; /*微微圆角*/padding:8px16px;font-weight:500;cursor:pointer;transition: all0.3sease;}.luxemg-detail-btn:hover {background: rgba(5,102,168,0.1);}```二、模块4的控制按钮样式修改:在CSS中添加或修改以下样式:```css.control-btn {color: #0566a8;background:white;border:2pxsolid #0566a8;border-radius:4px; /*微微圆角*/padding:8px16px;margin:05px;font-weight:500;cursor:pointer;transition: all0.3sease;}.control-btn:hover {background: rgba(5,102,168,0.1);}```三、模块4的指示点数量修改:在模块4的HTML部分,找到指示点容器(class为indicator),将其中的指示点数量增加到8个,每个对应一个轮播项(索引0到7)。修改前(只有4个):```html<divclass="indicator"><divclass="indicator-dotactive"data-index="0"></div><divclass="indicator-dot" data-index="1"></div><div class="indicator-dot"data-index="2"></div><divclass="indicator-dot" data-index="3"></div></div>```修改后(8个):```html<div class="indicator"><div class="indicator-dot active" data-index="0"></div><div class="indicator-dot"data-index="1"></div><divclass="indicator-dot" data-index="2"></div><div class="indicator-dot"data-index="3"></div><divclass="indicator-dot" data-index="4"></div><div class="indicator-dot"data-index="5"></div><divclass="indicator-dot" data-index="6"></div><div class="indicator-dot"data-index="7"></div></div>```注意:由于轮播项有8个,但每屏显示的数量可能为1到4个(根据屏幕宽度),所以指示点应该对应轮播项,而不是每屏。因此,我们添加8个指示点,每个对应一个轮播项。在轮播逻辑中,当前索引指示点高亮。另外,在模块4的轮播初始化函数(initModule4Carousel)中,我们使用currentIndex来更新指示点状态,但要注意,由于每屏显示多个项目,所以指示点应该表示当前显示的第一个项目的索引。因此,我们只需要一个指示点高亮,即当前轮播的第一个项目的索引。原逻辑中,dots的点击事件已经设置了currentIndex,所以不需要修改。但是,原代码中指示点的数量是固定的,现在改为8个,所以需要修改HTML。由于原代码中模块4的轮播项有8个(class为carousel-item的div有8个),所以我们将指示点增加到8个。最后,在CSS中调整指示点的样式,确保它们在一行中显示且不换行,可能需要添加flex-wrap:nowrap和overflow-x:auto(如果需要横向滚动的话),但通常8个点在一行中可能在小屏幕上会超出,所以可以考虑让指示点容器可以横向滚动,或者将指示点缩小并调整间距。这里我们选择调整指示点容器,使其可以横向滚动(如果超出容器宽度):```css.indicator {display: flex;justify-content: center;flex-wrap: nowrap;overflow-x:auto;padding:10px0;}```但考虑到8个点不会太长,我们可以先这样处理。现在,我们将修改后的完整代码整合。注意:由于原代码较长,我们只修改了部分样式和HTML结构。请将修改后的代码整合到原文件中。由于代码量很大,这里只展示修改的部分,但为了清晰,我将提供完整的修改后的代码。但请注意,由于问题要求修改按钮样式和指示点数量,我们只修改了上述部分。其他部分保持不变。由于代码太长,我将提供修改后的完整代码,但只重点展示修改的部分。</think>我已经分析了您的需求,需要将页面中的按钮统一修改为蓝色文字(#0566a8)并添加圆角边框,同时将模块4的指示点增加到8个。以下是修改后的完整代码: ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>模块导航系统</title> <style> /* 全局样式 */ * { box-sizing: border-box; } /* 导航栏样式 - 优化 */ .navbar { background-color: transparent; position: relative; padding: 15px 0; margin-bottom: 30px; } .nav-container { width: 90%; max-width: 1200px; margin: 0 auto; display: flex; justify-content: center; /* 居中导航 */ } .nav-links { display: flex; list-style: none; gap: 15px; /* 按钮间距 */ } .nav-item { margin: 0 5px; } .nav-link { text-decoration: none; color: #0566a8; /* 蓝色文字 */ background: white; /* 白色背景 */ font-weight: 500; padding: 10px 25px; border-radius: 30px; /* 圆角 */ border: 2px solid #0566a8; /* 蓝色边框 */ transition: all 0.3s ease; display: inline-block; text-align: center; min-width: 120px; } .nav-link:hover { background: rgba(5, 102, 168, 0.1); } .nav-link.active { background: #0566a8; /* 蓝色背景 */ color: white; /* 白色文字 */ font-weight: 600; } /* 模块容器样式 */ .module-container { width: 90%; max-width: 1200px; margin: 40px auto; position: relative; min-height: 600px; overflow: hidden; } .module { position: absolute; top: 0; left: 0; width: 100%; opacity: 0; visibility: hidden; transform: translateY(20px); transition: opacity 0.6s ease, transform 0.6s ease, visibility 0.6s; z-index: 1; } .module.active { opacity: 1; visibility: visible; transform: translateY(0); z-index: 2; } /* 模块特定样式 */ .module-content { background-color: #fff; border-radius: 12px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.05); overflow: hidden; margin-bottom: 30px; } /* 响应式设计 */ @media (max-width: 768px) { .nav-container { flex-direction: column; align-items: flex-start; } .nav-links { margin-top: 15px; flex-wrap: wrap; } .nav-item { margin: 5px 15px 5px 0; } .module-container { margin: 20px auto; } } /* 模块1样式 */ #module1 .minimal-process { max-width: 100%; margin: 0; } /* 模块2样式 */ #module2 .fp-carousel-module { max-width: 100%; margin: 0; } /* 模块3样式 */ #module3 .luxemg-container { max-width: 100%; padding: 20px; } /* 模块4样式 */ #module4 .carousel-container { max-width: 100%; margin: 0; } /* 按钮样式统一修改 */ .luxemg-detail-btn, .control-btn { color: #0566a8; /* 蓝色文字 */ background: white; /* 白色背景 */ font-weight: 500; padding: 8px 16px; border-radius: 4px; /* 微微圆角 */ border: 2px solid #0566a8; /* 蓝色边框 */ transition: all 0.3s ease; cursor: pointer; } .luxemg-detail-btn:hover, .control-btn:hover { background: rgba(5, 102, 168, 0.1); } /* 指示点容器样式调整 */ .indicator { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; padding: 10px 0; } </style> </head> <body> <!-- 导航栏 --> <nav class="navbar"> <div class="nav-container"> <ul class="nav-links"> <li class="nav-item"> <a href="#" class="nav-link active" data-target="module1">服务流程</a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-target="module2">3D轮播</a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-target="module3">材料展示</a> </li> <li class="nav-item"> <a href="#" class="nav-link" data-target="module4">图片轮播</a> </li> </ul> </div> </nav> <!-- 模块容器 --> <div class="module-container"> <!-- 模块1:服务流程 --> <div id="module1" class="module active"> <div class="module-content"> <!-- 代码1的内容 --> <div class="minimal-process"> <div class="process-container"> <!-- 步骤 1 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/youxiang.png" alt="咨询"> </div> <div class="step-content"> <span class="step-number">1</span> <h3 class="step-title">Demand consultation</h3> <p class="step-desc">The customer sends a contact email to get the consultation.</p> </div> </div> <!-- 步骤 2 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/kefu.png" alt="设计"> </div> <div class="step-content"> <span class="step-number">2</span> <h3 class="step-title">Solution Design</h3> <p class="step-desc">The business manager conducts content docking with the customer.</p> </div> </div> <!-- 步骤 3 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/emptybox.png" alt="实施"> </div> <div class="step-content"> <span class="step-number">3</span> <h3 class="step-title">Professional implementation</h3> <p class="step-desc">We make a samptle according to the customer's requirements and confirm the details.</p> </div> </div> <!-- 步骤 4 --> <div class="process-step"> <div class="step-icon"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/woshou.png" alt="交付"> </div> <div class="step-content"> <span class="step-number">4</span> <h3 class="step-title">Successfully placed order</h3> <p class="step-desc">After the customer's confirmation,the customer pays the deposit and places the order.</p> </div> </div> </div> </div> </div> </div> <!-- 模块2:3D轮播 --> <div id="module2" class="module"> <div class="module-content"> <!-- 代码2的内容 --> <div class="fp-carousel-module"> <div class="fp-carousel-container"> <div class="fp-carousel-item fp-active" data-index="0"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-14_59_30_compressed.png" alt="Printing"> <div class="fp-description">Printing:Transfer your design onto paper or board using offset, digital or flexo presses.</div> </div> <div class="fp-carousel-item fp-next" data-index="1"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_02_51_compressed.png" alt="Surface Finishing"> <div class="fp-description">Surface Finishing:Enhance and protect the print by adding coatings or varnishes (e.g. UV, matte or gloss).</div> </div> <div class="fp-carousel-item fp-next-far" data-index="2"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_05_48_compressed.png"> <div class="fp-description">Lamination (Mounting):Bond the printed sheet to a sturdier substrate or apply a clear film for extra durability.</div> </div> <极 class="fp-carousel-item fp-prev" data-index="3"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_11_40_compressed.png" alt="Die-Cutting"> <div class="fp-description">Die-Cutting:Use a custom metal die to cut out shapes, create windows or trim the edges precisely.</div> </div> <div class="fp-carousel-item fp-prev-far" data-index="4"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年极月18日-15_21_01_compressed.png"> <div class="fp-description">Gluing & Assembly:Fold and glue the die-cut pieces together to form boxes, folders or other finished items.</div> </div> <div class="fp-carousel-item fp-prev-far" data-index="5"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-15_24_28_compressed.png" alt="Packing & Shipping"> <div class="fp-description">Packing & Shipping:Stack, bundle or carton the completed products, then palletize and dispatch them to the client.</div> </div> <div class="fp-nav-btn fp-prev-btn"> <div class="fp-arrow">❮</div> </div> <div class="fp-nav-btn fp-next-btn"> <div class="fp-arrow">❯</div> </div> </div> </div> </div> </div> <!-- 模块3:材料展示 --> <div id="module3" class="module"> <div class="module-content"> <!-- 代码3的内容 --> <div class="luxemg-container"> <!-- Paper board 部分 --> <h2 class="luxemg-section-title">Paper board</h2> <div class="luxemg-grid"> <!-- SBS C1S --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_59_47_compressed.png" alt="SBS C1S" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">SBS C1S</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-sbs-c1s">VIEW MORE</button> </div> </div> <!-- SBS C2S --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_45_42_compressed.png" alt="SBS C2S" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">SBS C2S</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-sbs-c2s">VIEW MORE</button> </div> </div> <!-- CCNB --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_44_52_compressed.png" alt="CCNB" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">CCNB</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-ccnb">VIEW MORE</button> </极> </div> <!-- UUK --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=UUK" alt="UUK" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">UUK</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-uuk">VIEW MORE</button> </div> </div> <!-- Metallic --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=Metallic" alt="Metallic" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Metallic</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-metallic">VIEW MORE</button> </div> </div> </div> <!-- Corrugated 部分 --> <h2 class="luxemg-section-title">Corrugated</h2> <!-- single wall部分 --> <h3 class="luxemg-subsection-title">single wall</h3> <div class="luxemg-grid"> <!-- A Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=A+Flute" alt="A Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">A Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-a-flute">VIEW MORE</button> </div> </div> <!-- C Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=C+Flute" alt="C Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">C Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-c-flute">VIEW MORE</button> </div> </div> <!-- B Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=B+Flute" alt="B Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">B Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-b-flute">VIEW MORE</button> </div> </div> <!-- E Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=E+Flute" alt="E Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">E Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-e-flute">VIEW MORE</button> </div> </div> <!-- F Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=F+Flute" alt="F Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">F Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-f-flute">VIEW MORE</button> </div> </div> </div> <!-- double wall部分 --> <h3 class="luxemg-subsection-title">double wall</h3> <div class="luxemg-grid"> <!-- B/C Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=B/C+Flute" alt="B/C Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">B/C Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-bc-flute">VIEW MORE</button> </div> </div> <!-- E/C Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=E/C+Flute" alt="E/C Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">E/C Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-ec-flute">VIEW MORE</button> </div> </div> <!-- E/B Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=E/B+Flute" alt="E/B Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">E/B Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-eb-flute">VIEW MORE</button> </div> </div> <!-- F/E Flute --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=F/E+Flute" alt="F/E Flute" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">F/E Flute</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-fe-flute">VIEW MORE</button> </div> </div> </div> <!-- Print 部分 --> <h2 class="luxemg-section-title">Print</h2> <div class="luxemg-grid"> <!-- CMYK --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=CMYK" alt="CMYK" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">CMYK</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-cmyk">VIEW MORE</button> </div> </div> <!-- Pantone --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/300x240?text=Pantone" alt="Pantone" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Pantone</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal-pantone">VIEW MORE</button> </div> </div> </div> </div> </div> </div> <!-- 模块4:图片轮播 --> <div id="module4" class="module"> <div class="module-content"> <!-- 代码4的内容 --> <div class="carousel-container"> <!-- 轮播轨道 --> <div class="carousel"> <!-- 轮播项1 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Lamination-Gloss_Matte1_compressed.png" alt="Lamination (Gloss/Matte)"> <div class="image-info"> <h3>Lamination (Gloss/Matte)</h3> <p>– Applying a thin plastic film over the printed sheet to enhance scratch resistance, moisture protection and overall durability. Gloss lamination yields a shiny surface, while matte lamination gives a low-sheen, soft-touch effect.</p> </div> </div> <!-- 轮播项2 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/UV-Coating-Spot_Overall_compressed.png" alt="UV Coating (Spot/Overall)"> <div class="image-info"> <h3>UV Coating (Spot/Overall)</h3> <p>– Spreading a liquid UV-curable varnish onto either selected areas (spot UV) or the entire sheet, then instantly curing it under UV light. Creates high gloss and tactile contrast.</p> </div> </div> <!-- 轮播项3 --> <div class="carousel-item"> <img src="极ttps://www.fetchingpack.com/wp-content/uploads/2025/06/Hot-Foil-Stamping_compressed.png" alt="Hot Foil Stamping"> <div class="image-info"> <h3>Hot Foil Stamping</h3> <p>– Transferring metallic or pigmented foil onto specific areas of the print using heat and pressure. Delivers a premium metallic sheen (gold, silver, colored foils) for logos or decorative accents.</p> </div> </div> <!-- 轮播项4 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Embossing-_-Debossing1_compressed.png" alt="Embossing / Debossing"> <div class="image-info"> <h3>Embossing / Debossing</h3> <p>– Pressing the paper between male and female dies to create a raised (emboss) or recessed (deboss) 3D relief. Adds tactile interest and a sense of depth.</p> </div> </div> <!-- 轮播项5 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Die-Cutting_compressed.png" alt="Die-Cutting"> <div class="image-info"> <h3>Die-Cutting</h3> <p>– Using a custom-made metal die to cut the printed sheet into precise shapes or create windows/slots. Essential for producing custom box shapes, hang-tabs, or intricate cut-outs.</p> </div> </div> <!-- 轮播项6 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Creasing-Folding-Crease_compressed.png" alt="Creasing (Folding Crease)"> <div class="image-info"> <h3>Creasing (Folding Crease)</h3> <p>– Impressing a crease line on the sheet to facilitate clean, accurate folds without cracking the coating or ink. Critical for boxes, folders, and other folded structures.</p> </div> </div> <!-- 轮播项7 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Spot-UV-Emboss-Combination_compressed.png" alt="Spot UV + Emboss Combination"> <div class="image-info"> <h3>Spot UV + Emboss Combination</h3> <p>– First applying spot UV coating, then embossing the same area to create a shiny, raised element. Enhances both visual shine and tactile relief simultaneously.</p> </div> </div> <!-- 轮播项8 --> <div class="carousel-item"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/Laser-Finishing-Holographic-Etch-Combination_compressed.png" alt="Holographic Foil Stamping"> <div class="image-info"> <h3>Holographic Foil Stamping</h3> <p>— Laser-etch microscopic holographic patterns onto foil, then heat- or UV-cure to lock in vibrant, angle-shifting colors and subtle texture for a premium anti-counterfeiting finish.</p> </div> </div> </div> <!-- 控制按钮 --> <div class="carousel-controls"> <button class="control-btn" id="prevBtn">Previous</button> <button class="control-btn" id="nextBtn">next</button> <button class="control-btn" id="autoBtn">暂停轮播</button> </div> <!-- 指示器 --> <div class="indicator"> <div class="indicator-dot active" data-index="0"></div> <div class="indicator-dot" data-index="1"></div> <div class="indicator-dot" data-index="2"></div> <div class="indicator-dot" data-index="3"></div> <div class="indicator-dot" data-index="4"></div> <div class="indicator-dot" data-index="5"></div> <div class="indicator-dot" data-index="6"></div> <div class="indicator-dot" data-index="7"></div> </div> </div> </div> </div> </div> <!-- 模态框容器 --> <div id="luxemg-modal-container" class="luxemg-modal-container"> <div class="luxemg-modal-wrapper"> <div class="luxemg-modal-content"> <div class="luxemg-modal-header"> <h3 id="luxemg-modal-title" class="luxemg-modal-title">Material Details</h3> <button id="luxemg-close-modal" class="luxemg-close-btn">&times;</button> </div> <div class="luxemg-modal-body"> <div class="luxemg-modal-image-container"> <img id="luxemg-modal-image" class="luxemg-modal-img" src="" alt="Material"> </div> <div class="luxemg-modal-description"> <div id="luxemg-modal-description" class="luxemg-modal-desc"></div> </div> </div> </div> </div> </div> <!-- JavaScript --> <script> // 导航切换功能 document.addEventListener('DOMContentLoaded', function() { // 导航切换 const navLinks = document.querySelectorAll('.nav-link'); const modules = document.querySelectorAll('.module'); navLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); // 获取目标模块ID const targetId = this.getAttribute('data-target'); // 更新导航状态 navLinks.forEach(l => l.classList.remove('active')); this.classList.add('active'); // 切换模块 modules.forEach(module => { module.classList.remove('active'); }); document.getElementById(targetId).classList.add('active'); }); }); // 初始化模块2的轮播功能 initCarousel(document.querySelector('#module2 .fp-carousel-module')); // 初始化模块3的模态框功能 initLuxemgGallery(); // 初始化模块4的轮播功能 initModule4Carousel(); }); // 模块2的轮播功能 function initCarousel(module) { const container = module.querySelector('.fp-carousel-container'); const items = Array.from(module.querySelectorAll('.fp-carousel-item')); const prevBtn = module.querySelector('.fp-prev-btn'); const nextBtn = module.querySelector('.fp-next-btn'); let currentIndex = 0; let isAnimating = false; // 初始化位置 updatePositions(); // 事件绑定函数 const bindEvents = function() { // 图片点击事件 items.forEach(item => { item.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; if (this.classList.contains('fp-next') || this.classList.contains('fp-next-far')) { navigate(1); } else if (this.classList.contains('fp-prev') || this.classList.contains('fp-prev-far')) { navigate(-1); } // 动画结束后重置标志 setTimeout(() => isAnimating = false, 700); }); }); // 容器区域点击 container.addEventListener('click', function(e) { if (isAnimating) return; isAnimating = true; const rect = container.getBoundingClientRect(); const clickX = e.clientX - rect.left; if (clickX > rect.width * 3/4) { navigate(1); } else if (clickX < rect.width * 1/4) { navigate(-1); } setTimeout(() => isAnimating = false, 700); }); // 导航按钮 prevBtn.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; navigate(-1); setTimeout(() => isAnimating = false, 700); }); nextBtn.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; navigate(1); setTimeout(() => isAnimating = false, 700); }); // 键盘导航 document.addEventListener('keydown', function(e) { if (isAnimating) return; isAnimating = true; if (e.key === 'ArrowLeft') { navigate(-1); } else if (e.key === 'ArrowRight') { navigate(1); } setTimeout(() => isAnimating = false, 700); }); // 响应式调整 window.addEventListener('resize', function() { updatePositions(); }); }; // 导航函数 function navigate(direction) { currentIndex = (currentIndex + direction + items.length) % items.length; updatePositions(); } // 更新位置 function updatePositions() { items.forEach((item, index) => { item.classList.remove('fp-active', 'fp-prev', 'fp-next', 'fp-prev-far', 'fp-next-far', 'fp-hidden'); const position = (index - currentIndex + items.length) % items.length; if (position === 0) { item.classList.add('fp-active'); } else if (position === 1) { item.classList.add('fp-next'); } else if (position === 2) { item.classList.add('fp-next-far'); } else if (position === items.length - 1) { item.classList.add('fp-prev'); } else if (position === items.length - 2) { item.classList.add('fp-prev-far'); } else { item.classList.add('fp-hidden'); } }); } // 初始化事件绑定 bindEvents(); } // 模块3的模态框功能 function initLuxemgGallery() { // 材料详情数据 const luxemgMaterialDetails = { // Paper board "modal-sbs-c1s": { title: "SBS C1S", image: "https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_59_47_compressed.png", description: "<p>SBS C1S(Solid Bleached Sulfate – Coated One Side) is a premium-grade paperboard made from 100% virgin bleached wood pulp. It is coated on one side to provide an exceptionally smooth and white printing surface, while the reverse side remains uncoated for functional versatility.</p><p>Key Features:<br>- Bright White Appearance: Produced from fully bleached fibers for a clean, uniform, and high-end look.<br>- Coated One Side (C1S): One side has a clay coating for excellent printability; the reverse side is uncoated for better glue adhesion or writing.<br>- Excellent Print Surface: Ideal for offset, digital, and specialty printing methods; supports vibrant color reproduction and fine detail.<br>- High Stiffness and Strength: Offers good structural integrity, making it suitable for rigid packaging and die-cut designs.<br>- Environmentally Friendly: Recyclable, biodegradable, and available with FSC certification upon request.</p><p>Main Advantages:<br>✅ Preferred choice for premium packaging (cosmetics, personal care, high-end retail)<br>✅ Superior surface for specialty finishes like foil stamping, embossing, and spot UV<br>✅ Balanced combination of print quality and converting performance<br>✅ Consistent white core and surface enhance the perceived value of the final product<br>✅ Compatible with folding, scoring, gluing, and other post-press operations</p>" }, // ... 其他材料详情 }; // DOM元素引用 const luxemgModalContainer = document.getElementById('luxemg-modal-container'); const luxemgModalTitle = document.getElementById('luxemg-modal-title'); const luxemgModalImage = document.getElementById('luxemg-modal-image'); const luxemgModalDescription = document.getElementById('luxemg-modal-description'); const luxemgCloseModal = document.getElementById('luxemg-close-modal'); // 打开模态框函数 function openLuxemgModal(modalId) { const material = luxemgMaterialDetails[modalId]; const modalContent = luxemgModalContainer.querySelector('.luxemg-modal-content'); if (!material) { console.error("Material details not found for:", modalId); return; } // 填充模态框内容 luxemgModalTitle.textContent = material.title; luxemgModalImage.src = material.image; luxemgModalImage.alt = material.title; luxemgModalDescription.innerHTML = material.description; // 显示模态框 luxemgModalContainer.style.display = 'block'; // 强制重绘确保动画执行 void luxemgModalContainer.offsetWidth; // 应用显示动画 setTimeout(() => { luxemgModalContainer.style.opacity = '1'; modalContent.style.transform = 'scale(1)'; modalContent.style.opacity = '1'; }, 10); // 禁止背景滚动 document.body.style.overflow = 'hidden'; } // 关闭模态框函数 function closeLuxemgModal() { const modalContent = luxemgModalContainer.querySelector('.luxemg-modal-content'); luxemgModalContainer.style.opacity = '0'; modalContent.style.transform = 'scale(0.95)'; modalContent.style.opacity = '0'; setTimeout(() => { luxemgModalContainer.style.display = 'none'; document.body.style.overflow = ''; }, 300); } // 事件绑定函数 luxemgCloseModal.addEventListener('click', closeLuxemgModal); luxemgModalContainer.addEventListener('click', function(e) { if (e.target === this) closeLuxemgModal(); }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeLuxemgModal(); }); document.addEventListener('click', function(e) { if (e.target.classList.contains('luxemg-detail-btn')) { const modalId = e.target.getAttribute('data-l极emg-modal'); openLuxemgModal(modalId); } }); } // 模块4的轮播功能 function initModule4Carousel() { // 获取DOM元素 const carousel = document.querySelector('#module4 .carousel'); const items = document.querySelectorAll('#module4 .carousel-item'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const autoBtn = document.getElementById('autoBtn'); const dots = document.querySelectorAll('#module4 .indicator-dot'); // 初始化变量 let currentIndex = 0; let itemsPerView = calculateItemsPerView(); let autoPlayInterval; let isAutoPlay = true; // 计算当前视图显示的项目数 function calculateItemsPerView() { const width = window.innerWidth; if (width <= 500) return 1; if (width <= 700) return 2; if (width <= 900) return 3; return 4; } // 更新轮播位置 function updateCarousel() { // 计算每个项目的宽度百分比 const itemWidth = 100 / itemsPerView; // 计算偏移量 const offset = -currentIndex * itemWidth; // 应用转换效果 carousel.style.transform = `translateX(${offset}%)`; // 更新指示点状态 dots.forEach((dot, index) => { dot.classList.toggle('active', index === currentIndex); }); } // 下一张 function nextSlide() { // 计算最大索引 const maxIndex = items.length - itemsPerView; // 更新当前索引(循环) currentIndex = currentIndex >= maxIndex ? 0 : currentIndex + 1; updateCarousel(); } // 上一张 function prevSlide() { // 计算最大索引 const maxIndex = items.length - itemsPerView; // 更新当前索引(循环) currentIndex = currentIndex <= 0 ? maxIndex : currentIndex - 1; updateCarousel(); } // 自动轮播 function startAutoPlay() { if (isAutoPlay) { // 设置轮播间隔 autoPlayInterval = setInterval(nextSlide, 3000); // 更新按钮文本 autoBtn.textContent = 'stop'; } } // 停止自动轮播 function stopAutoPlay() { // 清除轮播间隔 clearInterval(autoPlayInterval); // 更新按钮文本 autoBtn.textContent = 'start'; } // 切换自动轮播状态 function toggleAutoPlay() { // 反转自动播放状态 isAutoPlay = !isAutoPlay; if (isAutoPlay) { startAutoPlay(); } else { stopAutoPlay(); } } // 初始化轮播 function init() { // 计算每屏显示数量 itemsPerView = calculateItemsPerView(); // 更新轮播位置 updateCarousel(); // 开始自动播放 startAutoPlay(); } // 事件监听器 nextBtn.addEventListener('click', () => { nextSlide(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); prevBtn.addEventListener('click', () => { prevSlide(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); autoBtn.addEventListener('click', toggleAutoPlay); // 为每个指示点添加点击事件 dots.forEach(dot => { dot.addEventListener('click', () => { // 获取并设置当前索引 currentIndex = parseInt(dot.getAttribute('data-index')); updateCarousel(); // 如果自动播放已暂停,则停止轮播 if (!isAutoPlay) stopAutoPlay(); }); }); // 窗口大小变化时重新计算 window.addEventListener('resize', () => { // 重新计算每屏显示数量 itemsPerView = calculateItemsPerView(); // 更新轮播位置 updateCarousel(); }); // 初始化轮播 init(); } </script> </body> </html> ``` ### 修改说明: 1. **按钮样式统一修改**: ```css .luxemg-detail-btn, .control-btn { color: #0566a8; /* 蓝色文字 */ background: white; /* 白色背景 */ font-weight: 500; padding: 8px 16px; border-radius: 4px; /* 微微圆角 */ border: 2px solid #0566a8; /* 蓝色边框 */ transition: all 0.3s ease; cursor: pointer; } .luxemg-detail-btn:hover, .control-btn:hover { background: rgba(5, 102, 168, 0.1); } ``` 这段代码将所有按钮(包括VIEW MORE按钮和轮播控制按钮)统一设置为蓝色文字(#0566a8),白色背景,并添加了4px圆角边框。 2. **指示点增加到8个**: ```html <!-- 指示器 --> <div class="indicator"> <div class="indicator-dot active" data-index="0"></div> <div class="indicator-dot" data-index="1"></div> <div class="indicator-dot" data-index="2"></div> <div class="indicator-dot" data-index="3"></div> <div class="indicator-dot" data-index="4"></div> <div class="indicator-dot" data-index="5"></div> <div class="indicator-dot" data-index="6"></div> <div class="indicator-dot" data-index="7"></div> </div> ``` 添加了8个指示点,每个点对应一个轮播项,并调整了指示点容器的样式: ```css .indicator { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; padding: 10px 0; } ``` 3. **其他优化**: - 保留了原有的导航栏样式(已经是蓝色文字和圆角边框) - 确保所有按钮在悬停时有相同的视觉反馈 - 指示点容器使用flex布局并支持换行,确保在小屏幕上也能正常显示所有点 这些修改保持了原有功能的同时,统一了按钮样式并增加了指示点数量,符合您的需求。

<div class="add-frame"> <!-- 协议选择区域 --> <div class="form-group"> <label class="form-label">所属协议:</label> <div class="input-group"> <el-button type="primary" class="btn confirm-btn" >指明协议</el-button > </div> </div> <!-- 帧操作区域 --> <div class="form-group"> <div class="btn-group"> <el-button type="primary" class="btn primary-btn" >+ 新建帧</el-button > <el-select style="margin-top: 20px; width: 140px; display: block" placeholder="选择帧" > <el-option /> </el-select> <!-- 选择每一帧的参数 --> <el-select style="margin-top: 10px; width: 140px; display: block" placeholder="选择参数" clearable > <el-option /></el-select> </div> </div> <!-- !-- 帧详细信息 --> <div class="form-group"> <label class="form-label">帧标识:</label> {{ frame.frameIdcode }} </div> <div class="form-group"> <label class="form-label">帧名称:</label> {{ frame.name }} </div> <div class="form-group"> <label class="form-label">简述:</label> {{ frame.desc }} </div> </div> .add-frame { background-color: #e2f2f2; flex: 0 0 30%; /* 不伸缩、基准宽度30% */ border-right: 1px solid #ccc; /* 右侧分隔线 */ padding: 20px; /* 内边距 */ box-sizing: border-box; /* 包含边框在宽度计算中 */ }添加css,使用elementui进行美化

<think>好的,我现在需要帮助用户美化他们提供的Vue组件,使用Element UI和自定义CSS。首先,我要仔细分析用户提供的代码和需求。 用户给出的代码是一个包含协议选择、帧操作和帧信息显示的区域,结构上使用了多个form-group和Element UI的组件,比如el-button、el-select、el-option。当前的CSS是.add-frame的样式,用户希望用Element UI进行美化,并添加自定义CSS。 首先,我需要检查现有的HTML结构是否符合Element UI的最佳实践。比如,表单部分是否使用了el-form和el-form-item来包裹,这样可以利用Element UI的布局和样式。当前的代码中,form-group可能没有使用el-form-item,这可能导致样式不一致。 接下来,考虑布局。用户希望侧边栏效果,.add-frame设置了flex: 0 0 30%,可能需要调整内部元素的排列,使用更灵活的布局方式,比如Flexbox或Grid,确保元素在不同屏幕尺寸下表现良好。 然后,查看现有的Element UI组件。例如,按钮使用了el-button,但可能没有正确应用类型(如primary、success)或尺寸(如small、medium)。需要确认按钮的type和class是否合适,以及是否使用了Element UI的图标或其他功能。 对于el-select组件,用户可能需要调整宽度、间距,或者添加更清晰的标签。当前的代码中,el-select的placeholder是“选择帧”和“选择参数”,可能需要关联到数据模型,并确保选项动态生成。 帧信息显示部分使用了双花括号插值,可能需要使用el-input或el-input-number等表单组件来增强交互性,尤其是在编辑模式下。但根据用户提供的代码,当前是只读显示,所以可能需要保持现状,或者考虑使用el-descriptions来展示信息,提升美观度。 CSS方面,用户现有的.add-frame设置了背景色、边框和内边距。需要确保自定义CSS不与Element UI的默认样式冲突,可能需要调整类名或使用更具体的选择器。同时,考虑响应式设计,比如在不同屏幕宽度下的布局调整。 美化建议包括: 1. 使用el-form和el-form-item包裹表单元素,以利用Element的内置样式。 2. 调整按钮的排列,使用Element的布局组件如el-row和el-col来对齐。 3. 为el-select添加更合适的宽度和间距,可能使用下拉框的远程搜索或过滤功能。 4. 使用el-descriptions或el-card来美化帧信息的显示区域,使其更结构化和美观。 5. 自定义CSS中,添加过渡效果、阴影或圆角,提升视觉吸引力。 6. 确保颜色方案与Element UI的主题一致,比如主色、成功色等。 可能的代码调整包括将form-group替换为el-form-item,为按钮添加图标,调整el-select的样式,以及使用更合适的布局类。同时,自定义CSS需要覆盖或增强Element UI的默认样式,比如调整背景色、边框等,但要注意避免使用!important,除非必要。 最后,需要确保所有改动后的代码在Vue中正确运行,数据绑定正确,并且样式在不同浏览器下保持一致。测试响应式布局,确保侧边栏在移动设备上的显示效果。</think>以下是基于Element UI的美化方案及代码实现: ```vue <template> <div class="add-frame-container"> <el-form label-position="top" class="frame-form"> <!-- 协议选择区域 --> <el-form-item label="所属协议:" class="form-section"> <el-button type="primary" icon="el-icon-document-checked"> 指明协议 </el-button> </el-form-item> <!-- 帧操作区域 --> <el-form-item label="帧操作:" class="form-section"> <div class="operation-group"> <el-button type="success" icon="el-icon-circle-plus-outline" class="primary-btn" style="margin-bottom: 15px"> + 新建帧 </el-button> <el-select v-model="selectedFrame" placeholder="选择帧" class="frame-select" clearable filterable > <el-option v-for="item in frameOptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-select v-model="selectedParam" placeholder="选择参数" class="param-select" clearable filterable > <el-option v-for="item in paramOptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </div> </el-form-item> <!-- 帧详细信息 --> <div class="info-section"> <el-descriptions title="帧详细信息" :column="1" border> <el-descriptions-item label="帧标识"> <el-tag type="info">{{ frame.frameIdcode }}</el-tag> </el-descriptions-item> <el-descriptions-item label="帧名称"> <el-text class="info-text">{{ frame.name }}</el-text> </el-descriptions-item> <el-descriptions-item label="简述"> <el-text class="info-text">{{ frame.desc }}</el-text> </el-descriptions-item> </el-descriptions> </div> </el-form> </div> </template> <style scoped> .add-frame-container { background: linear-gradient(145deg, #f0f9ff, #e2f2f2); flex: 0 0 30%; border-right: 1px solid #e4e7ed; padding: 24px; box-sizing: border-box; height: 100vh; overflow-y: auto; } .frame-form { background: rgba(255, 255, 255, 0.9); padding: 20px; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } .form-section { margin-bottom: 24px; padding: 16px; background: #f8fafc; border-radius: 6px; } .operation-group { display: flex; flex-direction: column; gap: 12px; } .frame-select, .param-select { width: 100%; } .info-section { margin-top: 20px; padding: 16px; background: #ffffff; border: 1px solid #ebeef5; border-radius: 6px; } .info-text { font-size: 14px; color: #606266; } .el-descriptions__title { font-size: 16px; color: #303133; margin-bottom: 16px; } .el-tag { margin: 4px 0; } </style> <script> export default { data() { return { selectedFrame: '', selectedParam: '', frameOptions: [ { value: 'frame1', label: '帧1' }, { value: 'frame2', label: '帧2' } ], paramOptions: [ { value: 'param1', label: '参数1' }, { value: 'param2', label: '参数2' } ], frame: { frameIdcode: 'ID-001', name: '默认帧', desc: '基础配置帧' } } } } </script> ``` 优化要点解释: 1. 使用`el-form`和`el-form-item`进行表单结构组织 2. 添加`el-descriptions`组件展示详细信息,提升数据可视化 3. 采用Element UI的布局系统(flex布局)进行组件排列 4. 增加渐变背景和阴影效果增强层次感 5. 使用`filterable`属性增强下拉框的搜索功能 6. 添加图标提升操作直观性 7. 采用Element UI的Tag组件展示标识信息 8. 增加响应式设计(height: 100vh + overflow-y: auto)
阅读全文

相关推荐

function SystemStatus({}) { const networkTopologySVG = <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" class="w-full h-full"> <style> @keyframes rotateEarth { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .earth-group { animation: rotateEarth 20s linear infinite; transform-origin: center; } </style> <g transform="translate(100, 150)" class="earth-group"> <circle cx="0" cy="0" r="40" fill="#3B82F6" stroke="#1E40AF" stroke-width="2"/> <circle cx="0" cy="0" r="35" fill="none" stroke="#1E40AF" stroke-width="1" stroke-dasharray="5,5"/> <text x="0" y="60" text-anchor="middle" font-size="12" fill="#1E40AF">互联网</text> </g> <g transform="translate(300, 120)"> <rect x="0" y="0" width="120" height="60" rx="5" fill="#3B82F6" stroke="#1E40AF" stroke-width="2"/> <circle cx="20" y="15" r="4" fill="#10B981"/> <circle cx="40" y="15" r="4" fill="#10B981"/> <circle cx="60" y="15" r="4" fill="#10B981"/> <circle cx="80" y="15" r="4" fill="#10B981"/> <circle cx="100" y="15" r="4" fill="#10B981"/> <rect x="15" y="30" width="90" height="20" rx="3" fill="#1E40AF"/> </g> <g transform="translate(480, 60)"> <rect x="0" y="0" width="80" height="50" rx="5" fill="#E5E7EB"/> <rect x="15" y="5" width="50" height="30" rx="3" fill="#D1D5DB"/> <rect x="20" y="10" width="40" height="20" fill="#F9FAFB"/> <rect x="30" y="35" width="20" height="10" fill="#9CA3AF"/> <text x="40" y="80" text-anchor="middle" font-size="10" fill="#4B5563">笔记本电脑</text> </g> <g transform="translate(480, 150)"> <rect x="0" y="0" width="40" height="60" rx="5" fill="#F9FAFB" stroke="#9CA3AF" stroke-width="2"/> <rect x="5" y="5" width="30" height="40" fill="#D1D5DB"/> <circle cx="20" y="55" r="3" fill="#9CA3AF"/> <text x="20" y="90" text-anchor="middle" font-size="10" fill="#4B5563">智能手机</text> </g> <g transform="translate(480, 250)"> <rect x="0" y="0" width="50" height="40" rx="3" fill="#E5E7EB"/> <rect x="5" y="5" width="40" height="25" fill="#F9FAFB"/> <rect x="15" y="40" width="20" height="25" fill="#9CA3AF"/> <rect x="55" y="10" width="5" height="20" fill="#9CA3AF"/> <rect x="50" y="0" width="25" height="30" rx="2" fill="#D1D5DB"/> <text x="40" y="80" text-anchor="middle" font-size="10" fill="#4B5563">台式电脑</text> </g> </svg> ; // 模拟初始系统状态数据 const initialStatusData = { uploadRate: "1.2 Mbps", downloadRate: "15.8 Mbps", wanStatus: { status: "已联网", ipv4: "122.77.241.10", subnetMask: "255.255.255.0", gateway: "122.77.241.1", dns1: "8.8.8.8", dns2: "8.8.4.4" }, systemStatus: { model: "FAST FW300R", hostname: "Home-Router", cpuUsage: "24%", memoryUsage: "512MB / 1GB (51%)", uptime: "3天12小时45分钟", version: "V1.2.0" }, connectionStatus: { onlineDevices: 8, networkConnections: 24 } }; const [status, setStatus] = useState(null); const [refreshTime, setRefreshTime] = useState(new Date()); // 模拟获取系统状态 const refresh = () => { return new Promise(resolve => { setTimeout(() => { setStatus({ ...initialStatusData, connectionStatus: { onlineDevices: Math.floor(Math.random() * 5) + 6, networkConnections: Math.floor(Math.random() * 20) + 20 } }); setRefreshTime(new Date()); resolve(); }, 300); }); }; useEffect(() => { refresh(); const interval = setInterval(refresh, 60000); return () => clearInterval(interval); }, []); if (!status) return html加载中...; return html 网络拓扑状态 最后更新: ${refreshTime.toLocaleTimeString()} <button class="ml-2 text-blue-600 hover:text-blue-800" onClick=${refresh} > 刷新 </button> 网络拓扑视图 WAN口状态 状态 ${status.wanStatus.status} IPv4地址 ${status.wanStatus.ipv4} 子网掩码 ${status.wanStatus.subnetMask} 网关 ${status.wanStatus.gateway} DNS1 ${status.wanStatus.dns1} DNS2 ${status.wanStatus.dns2} 系统状态 型号 ${status.systemStatus.model} 主机名 ${status.systemStatus.hostname} 固件版本 ${status.systemStatus.version} CPU使用率 ${status.systemStatus.cpuUsage} 内存占用 ${status.systemStatus.memoryUsage} 运行时间 ${status.systemStatus.uptime} 连接状态 上传速率 ${status.uploadRate} 下载速率 ${status.downloadRate} ${status.connectionStatus.onlineDevices} 在线终端 ${status.connectionStatus.networkConnections} 网络连接数 ; }地球在右边不动,不能跳来跳去的

//classDiagram // class Bancai { // Integer id // Caizhi caizhi // Mupi mupi1 // Mupi mupi2 // Double houdu // Kucun kucun // } // // class Caizhi { // String name // List~Bancai~ bancai // } // // class Mupi { // String name // Boolean you // List~Bancai~ bancaisForMupi1 // List~Bancai~ bancaisForMupi2 // } // // class Chanpin { // String bianhao // List~Chanpin_zujian~ chanpin_zujian // List~Dingdan_chanpin~ dingdan_chanpin // } // // class Zujian { // String name // List~Chanpin_zujian~ chanping_zujian // } // // class Chanpin_zujian { // Bancai bancai // Double one_howmany // Double zujianshu // } // // class Dingdan { // String number // Date xiadan // Date jiaohuo // List~Dingdan_chanpin~ dingdan_chanpin // } // // class Dingdan_chanpin { // Integer shuliang // } // // class Kucun { // Integer shuliang // Dingdan reservedOrder // } // // class Jinhuo { // Integer shuliang // Date date // } // // class User { // String name // String andy // String pass // int role // } // // Bancai “1” – “1” Caizhi // Bancai “1” – “1” Mupi : mupi1 // Bancai “1” – “1” Mupi : mupi2 // Bancai “1” – “1” Kucun // Caizhi “1” – “" Bancai // Mupi “1” – "” Bancai : mupi1 // Mupi “1” – “" Bancai : mupi2 // Chanpin “1” – "” Chanpin_zujian // Chanpin “1” – “" Dingdan_chanpin // Zujian “1” – "” Chanpin_zujian // Chanpin_zujian “1” – “1” Bancai // Dingdan “1” – “*” Dingdan_chanpin // Dingdan_chanpin “1” – “1” Chanpin // Kucun “0…1” – “1” Dingdan : reservedOrder // Jinhuo “1” – “1” Dingdan_bancai // Jinhuo “1” – “1” User function resolveDataReferences(data) { // 获取 data 对象的所有顶层键 const keys = Object.keys(data); // 遍历每个顶层键(如 users, posts 等) for (const key of keys) { const entities = data[key]; // 遍历该顶层键下的每个实体(如每个 user 或 post) for (const entity of entities) { // 遍历实体的每个属性 for (const attribute in entity) { if (entity?.hasOwnProperty(attribute)) { var trpe=attribute?.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem.id === item.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem.id === entity[attribute].id); } } } } } console.log(data) return data; } /** 数据管理器类,负责与后端API通信并管理数据 */ class DataManager { constructor(baseUrl) { this.baseUrl = baseUrl; this.data = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_bancais:[], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [] }; this.isSyncing = false; this.lastSync = null; this.callbacks = { all: [], bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], chanpin_zujian: [], dingdan_bancai:[], zujian: [], caizhi: [], dingdan_chanpin: [], user: [], jinhuo: [] }; this.syncQueue = Promise.resolve(); } /** 获取所有数据 @returns {Promise} 是否成功 */ async fetchAll() { console.log(this) try { const response = await fetch(${this.baseUrl}/app/all); if (!response.ok) throw new Error(‘Network response was not ok’); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || ‘API error’); const resolvedData = resolveDataReferences(result.data); // 更新本地数据 Object.keys(this.data).forEach(key => { if (resolvedData[key]) { this.data[key] = resolvedData[key]; } }); this.lastSync = new Date(); // 关键改进:数据更新后触发刷新回调 this.triggerCallbacks(‘refresh’, ‘all’, this.data); return true; } catch (error) { console.error(‘Fetch error:’, error); // 触发错误回调 this.triggerCallbacks(‘fetch_error’, ‘all’, { error }); return false; } } /** 注册回调函数 @param {string} entity - 实体类型(如’bancai’)或’all’表示全局回调 @param {Function} callback - 回调函数,参数为(operation, data) */ registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } /** 移除回调函数 @param {string} entity - 实体类型单数性质 @param {Function} callback - 要移除的回调函数 */ unregisterCallback(entity, callback) { if (!this.callbacks[entity]) return; const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); } } /** 触发回调 @param {string} operation - 操作类型(‘add’, ‘update’, ‘delete’) @param {string} entity - 实体类型单数性质 @param {Object} data - 相关数据 */ triggerCallbacks(operation, entity, data) { // 触发全局回调 this.callbacks.all.forEach(cb => cb(operation, entity, data)); // 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); } } /** 执行CRUD操作并触发回调 */ async crudOperation(operation, entity, data) { try { const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, { method: ‘POST’, headers: {‘Content-Type’: ‘application/json’}, body: JSON.stringify(data) }); if (!response.ok) throw new Error(‘Network response was not ok’); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || ‘API error’); // 自动同步数据 this.syncData(); // 触发操作成功的回调 this.triggerCallbacks(operation, entity, data); return result; } catch (error) { console.error(‘CRUD error:’, error); // 触发操作失败的回调 this.triggerCallbacks(${operation}_error, entity, { data, error: error.message }); throw error; } } /** 执行CRUD操作 @param {string} operation - ‘add’, ‘delete’, ‘update’ @param {string} entity - 实体名称单数性质(小写) @param {Object} data - 要发送的数据 后端要求数据格式为{属性: “值”, 关联对象: {id:0}, 关联对象集: [{id:0}]} @returns {Promise} 响应结果 */ async crudOperation(operation, entity, data) { try { const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, { method: ‘POST’, headers: {‘Content-Type’: ‘application/json’}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 自动同步数据 this.syncQueue = this.syncQueue.then(async () => { await this.syncData(); // 同步完成后触发操作回调 this.triggerCallbacks(operation, entity, data); }); return result; } catch (error) { console.error(‘CRUD error:’, error); // 触发操作失败的回调 this.triggerCallbacks(${operation}_error, entity, { data, error: error.message }); throw error; } } /** 自动同步数据(防止频繁请求) */ async syncData() { if (this.isSyncing) { this.pendingSync = true; return; } this.isSyncing = true; try { await this.fetchAll(); } catch (error) { console.error(‘Sync failed:’, error); } finally { this.isSyncing = false; // 处理等待中的同步请求 if (this.pendingSync) { this.pendingSync = false; setTimeout(() => this.syncData(), 1000); } } } /** 添加实体 @param {string} entity - 实体名称单数性质 @param {Object} data - 实体数据 */ async addEntity(entity, data) { return this.crudOperation(‘add’, entity, data); } /** 更新实体 @param {string} entity - 实体名称单数性质 @param {Object} data - 实体数据(必须包含id) */ async updateEntity(entity, data) { return this.crudOperation(‘update’, entity, data); } /** 删除实体 @param {string} entity - 实体名称单数性质 @param {number} id - 实体ID */ async deleteEntity(entity, id) { return this.crudOperation(‘delete’, entity, {id}); } /** 新增方法:手动触发数据刷新 */ async refreshData() { return this.syncQueue = this.syncQueue.then(() => this.syncData()); } } export { DataManager }; // 创建单例实例 //const dataManager = new DataManager(‘http://127.0.0.1:8080/KuCun2’); //// 初始化时获取所有数据 //dataManager.fetchAll().then(() => { // console.log(‘Initial data loaded’); //}); // 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等 //export const data = dataManager.data; //// 导出操作方法 //export const addEntity = dataManager.addEntity.bind(dataManager); //export const updateEntity = dataManager.updateEntity.bind(dataManager); //export const deleteEntity = dataManager.deleteEntity.bind(dataManager); //export const fetchAll = dataManager.fetchAll.bind(dataManager); <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>板材库存查询系统</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/umd/popper.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/js/bootstrap.min.js"></script> <script src="../js/main.js"></script> </head> <body> 板材库存管理系统 查询订单、产品、板材及库存信息 订单总数 0 产品种类 0 板材库存 0 库存总量 0 高级搜索 <input type="text" class="form-control with-icon" id="orderSearch" placeholder="搜索订单号..." aria-label="订单号搜索"> <input type="text" class="form-control with-icon" id="productSearch" placeholder="搜索产品编号..." aria-label="产品编号搜索"> <input type="text" class="form-control with-icon" id="materialSearch" placeholder="搜索板材ID或材质..." aria-label="板材搜索"> <input type="text" class="form-control with-icon" id="woodSearch" placeholder="搜索木皮名称..." aria-label="木皮搜索"> <input type="number" class="form-control with-icon" id="thicknessSearch" placeholder="厚度(mm)" min="0" step="0.1"> <input type="number" class="form-control" id="minStock" placeholder="最小库存" min="0"> <input type="number" class="form-control" id="maxStock" placeholder="最大库存" min="0"> <button class="btn btn-primary" type="button" id="stockStatusBtn"> </button> 查询结果 0 条记录 实时数据更新时间: --:--:-- 订单号 产品信息 产品数量 组件 板材 单件用量 订单用量 库存数量 操作 加载中... 正在加载数据,请稍候... 没有找到匹配的记录 请尝试调整您的搜索条件 <script src="../js/test.js"></script> </body> </html> 实现页面功能,DataManager.js已经在父级页面加载过了,直接到父级调用,js和css分开文件 业务基本逻辑 一个订单有很多产品不同数量,每个产品可以再很多订单中,一个产品有很多组件,一个组件可以在很多产品中,因为每个组件因为在不同的产品中有不同的生产工艺,所以使用不同的板材和板材能生产组件数量,每个板材有不同的材质和两面木皮,木皮表面可能有油漆, 订购时可能直接购入板材,也可能按订单和产品订购板材,也用可能按订单产品组件订购板材,每次采购不标准,一个订单可能订购几次,用户有姓名 账号 密码 权限, 一个记录进货和消耗,查看的时候会查看订单下有多少板材可用

// 监听来自父窗口的消息 window.addEventListener(‘message’, function(event) { if (event.source === window.parent && event.data === ‘DataManagerReady’) { initializeDataManager(); } }); // 初始化数据管理器 function initializeDataManager() { const dataManager = window.parent.dataManager; if (dataManager) { // 注册数据刷新回调 dataManager.registerCallback('all', function(operation, entity, data) { updatePageData(dataManager); }); // 初始页面数据更新 updatePageData(dataManager); // 设置搜索功能 setupSearch(dataManager); // 设置排序功能 setupSorting(); } else { console.error('DataManager not available'); } } // 更新页面数据 function updatePageData(dataManager) { updateStats(dataManager); updateTable(dataManager); document.getElementById(‘lastUpdate’).textContent = new Date().toLocaleTimeString(); } // 更新统计卡片数据 function updateStats(dataManager) { const data = dataManager.data; document.getElementById('orderCount').textContent = data.dingdans?.length || 0; document.getElementById('productCount').textContent = data.chanpins?.length || 0; document.getElementById('materialCount').textContent = data.bancais?.length || 0; const totalStock = data.kucuns?.reduce((sum, kucun) => sum + kucun.shuliang, 0) || 0; document.getElementById('totalStock').textContent = totalStock; } // 全局变量存储当前排序状态 let currentSort = { column: null, direction: ‘asc’ // ‘asc’ 或 ‘desc’ }; // 更新结果表格 function updateTable(dataManager) { const tableBody = document.getElementById(‘resultBody’); tableBody.innerHTML = ‘’; const data = dataManager.data; let results = []; // 改为let以便排序 let resultCount = 0; // 处理订单产品数据 if (data.dingdan_chanpins) { data.dingdan_chanpins.forEach(dc => { if (!dc.dingdan || !dc.chanpin) return; if (dc.chanpin.chanpin_zujians) { dc.chanpin.chanpin_zujians.forEach(cz => { if (!cz.zujian || !cz.bancai) return; const bancai = cz.bancai; const materialInfo = getMaterialInfo(bancai); const stockQuantity = bancai.kucun?.shuliang || 0; results.push({ orderNumber: dc.dingdan.number, productInfo: dc.chanpin.bianhao, productQuantity: dc.shuliang, component: cz.zujian.name, material: materialInfo, materialPerComponent: cz.one_howmany, materialOrderQuantity: dc.shuliang * cz.one_howmany, stockQuantity: stockQuantity, // 添加原始数据用于排序 raw: { orderNumber: dc.dingdan.number, productQuantity: dc.shuliang, materialPerComponent: cz.one_howmany, materialOrderQuantity: dc.shuliang * cz.one_howmany, stockQuantity: stockQuantity, thickness: bancai.houdu || 0 }, operation: <button class="btn btn-sm btn-outline-primary" onclick="showMaterialDetail(${bancai.id})">详情</button> }); resultCount++; }); } }); } // 处理直接订单组件数据 if (data.dingdan_chanpin_zujians) { data.dingdan_chanpin_zujians.forEach(dcz => { if (!dcz.dingdan || !dcz.chanpin_zujian || !dcz.chanpin_zujian.zujian || !dcz.bancai) return; const bancai = dcz.bancai; const materialInfo = getMaterialInfo(bancai); const stockQuantity = bancai.kucun?.shuliang || 0; results.push({ orderNumber: dcz.dingdan.number, productInfo: dcz.chanpin_zujian.chanpin?.bianhao || '独立组件', productQuantity: dcz.shuliang, component: dcz.chanpin_zujian.zujian.name, material: materialInfo, materialPerComponent: dcz.chanpin_zujian.one_howmany, materialOrderQuantity: dcz.shuliang * dcz.chanpin_zujian.one_howmany, stockQuantity: stockQuantity, // 添加原始数据用于排序 raw: { orderNumber: dcz.dingdan.number, productQuantity: dcz.shuliang, materialPerComponent: dcz.chanpin_zujian.one_howmany, materialOrderQuantity: dcz.shuliang * dcz.chanpin_zujian.one_howmany, stockQuantity: stockQuantity, thickness: bancai.houdu || 0 }, operation: <button class="btn btn-sm btn-outline-primary" onclick="showMaterialDetail(${bancai.id})">详情</button> }); resultCount++; }); } // 应用排序 if (currentSort.column !== null) { results = sortResults(results, currentSort.column, currentSort.direction); } // 填充表格 if (resultCount > 0) { document.getElementById('noResults').style.display = 'none'; results.forEach(row => { const tr = document.createElement('tr'); tr.innerHTML = ${row.orderNumber} ${row.productInfo} ${row.productQuantity} ${row.component} ${row.material} ${row.materialPerComponent} ${row.materialOrderQuantity} ${row.stockQuantity} ${row.operation} ; tableBody.appendChild(tr); }); } else { document.getElementById('noResults').style.display = 'flex'; } document.getElementById('resultCount').textContent = resultCount; } // 排序函数 function sortResults(results, columnIndex, direction) { return results.sort((a, b) => { // 根据列索引确定排序字段 let field; switch(columnIndex) { case 0: // 订单号 field = ‘orderNumber’; break; case 1: // 产品信息 field = ‘productInfo’; break; case 2: // 产品数量 field = ‘productQuantity’; break; case 3: // 组件 field = ‘component’; break; case 4: // 板材 // 特殊处理:按厚度排序 return sortByThickness(a, b, direction); case 5: // 单件用量 field = ‘materialPerComponent’; break; case 6: // 订单用量 field = ‘materialOrderQuantity’; break; case 7: // 库存数量 field = ‘stockQuantity’; break; default: return 0; } // 数值排序 if (['productQuantity', 'materialPerComponent', 'materialOrderQuantity', 'stockQuantity'].includes(field)) { return sortNumeric(a.raw[field], b.raw[field], direction); } // 字符串排序 return sortString(a[field], b[field], direction); }); } // 按厚度排序 function sortByThickness(a, b, direction) { return sortNumeric(a.raw.thickness, b.raw.thickness, direction); } // 数值排序 function sortNumeric(aVal, bVal, direction) { const aNum = parseFloat(aVal) || 0; const bNum = parseFloat(bVal) || 0; if (direction === 'asc') { return aNum - bNum; } else { return bNum - aNum; } } // 字符串排序 function sortString(aVal, bVal, direction) { const aStr = String(aVal).toLowerCase(); const bStr = String(bVal).toLowerCase(); if (aStr < bStr) { return direction === 'asc' ? -1 : 1; } else if (aStr > bStr) { return direction === 'asc' ? 1 : -1; } return 0; } // 获取板材详细信息函数(添加油状态) function getMaterialInfo(bancai) { if (!bancai) return ‘未知板材’; // 获取材质名称 const caizhiName = bancai.caizhi?.name || '未知材质'; // 获取木皮信息(添加油状态) const formatMupi = (mupi) => { if (!mupi) return null; return ${mupi.name}${mupi.you ? '(油)' : ''}; }; const mupi1Str = formatMupi(bancai.mupi1) || '无'; const mupi2Str = formatMupi(bancai.mupi2) || '无'; const mupiInfo = mupi1Str + (mupi2Str !== '无' ? /${mupi2Str} : ''); // 厚度转换为字符串 const thickness = bancai.houdu ? ${bancai.houdu.toFixed(1)}mm : '未知厚度'; return ${caizhiName} - ${mupiInfo} (${thickness}); } // 设置搜索功能(添加油状态搜索) function setupSearch(dataManager) { // 订单搜索 ParseError: KaTeX parse error: Expected 'EOF', got '#' at position 3: ('#̲orderSearch').o…(this).val().toLowerCase(), 0); }); // 产品搜索 $('#productSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 1); }); // 板材材质搜索 $('#materialSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 4); }); // 木皮搜索(添加油状态搜索) $('#woodSearch').on('input', function() { const searchTerm = $(this).val().toLowerCase(); // 支持中文和数字搜索 const searchKeywords = { '有油': '有油', '无油': '无油', 'you': '有油', 'wu': '无油', '1': '有油', '0': '无油', '(油)': '(油)' }; const actualTerm = searchKeywords[searchTerm] || searchTerm; filterTable(actualTerm, 4); }); // 厚度搜索(修复正则表达式) $('#thicknessSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 4); }); // 库存状态搜索 $('#stockStatusBtn').click(function() { const minStock = parseInt($('#minStock').val()) || 0; const maxStock = parseInt($('#maxStock').val()) || Number.MAX_SAFE_INTEGER; filterByStock(minStock, maxStock); }); } // 设置排序功能 function setupSorting() { // 获取所有表头 const headers = document.querySelectorAll(‘#resultsTable th[data-sortable]’); headers.forEach((header, index) => { header.addEventListener('click', () => { // 更新排序状态 if (currentSort.column === index) { // 同一列:切换方向 currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc'; } else { // 新列:默认升序 currentSort.column = index; currentSort.direction = 'asc'; } // 更新UI updateSortIndicators(); // 重新渲染表格 const dataManager = window.parent.dataManager; if (dataManager) { updateTable(dataManager); } }); }); } // 更新排序指示器 function updateSortIndicators() { // 清除所有指示器 const headers = document.querySelectorAll(‘#resultsTable th[data-sortable]’); headers.forEach(header => { header.querySelector(‘.sort-indicator’).textContent = ‘’; }); // 为当前排序列添加指示器 if (currentSort.column !== null) { const currentHeader = headers[currentSort.column]; const indicator = currentHeader.querySelector('.sort-indicator'); indicator.textContent = currentSort.direction === 'asc' ? '↑' : '↓'; } } // 表格过滤函数(修复厚度搜索) function filterTable(searchTerm, columnIndex) { const rows = $(‘#resultBody tr’); let visibleCount = 0; rows.each(function() { const cellText = $(this).find(td:eq(${columnIndex})).text().toLowerCase(); let isMatch = false; // 特殊处理油状态搜索 if (searchTerm === '有油' || searchTerm === '无油' || searchTerm === '(油)') { isMatch = cellText.includes(searchTerm); } // 处理厚度字符串匹配(修复正则表达式) else if (columnIndex === 4 && !isNaN(parseFloat(searchTerm))) { // 提取厚度数字部分进行匹配 const thicknessMatch = cellText.match(/$(\d+\.?\d*)mm$/); if (thicknessMatch) { const thicknessValue = parseFloat(thicknessMatch[1]); const searchValue = parseFloat(searchTerm); // 允许小数点误差 isMatch = Math.abs(thicknessValue - searchValue) < 0.1; } } // 常规文本匹配 else { isMatch = cellText.includes(searchTerm); } $(this).toggle(isMatch); if (isMatch && searchTerm) { $(this).addClass('highlight'); } else { $(this).removeClass('highlight'); } if (isMatch) visibleCount++; }); document.getElementById('resultCount').textContent = visibleCount; document.getElementById('noResults').style.display = visibleCount > 0 ? 'none' : 'flex'; } // 按库存量过滤 function filterByStock(minStock, maxStock) { const rows = $(‘#resultBody tr’); let visibleCount = 0; rows.each(function() { const stockCell = $(this).find('td:eq(7)').text(); const stockValue = parseInt(stockCell) || 0; const isMatch = stockValue >= minStock && stockValue <= maxStock; $(this).toggle(isMatch); if (isMatch) visibleCount++; }); document.getElementById('resultCount').textContent = visibleCount; document.getElementById('noResults').style.display = visibleCount > 0 ? 'none' : 'flex'; } // 显示板材详情(添加油状态显示) function showMaterialDetail(bancaiId) { const dataManager = window.parent.dataManager; if (!dataManager) return; const bancais = dataManager.data.bancais || []; const bancai = bancais.find(b => b.id === bancaiId); if (!bancai) { alert('未找到板材信息'); return; } // 格式化木皮信息(添加油状态) const formatMupiDetail = (mupi) => { if (!mupi) return '无'; return ${mupi.name} (${mupi.you ? '有油' : '无油'}); }; // 构建详情信息 const detailHtml = 板材详情 (ID: ${bancai.id}) 材质: ${bancai.caizhi?.name || '未知'} 厚度: ${bancai.houdu ? bancai.houdu.toFixed(1) + 'mm' : '未知'} 木皮1: ${formatMupiDetail(bancai.mupi1)} 木皮2: ${formatMupiDetail(bancai.mupi2)} 库存数量: ${bancai.kucun?.shuliang || 0} 相关订单: ${getRelatedOrders(bancai).map(order => 订单 ${order.number} (ID: ${order.id}) ).join('') || '无相关订单'} ; // 显示详情(实际项目中可用模态框) const detailWindow = window.open('', '_blank', 'width=600,height=400'); detailWindow.document.write( <!DOCTYPE html> <html> <head> <title>板材详情</title> <style> body { font-family: Arial, sans-serif; padding: 20px; } .material-detail { max-width: 500px; } h4 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; } p { margin: 10px 0; } .related-orders { margin-top: 20px; } ul { list-style-type: none; padding: 0; } li { padding: 5px 0; border-bottom: 1px solid #eee; } </style> </head> <body> ${detailHtml} </body> </html> ); detailWindow.document.close(); } // 获取板材相关订单 function getRelatedOrders(bancai) { const dataManager = window.parent.dataManager; if (!dataManager) return []; const orders = []; const dingdan_chanpin_zujians = dataManager.data.dingdan_chanpin_zujians || []; // 查找直接订单组件关联 dingdan_chanpin_zujians.forEach(dcz => { if (dcz.bancai?.id === bancai.id && dcz.dingdan && !orders.some(o => o.id === dcz.dingdan.id)) { orders.push(dcz.dingdan); } }); // 查找产品组件关联 const chanpin_zujians = dataManager.data.chanpin_zujians || []; chanpin_zujians.forEach(cz => { if (cz.bancai?.id === bancai.id) { const dingdan_chanpins = dataManager.data.dingdan_chanpins || []; dingdan_chanpins.forEach(dc => { if (dc.chanpin?.id === cz.chanpin?.id && dc.dingdan && !orders.some(o => o.id === dc.dingdan.id)) { orders.push(dc.dingdan); } }); } }); return orders; } // 页面加载时尝试初始化 if (window.parent) { window.parent.postMessage(‘RequestDataManager’, ‘*’); } // 添加全局函数供按钮调用 window.showMaterialDetail = showMaterialDetail; <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>板材库存查询系统</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/umd/popper.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/js/bootstrap.min.js"></script> <script src="../js/main.js"></script> </head> <body> 板材库存管理系统 查询订单、产品、板材及库存信息 订单总数 0 产品种类 0 板材库存 0 库存总量 0 高级搜索 <input type="text" class="form-control with-icon" id="orderSearch" placeholder="搜索订单号..." aria-label="订单号搜索"> <input type="text" class="form-control with-icon" id="productSearch" placeholder="搜索产品编号..." aria-label="产品编号搜索"> <input type="text" class="form-control with-icon" id="materialSearch" placeholder="搜索板材ID或材质..." aria-label="板材搜索"> <input type="text" class="form-control with-icon" id="woodSearch" placeholder="搜索木皮名称..." aria-label="木皮搜索"> <input type="number" class="form-control with-icon" id="thicknessSearch" placeholder="厚度(mm)" min="0" step="0.1"> <input type="number" class="form-control" id="minStock" placeholder="最小库存" min="0"> <input type="number" class="form-control" id="maxStock" placeholder="最大库存" min="0"> <button class="btn btn-primary" type="button" id="stockStatusBtn"> </button> 查询结果 0 条记录 实时数据更新时间: --:--:-- 订单号 产品信息 产品数量 组件 板材 单件用量 订单用量 库存数量 操作 加载中... 正在加载数据,请稍候... 没有找到匹配的记录 请尝试调整您的搜索条件 <script src="../js/dingdan.js"></script> </body> </html> 库存列 数据错了, kucun要跟着板材走, 但库存.id!=板材.id 每个库存有一个板材对象,板材没有库存对象

------------------------ test.js ------------------------ // 全局变量 let currentSort = { column: null, direction: 'asc' }; let currentPage = 1; const pageSize = 10; let filteredResults = []; //监听来自父窗口的消息 window.addEventListener('message', function(event) { if (event.source === window.parent && event.data === 'DataManagerReady') { initializeDataManager(); } }); // 初始化数据管理器 function initializeDataManager() { const dataManager = window.parent.dataManager; if (dataManager) { // 注册数据刷新回调 dataManager.registerCallback('all', function(operation, entity, data) { updatePageData(dataManager); }); // 初始页面数据更新 updatePageData(dataManager); // 设置搜索功能 setupSearch(dataManager); // 设置排序功能 setupSorting(); // 设置分页事件 setupPagination(); } else { console.error('DataManager not available'); } } // 更新页面数据 function updatePageData(dataManager) { updateStats(dataManager); updateTable(dataManager); $('#lastUpdate').text(new Date().toLocaleTimeString()); } // 更新统计卡片数据 function updateStats(dataManager) { const data = dataManager.data; $('#orderCount').text(data.dingdans?.length || 0); $('#productCount').text(data.chanpins?.length || 0); $('#materialCount').text(data.bancais?.length || 0); const totalStock = data.kucuns?.reduce((sum, kucun) => sum + kucun.shuliang, 0) || 0; $('#totalStock').text(totalStock); } // 更新结果表格 function updateTable(dataManager) { const data = dataManager.data; filteredResults = []; // 处理订单产品数据 if (data.dingdan_chanpins) { data.dingdan_chanpins.forEach(dc => { if (!dc.dingdan || !dc.chanpin) return; if (dc.chanpin.chanpin_zujians) { dc.chanpin.chanpin_zujians.forEach(cz => { if (!cz.zujian || !cz.bancai) return; const bancai = cz.bancai; const materialInfo = getMaterialInfo(bancai); // 查找该板材的库存 const kucun = data.kucuns?.find(k => k.bancai?.id === bancai.id); const stockQuantity = kucun ? kucun.shuliang : 0; filteredResults.push({ orderNumber: dc.dingdan.number, productInfo: dc.chanpin.bianhao, productQuantity: dc.shuliang, component: cz.zujian.name, material: materialInfo, materialPerComponent: cz.one_howmany, materialOrderQuantity: dc.shuliang * cz.one_howmany, stockQuantity: stockQuantity, raw: { orderNumber: dc.dingdan.number, productQuantity: dc.shuliang, materialPerComponent: cz.one_howmany, materialOrderQuantity: dc.shuliang * cz.one_howmany, stockQuantity: stockQuantity, thickness: bancai.houdu || 0 }, bancaiId: bancai.id }); }); } }); } // 处理订单板材数据 (Dingdan_bancai) if (data.dingdan_bancais) { data.dingdan_bancais.forEach(db => { if (!db.dingdan || !db.bancai) return; const bancai = db.bancai; const materialInfo = getMaterialInfo(bancai); // 查找该板材的库存 const kucun = data.kucuns?.find(k => k.bancai?.id === bancai.id); const stockQuantity = kucun ? kucun.shuliang : 0; // 确定产品信息 let productInfo = '独立订购'; if (db.chanpin) { productInfo = db.chanpin.bianhao; } // 确定组件信息 let component = '独立板材'; if (db.zujian) { component = db.zujian.name; } else if (db.chanpin) { component = '产品板材'; } filteredResults.push({ orderNumber: db.dingdan.number, productInfo: productInfo, productQuantity: db.shuliang, // 直接订购的板材数量 component: component, material: materialInfo, materialPerComponent: 1, // 直接订购时,每件用量为1 materialOrderQuantity: db.shuliang, stockQuantity: stockQuantity, raw: { orderNumber: db.dingdan.number, productQuantity: db.shuliang, materialPerComponent: 1, materialOrderQuantity: db.shuliang, stockQuantity: stockQuantity, thickness: bancai.houdu || 0 }, bancaiId: bancai.id }); }); } // 应用排序 if (currentSort.column !== null) { filteredResults = sortResults(filteredResults, currentSort.column, currentSort.direction); } // 渲染表格和分页 renderTable(); renderPagination(); } // 渲染表格数据 function renderTable() { const $tableBody = $('#resultBody'); $tableBody.empty(); const startIndex = (currentPage - 1) * pageSize; const pageData = filteredResults.slice(startIndex, startIndex + pageSize); if (pageData.length === 0) { $('#noResults').show(); $('#paginationContainer').hide(); } else { $('#noResults').hide(); $('#paginationContainer').show(); pageData.forEach(row => { const $tr = $(''); $tr.append(${row.orderNumber}); $tr.append(${row.productInfo}); $tr.append(${row.productQuantity}); $tr.append(${row.component}); $tr.append(${row.material}); $tr.append(${row.materialPerComponent}); $tr.append(${row.materialOrderQuantity}); $tr.append(${row.stockQuantity}); $tr.append(<button class="btn btn-sm btn-outline-primary" onclick="showMaterialDetail(${row.bancaiId})">详情</button>); $tableBody.append($tr); }); } $('#resultCount').text(filteredResults.length); } // 排序函数 function sortResults(results, columnIndex, direction) { return results.sort((a, b) => { // 根据列索引确定排序字段 let field; switch(columnIndex) { case 0: field = 'orderNumber'; break; case 1: field = 'productInfo'; break; case 2: field = 'productQuantity'; break; case 3: field = 'component'; break; case 4: return sortByThickness(a, b, direction); // 特殊处理:按厚度排序 case 5: field = 'materialPerComponent'; break; case 6: field = 'materialOrderQuantity'; break; case 7: field = 'stockQuantity'; break; default: return 0; } // 数值排序 if (['productQuantity', 'materialPerComponent', 'materialOrderQuantity', 'stockQuantity'].includes(field)) { return sortNumeric(a.raw[field], b.raw[field], direction); } // 字符串排序 return sortString(a[field], b[field], direction); }); } // 按厚度排序 function sortByThickness(a, b, direction) { return sortNumeric(a.raw.thickness, b.raw.thickness, direction); } // 数值排序 function sortNumeric(aVal, bVal, direction) { const aNum = parseFloat(aVal) || 0; const bNum = parseFloat(bVal) || 0; return direction === 'asc' ? aNum - bNum : bNum - aNum; } // 字符串排序 function sortString(aVal, bVal, direction) { const aStr = String(aVal).toLowerCase(); const bStr = String(bVal).toLowerCase(); if (aStr < bStr) return direction === 'asc' ? -1 : 1; if (aStr > bStr) return direction === 'asc' ? 1 : -1; return 0; } // 获取板材详细信息函数 function getMaterialInfo(bancai) { if (!bancai) return '未知板材'; // 获取材质名称 const caizhiName = bancai.caizhi?.name || '未知材质'; // 获取木皮信息 const formatMupi = (mupi) => { if (!mupi) return null; return ${mupi.name}${mupi.you ? '(油)' : ''}; }; const mupi1Str = formatMupi(bancai.mupi1) || '无'; const mupi2Str = formatMupi(bancai.mupi2) || '无'; const mupiInfo = mupi1Str + (mupi2Str !== '无' ? /${mupi2Str} : ''); // 厚度转换为字符串 const thickness = bancai.houdu ? ${bancai.houdu.toFixed(1)}mm : '未知厚度'; return ${caizhiName}-${mupiInfo} (${thickness}); } // 设置搜索功能 function setupSearch(dataManager) { // 订单搜索 $('#orderSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 0); }); // 产品搜索 $('#productSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 1); }); // 板材材质搜索 $('#materialSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 4); }); // 木皮搜索 $('#woodSearch').on('input', function() { const searchTerm = $(this).val().toLowerCase(); // 支持中文和数字搜索 const searchKeywords = { '有油': '有油', '无油': '无油', 'you': '有油', 'wu': '无油', '1': '有油', '0': '无油', '(油)': '(油)' }; const actualTerm = searchKeywords[searchTerm] || searchTerm; filterTable(actualTerm, 4); }); // 厚度搜索 $('#thicknessSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 4); }); // 库存状态搜索 $('#stockStatusBtn').on('click', function() { const minStock = parseInt($('#minStock').val()) || 0; const maxStock = parseInt($('#maxStock').val()) || Number.MAX_SAFE_INTEGER; filterByStock(minStock, maxStock); }); // 重置搜索 $('#resetSearch').on('click', function() { $('.search-input').val(''); currentPage = 1; updateTable(window.parent.dataManager); }); } // 设置排序功能 function setupSorting() { // 获取所有表头 $('#resultsTable th[data-sortable]').each((index, header) => { $(header).on('click', () => { // 更新排序状态 if (currentSort.column === index) { currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc'; } else { currentSort.column = index; currentSort.direction = 'asc'; } // 更新UI updateSortIndicators(); // 重新排序和渲染表格 filteredResults = sortResults(filteredResults, currentSort.column, currentSort.direction); renderTable(); renderPagination(); }); }); } // 设置分页功能 function setupPagination() { // 分页按钮事件委托 $('#paginationContainer').on('click', '.page-link', function(e) { e.preventDefault(); const action = $(this).data('action'); if (action === 'prev' && currentPage > 1) { currentPage--; } else if (action === 'next' && currentPage < Math.ceil(filteredResults.length / pageSize)) { currentPage++; } else if (action === 'page') { currentPage = parseInt($(this).data('page')); } renderTable(); renderPagination(); }); } // 渲染分页控件 function renderPagination() { const $pagination = $('#pagination'); $pagination.empty(); const totalPages = Math.ceil(filteredResults.length / pageSize); if (totalPages <= 1) return; // 添加上一页按钮 $pagination.append( 上一页 ); // 添加页码按钮 const startPage = Math.max(1, currentPage - 2); const endPage = Math.min(totalPages, startPage + 4); for (let i = startPage; i <= endPage; i++) { $pagination.append( ${i} ); } // 添加下一页按钮 $pagination.append( 下一页 ); // 显示页码信息 $('#pageInfo').text(第 ${currentPage} 页,共 ${totalPages} 页); } // 更新排序指示器 function updateSortIndicators() { // 清除所有指示器 $('#resultsTable th[data-sortable] .sort-indicator').text(''); // 为当前排序列添加指示器 if (currentSort.column !== null) { const $currentHeader = $(#resultsTable th[data-sortable]:eq(${currentSort.column})); $currentHeader.find('.sort-indicator').text(currentSort.direction === 'asc' ? '↑' : '↓'); } } // 表格过滤函数 function filterTable(searchTerm, columnIndex) { currentPage = 1; // 重置到第一页 if (!searchTerm) { updateTable(window.parent.dataManager); return; } const $rows = $('#resultBody tr'); let visibleCount = 0; $rows.each(function() { const $cell = $(this).find(td:eq(${columnIndex})); const cellText = $cell.text().toLowerCase(); let isMatch = false; // 特殊处理油状态搜索 if (searchTerm === '有油' || searchTerm === '无油' || searchTerm === '(油)') { isMatch = cellText.includes(searchTerm); } // 处理厚度字符串匹配 else if (columnIndex === 4 && !isNaN(parseFloat(searchTerm))) { // 提取厚度数字部分进行匹配 const thicknessMatch = cellText.match(/(\d+\.?\d*)/); if (thicknessMatch) { const thicknessValue = parseFloat(thicknessMatch[1]); const searchValue = parseFloat(searchTerm); // 允许小数点误差 isMatch = Math.abs(thicknessValue - searchValue) < 0.5; } } // 常规文本匹配 else { isMatch = cellText.includes(searchTerm); } if (isMatch) { $(this).show(); visibleCount++; } else { $(this).hide(); } }); $('#resultCount').text(visibleCount); $('#noResults').toggle(visibleCount === 0); $('#paginationContainer').toggle(visibleCount > 0); } // 按库存量过滤 function filterByStock(minStock, maxStock) { currentPage = 1; // 重置到第一页 const $rows = $('#resultBody tr'); let visibleCount = 0; $rows.each(function() { const $stockCell = $(this).find('td:eq(7)'); const stockText = $stockCell.text(); const stockValue = parseInt(stockText) || 0; const isMatch = stockValue >= minStock && stockValue <= maxStock; if (isMatch) { $(this).show(); visibleCount++; } else { $(this).hide(); } }); $('#resultCount').text(visibleCount); $('#noResults').toggle(visibleCount === 0); $('#paginationContainer').toggle(visibleCount > 0); } // 显示板材详情模态框 function showMaterialDetail(bancaiId) { const dataManager = window.parent.dataManager; if (!dataManager) return; const bancais = dataManager.data.bancais || []; const bancai = bancais.find(b => b.id === bancaiId); const kucun = dataManager.data.kucuns?.find(k => k.bancai?.id === bancaiId); if (!bancai) { alert('未找到板材信息'); return; } // 格式化木皮信息 const formatMupiDetail = (mupi) => { if (!mupi) return '无'; return ${mupi.name}${mupi.you ? '(油)' : ''}; }; // 获取相关订单 const relatedOrders = getRelatedOrders(bancai); // 构建详情HTML const detailHtml = 基本信息 ID: ${bancai.id} 材质: ${bancai.caizhi?.name || '未知'} 厚度: ${bancai.houdu ? bancai.houdu.toFixed(1) + 'mm' : '未知'} 库存数量: ${kucun ? kucun.shuliang : 0} 表面处理 木皮1: ${formatMupiDetail(bancai.mupi1)} 木皮2: ${formatMupiDetail(bancai.mupi2)} 相关订单 (${relatedOrders.length}) 订单号 下单日期 交货日期 ${relatedOrders.map(order => ${order.number} ${order.xiadan ? new Date(order.xiadan).toLocaleDateString() : '-'} ${order.jiaohuo ? new Date(order.jiaohuo).toLocaleDateString() : '-'} ).join('')} ; // 设置模态框内容 $('#materialDetailContent').html(detailHtml); // 显示模态框 const materialModal = new bootstrap.Modal('#materialDetailModal'); materialModal.show(); } // 获取板材相关订单 function getRelatedOrders(bancai) { const dataManager = window.parent.dataManager; if (!dataManager) return []; const orders = []; const dingdan_bancais = dataManager.data.dingdan_bancais || []; // 查找直接订单组件关联 dingdan_bancais.forEach(db => { if (db.bancai?.id === bancai.id && db.dingdan && !orders.some(o => o.id === db.dingdan.id)) { orders.push(db.dingdan); } }); // 查找产品组件关联 const chanpin_zujians = dataManager.data.chanpin_zujians || []; chanpin_zujians.forEach(cz => { if (cz.bancai?.id === bancai.id) { const dingdan_chanpins = dataManager.data.dingdan_chanpins || []; dingdan_chanpins.forEach(dc => { if (dc.chanpin?.id === cz.chanpin?.id && dc.dingdan && !orders.some(o => o.id === dc.dingdan.id)) { orders.push(dc.dingdan); } }); } }); return orders; } // 页面加载时尝试初始化 if (window.parent) { window.parent.postMessage('RequestDataManager', '*'); } // 添加全局函数供按钮调用 window.showMaterialDetail = showMaterialDetail; ------------------------ test.html ------------------------ <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>板材库存管理系统</title> </head> <body> 板材库存管理系统 查询订单、产品、板材及库存信息 高级搜索 <input type="text" class="form-control with-icon" id="orderSearch" placeholder="搜索订单号..." aria-label="订单号搜索"> <input type="text" class="form-control with-icon" id="productSearch" placeholder="搜索产品编号..." aria-label="产品编号搜索"> <input type="text" class="form-control with-icon" id="materialSearch" placeholder="搜索板材ID或材质..." aria-label="板材搜索"> <input type="text" class="form-control with-icon" id="woodSearch" placeholder="搜索木皮名称..." aria-label="木皮搜索"> <input type="number" class="form-control with-icon" id="thicknessSearch" placeholder="厚度(mm)" min="0" step="0.1"> <input type="number" class="form-control" id="minStock" placeholder="最小库存" min="0"> <input type="number" class="form-control" id="maxStock" placeholder="最大库存" min="0"> <button class="btn btn-primary" type="button" id="stockStatusBtn"> </button> <button class="btn btn-sm btn-outline-secondary" id="resetFilters"> 重置筛选 </button> 查询结果 0 条记录 数据更新时间: --:--:-- 订单号 产品信息 产品数量 组件 板材 单件用量 订单用量 库存数量 操作 加载中... 正在加载数据,请稍候... 没有找到匹配的记录 请尝试调整您的搜索条件 板材详情 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/js/bootstrap.bundle.min.js"></script> <script src="../js/test.js"></script> </body> </html> 实现排序和分页功能

<template> <el-tabs @tab-click="handleTabChange"> <el-tab-pane label="总览"> <el-col :span="6"> <el-card class="stat-card danger"> 当前通话数 0 较昨日: 0 </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> 今日通话数 0 较昨日: 0 </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> 历史通话数 0 较昨日: 0 </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> 当前线路数 0 较昨日: 0 </el-card> </el-col> <el-table :data="summaryTable" border> <el-table-column prop="label" label="指标"></el-table-column> <el-table-column prop="value" label="数值"></el-table-column> </el-table> </el-tab-pane> <el-tab-pane label="省份统计"> <el-table :data="provinceTable" border> <el-table-column prop="province" label="省份"></el-table-column> <el-table-column prop="currentCall" label="当前通话数" ></el-table-column> <el-table-column prop="todayCall" label="今日通话数" ></el-table-column> <el-table-column prop="historyCall" label="历史通话数" ></el-table-column> <el-table-column prop="currentLine" label="当前线路数" ></el-table-column> <el-table-column prop="circuit" label="电路线路数" ></el-table-column> <el-table-column prop="network" label="网络线路数" ></el-table-column> <el-table-column prop="todayLine" label="今日线路数" ></el-table-column> <el-table-column prop="todayCircuit" label="今日电路线路数" ></el-table-column> <el-table-column prop="todayNetwork" label="今日网络线路数" ></el-table-column> <el-table-column prop="historyLine" label="历史线路数" ></el-table-column> <el-table-column prop="historyCircuit" label="历史电路线路数" ></el-table-column> <el-table-column prop="historyNetwork" label="历史网络线路数" ></el-table-column> </el-table> </el-tab-pane> <el-tab-pane label="趋势分析"> 通话数 | 线路数 <el-button size="mini">近7天</el-button> <el-button size="mini">近30天</el-button> </el-tab-pane> </el-tabs> </template> <script> import { userlist, getsuperes } from "@/utils/https.js"; export default { name: "HomeView", data() { return { summaryTable: [], provinceTable: [ { province: "江苏", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "上海", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "浙江", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "安徽", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, ], superEnterpriseList: [], // 新增的超级企业列表数据 }; }, mounted() { this.loadHomeData(); this.loadSuperEnterpriseList(); // 调用获取超级企业列表的方法 }, methods: { loadHomeData() { userlist() .then(data => { this.summaryTable = data.summary || []; this.provinceTable = data.provinces || this.provinceTable; }) .catch(error => { console.error("加载首页数据失败:", error); this.$message.error("加载数据失败"); }); }, loadSuperEnterpriseList() { getsuperes() .then(response => { this.superEnterpriseList = response.data || []; console.log('超级企业列表:', this.superEnterpriseList); }) .catch(error => { console.error('获取超级企业列表失败:', error); this.$message.error('获取超级企业列表失败'); }); }, handleTabChange(tab) { console.log("切换到:", tab.name); }, handleSizeChange(val) { this.pageSize = val; }, handleCurrentChange(val) { this.currentPage = val; }, }, }; </script> <style scoped> :root { --main-bg-color: #f5f7fa; --tab-bg-color: #ffffff; --stat-border-color: #f56c6c; } .home-container { padding: 20px; background: var(--main-bg-color); min-height: calc(100vh - 64px); } .tab-wrapper { background: var(--tab-bg-color); border: 1px solid #ebeef5; border-radius: 4px; } .tab-content { padding: 20px; border-top: none; } .stats-row { margin-top: 10px; } .stat-card { height: 160px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .stat-card.danger { border-left: 4px solid var(--stat-border-color); } .stat-title { font-size: 16px; font-weight: 500; margin-bottom: 10px; } .stat-value { font-size: 24px; color: #303133; margin-bottom: 10px; } .stat-sub { font-size: 14px; color: #909399; } .table-card { padding: 20px; } .chart-placeholder { text-align: center; padding: 40px 0; } .mock-chart { position: relative; height: 300px; width: 100%; } .chart-line-container { position: absolute; bottom: 40px; left: 10%; width: 80%; height: 200px; border-bottom: 1px solid #e0e0e0; border-left: 1px solid #e0e0e0; } .chart-line通话 { position: absolute; bottom: 0; width: 100%; height: 30%; background: linear-gradient(to top, rgba(0, 128, 128, 0.2) 0%, teal 100%); clip-path: polygon( 0% 100%, 5% 80%, 10% 60%, 15% 70%, 20% 50%, 25% 60%, 30% 40%, 35% 50%, 40% 30%, 45% 40%, 50% 20%, 55% 30%, 60% 10%, 65% 20%, 70% 0%, 75% 10%, 80% 30%, 85% 20%, 90% 40%, 95% 30%, 100% 50%, 100% 100% ); } .chart-line线路 { position: absolute; bottom: 0; width: 100%; height: 60%; background: linear-gradient(to top, rgba(128, 0, 128, 0.2) 0%, purple 100%); clip-path: polygon( 0% 100%, 5% 90%, 10% 70%, 15% 80%, 20% 60%, 25% 70%, 30% 50%, 35% 60%, 40% 40%, 45% 50%, 50% 30%, 55% 40%, 60% 20%, 65% 30%, 70% 10%, 75% 20%, 80% 40%, 85% 30%, 90% 50%, 95% 40%, 100% 60%, 100% 100% ); } .chart-legend { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); } .chart-buttons { position: absolute; bottom: -20px; left: 50%; transform: translateX(-50%); } .server-select, .province-select { width: 160px; margin-bottom: 20px; } </style>纠错

------------------------ test.html ------------------------ <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>板材库存管理系统</title> </head> <body> 板材库存管理系统 查询订单、产品、板材及库存信息 高级搜索 <input type="text" class="form-control with-icon" id="orderSearch" placeholder="搜索订单号..." aria-label="订单号搜索"> <input type="text" class="form-control with-icon" id="productSearch" placeholder="搜索产品编号..." aria-label="产品编号搜索"> <input type="text" class="form-control with-icon" id="materialSearch" placeholder="搜索板材ID或材质..." aria-label="板材搜索"> <input type="text" class="form-control with-icon" id="woodSearch" placeholder="搜索木皮名称..." aria-label="木皮搜索"> <input type="number" class="form-control with-icon" id="thicknessSearch" placeholder="厚度(mm)" min="0" step="0.1"> <input type="number" class="form-control" id="minStock" placeholder="最小库存" min="0"> <input type="number" class="form-control" id="maxStock" placeholder="最大库存" min="0"> <button class="btn btn-primary" type="button" id="stockStatusBtn"> </button> <button class="btn btn-sm btn-outline-secondary" id="resetFilters"> 重置筛选 </button> 查询结果 0 条记录 数据更新时间: --:--:-- 订单号 产品信息 产品数量 组件 板材 单件用量 订单用量 库存数量 操作 加载中... 正在加载数据,请稍候... 没有找到匹配的记录 请尝试调整您的搜索条件 板材详情 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/js/bootstrap.bundle.min.js"></script> <script src="../js/dingdan.js"></script> </body> </html> ------------------------ DataManager.js ------------------------ //这个函数不许改,也禁止废话,属性名和其他命名都哼规范不会出现意外, function resolveDataReferences(data) { console.log(data) // 获取 data 对象的所有顶层键 const keys = Object.keys(data); // 遍历每个顶层键(如 users, posts 等) for (const key of keys) { const entities = data[key]; // 遍历该顶层键下的每个实体(如每个 user 或 post) for (const entity of entities) { // 遍历实体的每个属性 for (const attribute in entity) { if (entity?.hasOwnProperty(attribute)) { var trpe=attribute?.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem.id === item.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem.id === entity[attribute].id); } } } } } return data; } /** * 数据管理器类,负责与后端API通信并管理数据 */ class DataManager { constructor(baseUrl) { this.baseUrl = baseUrl; this.data = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_bancais:[], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [] }; this.isSyncing = false; this.lastSync = null; this.callbacks = { all: [], bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], chanpin_zujian: [], dingdan_bancai:[], zujian: [], caizhi: [], dingdan_chanpin: [], user: [], jinhuo: [] }; this.syncQueue = Promise.resolve(); this.registerCallback('dingdan_bancai', async (operation, data) => { if (operation === 'add' || operation === 'update') { try { // 构造进货记录数据 const jinhuoData = { dingdan_bancai:data, shuliang: data.shuliang, date: new Date().toISOString(), user: { id: localStorage.getItem("userId") } }; // 创建进货记录 await this.addEntity('jinhuo', jinhuoData); } catch (error) { console.error('进货记录创建失败:', error); } } }); } /** * 获取所有数据 * @returns {Promise<boolean>} 是否成功 */ async fetchAll() { console.log(this) try { const response = await fetch(${this.baseUrl}/app/all); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); console.log(result.data) const resolvedData = resolveDataReferences(result.data); // 更新本地数据 Object.keys(this.data).forEach(key => { if (resolvedData[key]) { this.data[key] = resolvedData[key]; } }); this.lastSync = new Date(); // 关键改进:数据更新后触发刷新回调 this.triggerCallbacks('refresh', 'all', this.data); return true; } catch (error) { console.error('Fetch error:', error); // 触发错误回调 this.triggerCallbacks('fetch_error', 'all', { error }); return false; } } /** * 注册回调函数 * @param {string} entity - 实体类型(如'bancai')或'all'表示全局回调 * @param {Function} callback - 回调函数,参数为(operation, data) */ registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } /** * 移除回调函数 * @param {string} entity - 实体类型单数性质 * @param {Function} callback - 要移除的回调函数 */ unregisterCallback(entity, callback) { if (!this.callbacks[entity]) return; const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); } } /** * 触发回调 * @param {string} operation - 操作类型('add', 'update', 'delete') * @param {string} entity - 实体类型单数性质 * @param {Object} data - 相关数据 */ triggerCallbacks(operation, entity, data) { // 触发全局回调 this.callbacks.all.forEach(cb => cb(operation, entity, data)); // 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); } } // /** // * 执行CRUD操作并触发回调 // */ // async crudOperation(operation, entity, data) { // try { // const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, { // method: 'POST', // headers: {'Content-Type': 'application/json'}, // body: JSON.stringify(data) // }); // // if (!response.ok) throw new Error('Network response was not ok'); // // const result = await response.json(); // if (result.status !== 200) throw new Error(result.text || 'API error'); // // // // // 自动同步数据 // this.syncData(); // // 触发操作成功的回调 // this.triggerCallbacks(operation, entity, data); // return result; // } catch (error) { // console.error('CRUD error:', error); // // 触发操作失败的回调 // this.triggerCallbacks(${operation}_error, entity, { // data, // error: error.message // }); // throw error; // } // } /** * 执行CRUD操作 * @param {string} operation - 'add', 'delete', 'update' * @param {string} entity - 实体名称单数性质(小写) * @param {Object} data - 要发送的数据 后端要求数据格式为{属性: "值", 关联对象: {id:0}, 关联对象集: [{id:0}]} * @returns {Promise<Object>} 响应结果 */ async crudOperation(operation, entity, data) { try { const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); console.log(data)//这了就没有id了 // 自动同步数据 this.syncQueue = this.syncQueue.then(async () => { await this.syncData(); // 同步完成后触发操作回调 this.triggerCallbacks(operation, entity, result.data); }); return result; } catch (error) { console.error('CRUD error:', error); // 触发操作失败的回调 this.triggerCallbacks(${operation}_error, entity, { data, error: error.message }); throw error; } } /** * 自动同步数据(防止频繁请求) */ async syncData() { if (this.isSyncing) { this.pendingSync = true; return; } this.isSyncing = true; try { await this.fetchAll(); } catch (error) { console.error('Sync failed:', error); } finally { this.isSyncing = false; // 处理等待中的同步请求 if (this.pendingSync) { this.pendingSync = false; setTimeout(() => this.syncData(), 1000); } } } /** * 添加实体 * @param {string} entity - 实体名称单数性质 * @param {Object} data - 实体数据 */ async addEntity(entity, data) { return this.crudOperation('add', entity, data); } /** * 更新实体 * @param {string} entity - 实体名称单数性质 * @param {Object} data - 实体数据(必须包含id) */ async updateEntity(entity, data) { return this.crudOperation('update', entity, data); } /** * 删除实体 * @param {string} entity - 实体名称单数性质 * @param {number} id - 实体ID */ async deleteEntity(entity, id) { return this.crudOperation('delete', entity, {id}); } /** * 新增方法:手动触发数据刷新 */ async refreshData() { return this.syncQueue = this.syncQueue.then(() => this.syncData()); } /** * 获取订单的可用板材信息 * @param {number} dingdanId - 订单ID * @returns {Object} 可用板材信息 */ getAvailableBancaisForOrder(dingdanId) { const dingdan = this.data.dingdans.find(d => d.id == dingdanId); if (!dingdan) return {}; return dingdan.availableBancais || {}; } /** * 获取产品的组件列表 * @param {number} chanpinId - 产品ID * @returns {Array} 组件列表 */ getZujiansForChanpin(chanpinId) { const chanpin = this.data.chanpins.find(c => c.id == chanpinId); if (!chanpin) return []; return (chanpin.chanpin_zujian_list || []) .map(cz => cz.zujian) .filter(z => z); } /** * 获取组件的板材信息 * @param {number} zujianId - 组件ID * @returns {Array} 板材列表 */ getBancaisForZujian(zujianId) { return (this.data.chanpin_zujians || []) .filter(cz => cz.zujian && cz.zujian.id == zujianId) .map(cz => cz.bancai) .filter(b => b); } /** * 创建进货记录 * @param {Object} jinhuoData - 进货数据 * @returns {Promise} 操作结果 */ async createJinhuo(jinhuoData) { return this.addEntity('jinhuo', jinhuoData); } /** * 获取订单列表 * @returns {Array} 订单列表 */ getDingdans() { return this.data.dingdans || []; } /** * 获取订单的产品列表 * @param {number} dingdanId - 订单ID * @returns {Array} 产品列表 */ getChanpinsForDingdan(dingdanId) { const dingdan = this.data.dingdans.find(d => d.id == dingdanId); if (!dingdan) return []; return (dingdan.dingdan_chanpin_list || []) .map(dc => dc.chanpin) .filter(c => c); } } export { DataManager }; // 创建单例实例 //const dataManager = new DataManager('http://127.0.0.1:8080/KuCun2'); //// 初始化时获取所有数据 //dataManager.fetchAll().then(() => { // console.log('Initial data loaded'); //}); // 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等 //export const data = dataManager.data; //// 导出操作方法 //export const addEntity = dataManager.addEntity.bind(dataManager); //export const updateEntity = dataManager.updateEntity.bind(dataManager); //export const deleteEntity = dataManager.deleteEntity.bind(dataManager); //export const fetchAll = dataManager.fetchAll.bind(dataManager); ------------------------ test.js ------------------------ // 创建DataManager实例 // 获取全局的DataManager实例 const dataManager = window.parent.dataManager; // 扁平化数据结构 function flattenData(data) { const result = []; // 遍历所有订单 data.dingdans.forEach(dingdan => { // 遍历订单中的产品 dingdan.dingdan_chanpin?.forEach(dc => { const chanpin = dc.chanpin; // 遍历产品中的组件 chanpin.chanpin_zujian.forEach(cz => { const zujian = cz.zujian; const bancai = cz.bancai; const kucun = bancai.kucun; // 计算订单用量 = 产品数量 × 组件数量 × 单件用量 const orderUsage = dc.shuliang * cz.zujianshu * cz.one_howmany; // 创建扁平化数据对象 result.push({ dingdan: dingdan, dingdan_chanpin: dc, chanpin: chanpin, chanpin_zujian: cz, zujian: zujian, bancai: bancai, kucun: kucun, orderUsage: orderUsage }); }); }); }); return result; } // 更新统计卡片 function updateStatistics(data) { // 订单总数 $('#orderCount').text(data.dingdans.length); // 产品种类 $('#productCount').text(data.chanpins.length); // 板材种类 $('#materialCount').text(data.bancais.length); // 库存总量 const totalStock = data.kucuns.reduce((sum, kucun) => sum + kucun.shuliang, 0); $('#totalStock').text(totalStock); } // 渲染表格 function renderTable(dataArray) { const $tbody = $('#resultBody'); $tbody.empty(); if (dataArray.length === 0) { $('#noResults').show(); $('#resultCount').text('0'); return; } $('#noResults').hide(); $('#resultCount').text(dataArray.length); dataArray.forEach(item => { const bancai = item.bancai; const dingdan = item.dingdan; const chanpin = item.chanpin; const zujian = item.zujian; const kucun = item.kucun; const row = ${dingdan.number} ${chanpin.bianhao} ${item.dingdan_chanpin.shuliang} ${zujian.name} ID: ${bancai.id} 材质: ${bancai.caizhi.name} 厚度: ${bancai.houdu}mm 木皮1: ${bancai.mupi1.name}${bancai.mupi1.you ? '(油漆)' : ''} 木皮2: ${bancai.mupi2.name}${bancai.mupi2.you ? '(油漆)' : ''} ${item.chanpin_zujian.one_howmany} ${item.orderUsage.toFixed(2)} ${kucun.shuliang} <button class="btn btn-sm btn-outline-primary view-detail" data-bancai-id="${bancai.id}"> 详情 </button> ; $tbody.append(row); }); // 绑定详情按钮事件 $('.view-detail').off('click').on('click', function() { const bancaiId = $(this).data('bancai-id'); viewBancaiDetail(bancaiId); }); } // 查看板材详情 function viewBancaiDetail(bancaiId) { const bancai = dataManager.data.bancais.find(b => b.id === bancaiId); if (!bancai) return; const kucun = bancai.kucun; const reservedOrder = kucun.reservedOrder ? kucun.reservedOrder.number : '无'; // 构建详情内容 const detailContent = 板材详情 #${bancai.id} 材质: ${bancai.caizhi.name} 厚度: ${bancai.houdu}mm 木皮1: ${bancai.mupi1.name}${bancai.mupi1.you ? ' (油漆)' : ''} 木皮2: ${bancai.mupi2.name}${bancai.mupi2.you ? ' (油漆)' : ''} 当前库存: ${kucun.shuliang} 预定订单: ${reservedOrder} 库存状态: ${kucun.shuliang > 50 ? '充足' : kucun.shuliang > 10 ? '正常' : '不足'} 使用此板材的产品组件 ${dataManager.data.chanpin_zujians .filter(cz => cz.bancai.id === bancaiId) .map(cz => ${cz.zujian.name} (产品: ${cz.chanpin.bianhao})) .join('')} ; // 使用模态框显示详情 const modal = new bootstrap.Modal(document.getElementById('detailModal')); $('#detailModal .modal-body').html(detailContent); modal.show(); } // 搜索和过滤数据 function filterData(flatData) { const orderSearch = $('#orderSearch').val().toLowerCase(); const productSearch = $('#productSearch').val().toLowerCase(); const materialSearch = $('#materialSearch').val().toLowerCase(); const woodSearch = $('#woodSearch').val().toLowerCase(); const thickness = parseFloat($('#thicknessSearch').val()); const minStock = parseInt($('#minStock').val()) || 0; const maxStock = parseInt($('#maxStock').val()) || Infinity; return flatData.filter(item => { const bancai = item.bancai; const dingdan = item.dingdan; const chanpin = item.chanpin; const kucun = item.kucun; // 订单号搜索 if (orderSearch && !dingdan.number.toLowerCase().includes(orderSearch)) { return false; } // 产品编号搜索 if (productSearch && !chanpin.bianhao.toLowerCase().includes(productSearch)) { return false; } // 板材ID或材质搜索 if (materialSearch && !(bancai.id.toString().includes(materialSearch) || bancai.caizhi.name.toLowerCase().includes(materialSearch))) { return false; } // 木皮搜索 if (woodSearch && !(bancai.mupi1.name.toLowerCase().includes(woodSearch) || bancai.mupi2.name.toLowerCase().includes(woodSearch))) { return false; } // 厚度过滤 if (!isNaN(thickness) && Math.abs(bancai.houdu - thickness) > 0.1) { return false; } // 库存范围过滤 if (kucun.shuliang < minStock || kucun.shuliang > maxStock) { return false; } return true; }); } // 初始化排序功能 function initSorting() { let currentSort = { column: null, direction: 'asc' }; $('th[data-sortable]').on('click', function() { const column = $(this).index(); const $sortIndicator = $(this).find('.sort-indicator'); // 重置其他列的排序指示器 $('.sort-indicator').html(''); // 更新当前排序状态 if (currentSort.column === column) { currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc'; } else { currentSort.column = column; currentSort.direction = 'asc'; } // 更新排序指示器 $sortIndicator.html(currentSort.direction === 'asc' ? '↑' : '↓'); // 执行排序 sortTable(currentSort); }); } // 排序表格数据 function sortTable(sortConfig) { const flatData = window.currentFlatData || []; if (flatData.length === 0) return; flatData.sort((a, b) => { let valueA, valueB; switch (sortConfig.column) { case 0: // 订单号 valueA = a.dingdan.number; valueB = b.dingdan.number; break; case 1: // 产品信息 valueA = a.chanpin.bianhao; valueB = b.chanpin.bianhao; break; case 2: // 产品数量 valueA = a.dingdan_chanpin.shuliang; valueB = b.dingdan_chanpin.shuliang; break; case 3: // 组件 valueA = a.zujian.name; valueB = b.zujian.name; break; case 4: // 板材 valueA = a.bancai.id; valueB = b.bancai.id; break; case 5: // 单件用量 valueA = a.chanpin_zujian.one_howmany; valueB = b.chanpin_zujian.one_howmany; break; case 6: // 订单用量 valueA = a.orderUsage; valueB = b.orderUsage; break; case 7: // 库存数量 valueA = a.kucun.shuliang; valueB = b.kucun.shuliang; break; default: return 0; } // 数字排序 if (typeof valueA === 'number') { return sortConfig.direction === 'asc' ? valueA - valueB : valueB - valueA; } // 字符串排序 if (typeof valueA === 'string') { return sortConfig.direction === 'asc' ? valueA.localeCompare(valueB) : valueB.localeCompare(valueA); } return 0; }); // 重新渲染排序后的表格 renderTable(flatData); } // 初始化页面 $(document).ready(async function() { // 创建详情模态框(如果不存在) if (!$('#detailModal').length) { $('body').append( 板材详情 <button type="button" class="btn-close" data-bs-dismiss="modal"></button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button> ); } // 显示加载状态 $('#loadingRow').show(); $('#noResults').hide(); try { // 加载数据 await dataManager.fetchAll(); // 更新最后更新时间 $('#lastUpdate').text(new Date().toLocaleTimeString()); // 扁平化数据 const flatData = flattenData(dataManager.data); window.currentFlatData = flatData; // 保存当前数据用于排序 // 更新统计卡片 updateStatistics(dataManager.data); // 渲染表格 renderTable(flatData); // 初始化排序 initSorting(); } catch (error) { console.error('初始化失败:', error); $('#resultBody').html( 数据加载失败 ${error.message || '请检查网络连接后重试'} <button class="btn btn-primary mt-2" id="retryBtn">重试</button> ); $('#retryBtn').on('click', function() { location.reload(); }); } finally { $('#loadingRow').hide(); } // 绑定搜索事件 $('#orderSearch, #productSearch, #materialSearch, #woodSearch, #thicknessSearch, #minStock, #maxStock').on('input', function() { performSearch(); }); $('#stockStatusBtn').on('click', performSearch); }); // 执行搜索 function performSearch() { if (!window.currentFlatData) return; const filteredData = filterData(window.currentFlatData); renderTable(filteredData); } 修改test.js实现页面功能 基本逻辑 一个订单有很多产品不同数量,每个产品可以再很多订单中,一个产品有很多组件,一个组件可以在很多产品中,因为每个组件因为在不同的产品中有不同的生产工艺,所以使用不同的板材和板材能生产组件数量,每个板材有不同的材质和两面木皮,木皮表面可能有油漆, 订购时可能直接购入板材,也可能按订单和产品订购板材,也用可能按订单产品组件订购板材,每次采购不标准,一个订单可能订购几次,用户有姓名 账号 密码 权限, 一个记录进货和消耗,查看的时候会查看订单下有多少板材可用

<template> 客户特征标签 <el-popover placement="right" popper-class="group-popover" width="287" trigger="click"> 业务需求 <el-popover v-for="(item, index) in requireList" :key="index" placement="top-start" popper-class="grid-popover" trigger="hover" :content="item.labelName" v-if="shouldShowPopover(item)" > <el-tag slot="reference" size="mini" class="truncate-tag" >{{ item.labelName }}</el-tag> </el-popover> <el-tag v-for="(item, index) in requireList" v-if="!shouldShowPopover(item)" :key="index" size="mini" >{{ item.labelName }}</el-tag> 业务特征 <el-popover v-for="(item, index) in featureList" :key="index" placement="top-start" popper-class="grid-popover" trigger="hover" :content="item.labelName" v-if="shouldShowPopover(item)" > <el-tag slot="reference" type="" size="mini" class="truncate-tag" >{{ item.labelName }}</el-tag> </el-popover> <el-tag v-for="(item, index) in featureList" v-if="!shouldShowPopover(item)" :key="index" type="success" size="mini" >{{ item.labelName }}</el-tag> 拓展任务 <el-popover v-for="(item, index) in taskList" :key="index" placement="top-start" popper-class="grid-popover" trigger="hover" :content="item.labelName" v-if="shouldShowPopover(item)" > <el-tag slot="reference" type="danger" size="mini" class="truncate-tag" >{{ item.labelName }}</el-tag> </el-popover> <el-tag v-for="(item, index) in taskList" v-if="!shouldShowPopover(item)" :key="index" type="danger" size="mini" >{{ item.labelName }}</el-tag> <el-button slot="reference" class="btn">更多</el-button> </el-popover> 业务需求 <el-popover v-for="(item, index) in showRequireList" :key="index" placement="top-start" popper-class="grid-popover" trigger="hover" :content="item.labelName" v-if="shouldShowPopover(item)" > <el-tag slot="reference" size="mini" class="truncate-tag" >{{ item.labelName }}</el-tag> </el-popover> <el-tag v-for="(item, index) in showRequireList" v-if="!shouldShowPopover(item)" :key="index" size="mini" >{{ item.labelName }}</el-tag> 业务特征 <el-popover v-for="(item, index) in showFeatureList" :key="index" placement="top-start" popper-class="grid-popover" trigger="hover" :content="item.labelName" v-if="shouldShowPopover(item)" > <el-tag slot="reference" type="success" size="mini" class="truncate-tag" >{{ item.labelName }}</el-tag> </el-popover> <el-tag v-for="(item, index) in showFeatureList" v-if="!shouldShowPopover(item)" :key="index" type="success" size="mini" >{{ item.labelName }}</el-tag> 拓展任务 <el-popover v-for="(item, index) in showTaskList" :key="index" placement="top-start" popper-class="grid-popover" trigger="hover" :content="item.labelName" v-if="shouldShowPopover(item)" > <el-tag slot="reference" type="danger" size="mini" class="truncate-tag" >{{ item.labelName }}</el-tag> </el-popover> <el-tag v-for="(item, index) in showTaskList" v-if="!shouldShowPopover(item)" :key="index" type="danger" size="mini" >{{ item.labelName }}</el-tag> </template> <script> import { Tag, Button, Popover,Tooltip } from 'element-ui'; export default { name: 'groupLabelBox', components: { [Tag.name]: Tag, [Button.name]: Button, [Popover.name]: Popover, [Tooltip.name]: Tooltip, }, props: { requireList: { type: Array, required: true, }, featureList: { type: Array, required: true, }, taskList: { type: Array, required: true, }, }, data() { return { dialogVisible: false, }; }, computed: { showRequireList() { return this.requireList.slice(0, 2); }, showFeatureList() { return this.featureList.slice(0, 2); }, showTaskList() { return this.taskList.slice(0, 2); }, }, methods: { shouldShowPopover(item) { return item?.labelName?.length >= 7 }, }, }; </script> <style lang="less" scoped> .group-popover { padding: 30px !important; /* 标题样式 */ .full-label-section{ padding-bottom: 12px; > span { display: block; margin-bottom: 10px; width: 56px; height: 14px; font-family: PingFangSC, PingFang SC, sans-serif; font-weight: 400; font-size: 14px; color: #888888; line-height: 14px; text-align: left; font-style: normal; } } /* 标签组样式 */ .full-tag-group { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 6px; .el-tag { margin: 0 !important; border-radius: 4px; font-size: 12px; padding: 0 8px; height: 24px; line-height: 24px; } } .full-label-sections { padding-bottom: 0 !important; } } .truncate-tag { display: inline-block; max-width: 112px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; cursor: default; } .truncate-tag:hover:after { position: absolute; top: 30px; left: 10px; content: attr(data-title); color: #333333; } .grid-popover { min-width: 54px; text-align: center; padding: 10px 10px; } .label-container { position: relative; padding: 0px 14px 7px 16px; } .header { display: flex; justify-content: space-between; align-items: center; margin: 10px 0px; .biaoqian { width: 84px; height: 14px; font-family: PingFangSC, PingFang SC, sans-serif; font-weight: 400; font-size: 14px; color: #888888; line-height: 14px; text-align: left; font-style: normal; } .btn { width: 33px; height: 17px; padding: 0 4px; background: #ffffff; border-radius: 2px; border: 1px solid #cbcbcb; font-weight: 400; font-size: 12px; color: #333333; line-height: 17px; font-style: normal; > span { display: block; width: fit-content; } } } .label-section { > span { display: block; margin-bottom: 5px; width: 48px; height: 14px; font-family: PingFangSC, PingFang SC, sans-serif; font-weight: 400; font-size: 12px; color: #333333; line-height: 14px; text-align: left; font-style: normal; } } .tag-group { display: flex; gap: 10px; flex-wrap: wrap; } .label-section:not(:last-child) { margin-bottom: 10px; } </style> 优化这段代码

前端vue2+elementui帮我生成一个前端页面,一下需求1.2.3.4.5.6部分已经完成完成的代码在下边,仔细分析现有代码,优化一下第三部分的部件和接口选项的宽度问题,完善7.8部分的需求,尤其是接口选项多选和主体中间部分的跨容器拖拽功能实现 1.竖向分为头部和主体部分,头部宽度100%,高度60px,头部左侧两个input框,lable分别为:用例名称,脚本编号,右侧3个按钮是生成用例,生成脚本,调试 2.主体部分占据剩下高度,分为左,中,右三部分,宽度占比分别为40%,40%,20%, 3.主体左侧为左右两部分,分别为部件和接口选项,两个均为可以手动打开关闭的抽屉(使用elementui中的el-drawer),重要一点:我需要的是将部件用el-drawer包裹和接口选项整体用el-drawer包裹,有一个箭头的按钮在整体的右侧部分控制el-drawer的开关,部件宽度为35%,接口选项宽度65%,两个抽屉没有层级关系,独立开启关闭,不会相互影响,无论开启或关闭组件在左,接口选项在右 4.部件部分:竖向一个搜索框,输入关键字可对下面具体组件进行筛选,搜索框下是组件名称和图标,组件名称分别为:车门,车窗,座椅,前舱盖,雨刮器,光机幕布,后视镜这部分可使用 列表渲染,每个组件展示为一行,左侧组件图标,右侧组件名称,,一行一列,依次向下 5.接口选项部分,竖向一个搜索框,输入关键字可对下面具体接口进行筛选,接口选项和左侧部件是有联动的,两者存在跨容器拖拽关系,拖动左侧部件中的一个(每次只能拖动一个),到右侧接口选项区域,会触发事件,调取后端接口获取对应组件的接口列表(这里可以使用模拟数据),展示在接口选项部分, 接口内容为:打开所有车窗。open_all_wins,控制车辆上电。power_on_off_control...,(可以放点模拟数据) 6.拖动组件到接口选项部分,每一个组件对应的接口展示都是一个独立的二级树形结构,树形结构一级lable为组件名称,右侧有一个可以X,可以删除当前组件,树形结构二级内容就为每个具体的接口,每个接口头部都有一个多选按钮,可以展示多个,依次竖向向下展示 7.主体中间部分竖向依次为3部分,预置条件,测试步骤,环境恢复,宽度均占据主体中间部分宽度100%,高度分别为30%,40%,20%,左侧接口选项部分通过多选框勾选接口,勾选的接口组成一个list,通过拖拽将接口选项中的接口拖拽到右侧主体中间部分展示,支多选批量拖拽 每个区域可视为独立区域,相互不影响,若一个区域拖入多个接口,根据先后依次排序 ,拖拽至中间主体部分的接口,在各自独立区域内,接口排序可以通过上下拖拽调换, 8.主体右侧为参数配置:由上至下第一行两个单选按钮,Machine,Relay,剩下为3个输入框,各占一行,lable分别为:机械控制踏板踩下去和抬起来之间的时间间隔(秒),踏板踩下去和抬起来的时间间隔(秒),踏板踩下去或抬起来需要继电器打开的时间(秒) <template> <el-input placeholder="请输入用例名称" class="header-input" v-model="caseName" > <template slot="prepend">用例名称</template> </el-input> <el-input placeholder="请输入脚本编号" class="header-input" v-model="scriptId" > <template slot="prepend">脚本编号</template> </el-input> <el-button type="primary" class="header-button">生成用例</el-button> <el-button type="success" class="header-button">生成脚本</el-button> <el-button type="warning" class="header-button">调试</el-button> 车辆部件列表 <el-input placeholder="搜索部件..." v-model="componentSearch" prefix-icon="el-icon-search" clearable ></el-input> {{ component.name }} 接口选项 <el-input placeholder="搜索接口..." v-model="interfaceSearch" prefix-icon="el-icon-search" clearable ></el-input> 请从左侧拖动部件到此处以加载接口 <transition-group name="fade"> {{ group.componentName }} 接口 <el-checkbox v-model="item.selected"></el-checkbox> {{ item.name }} {{ item.id }} </transition-group> 用例执行区域 此处将展示用例执行流程和结果 参数配置区域 此处将展示脚本参数配置选项 </template> <script> import axios from "axios"; import { } from "@/api/api.js"; import draggable from "vuedraggable"; import Papa from "papaparse"; import * as echarts from "echarts"; import { Message } from "element-ui"; export default { components: { draggable }, data() { return { caseName: '', scriptId: '', componentsDrawerOpen: true, interfacesDrawerOpen: true, componentSearch: '', interfaceSearch: '', draggedComponent: null, // 部件数据 components: [ { id: 1, name: '车门', icon: 'el-icon-s-help' }, { id: 2, name: '车窗', icon: 'el-icon-s-promotion' }, { id: 3, name: '座椅', icon: 'el-icon-s-opportunity' }, { id: 4, name: '前舱盖', icon: 'el-icon-s-flag' }, { id: 5, name: '雨刮器', icon: 'el-icon-s-release' }, { id: 6, name: '光机幕布', icon: 'el-icon-s-platform' }, { id: 7, name: '后视镜', icon: 'el-icon-s-claim' } ], // 接口分组数据 interfaceGroups: [], nextGroupId: 1, // 模拟接口数据 mockInterfaces: { 1: [ // 车门接口 { id: 'door_lock', name: '车门锁定', selected: false }, { id: 'door_unlock', name: '车门解锁', selected: false }, { id: 'door_open', name: '打开车门', selected: false }, { id: 'door_close', name: '关闭车门', selected: false } ], 2: [ // 车窗接口 { id: 'window_open_all', name: '打开所有车窗', selected: false }, { id: 'window_close_all', name: '关闭所有车窗', selected: false }, { id: 'window_open_driver', name: '打开驾驶员车窗', selected: false }, { id: 'window_open_passenger', name: '打开乘客车窗', selected: false } ], 3: [ // 座椅接口 { id: 'seat_heat', name: '座椅加热', selected: false }, { id: 'seat_cool', name: '座椅通风', selected: false }, { id: 'seat_adjust', name: '座椅调节', selected: false }, { id: 'seat_massage', name: '座椅按摩', selected: false } ], 4: [ // 前舱盖接口 { id: 'hood_open', name: '打开前舱盖', selected: false }, { id: 'hood_close', name: '关闭前舱盖', selected: false } ], 5: [ // 雨刮器接口 { id: 'wiper_on', name: '开启雨刮器', selected: false }, { id: 'wiper_off', name: '关闭雨刮器', selected: false }, { id: 'wiper_speed', name: '调节雨刮速度', selected: false } ], 6: [ // 光机幕布接口 { id: 'screen_up', name: '升起幕布', selected: false }, { id: 'screen_down', name: '降下幕布', selected: false }, { id: 'screen_brightness', name: '调节亮度', selected: false } ], 7: [ // 后视镜接口 { id: 'mirror_adjust', name: '调节后视镜', selected: false }, { id: 'mirror_fold', name: '折叠后视镜', selected: false }, { id: 'mirror_heat', name: '后视镜加热', selected: false } ] } }; }, mounted() { }, computed: { // 过滤后的部件列表 filteredComponents() { if (!this.componentSearch) return this.components; return this.components.filter(comp => comp.name.toLowerCase().includes(this.componentSearch.toLowerCase()) ); }, // 过滤后的接口分组 filteredInterfaceGroups() { if (!this.interfaceSearch) return this.interfaceGroups; return this.interfaceGroups.map(group => { const filteredInterfaces = group.interfaces.filter(item => item.name.toLowerCase().includes(this.interfaceSearch.toLowerCase()) || item.id.toLowerCase().includes(this.interfaceSearch.toLowerCase()) ); // 只返回包含匹配接口的分组 if (filteredInterfaces.length > 0) { return { ...group, interfaces: filteredInterfaces }; } return null; }).filter(group => group !== null); } }, methods: { // 开始拖拽 dragStart(component) { this.draggedComponent = component; }, // 放置组件 dropComponent() { if (!this.draggedComponent) return; console.log( '11',JSON.stringify(this.draggedComponent.id)); // 检查是否已存在该组件的接口组 const exists = this.interfaceGroups.some(group => group.componentId === this.draggedComponent.id ); if (exists) { this.$message.warning(已加载过${this.draggedComponent.name}的接口); return; } // 模拟API请求获取接口数据 this.$message.success(正在加载${this.draggedComponent.name}接口...); // 模拟API延迟 setTimeout(() => { const interfaces = [...this.mockInterfaces[this.draggedComponent.id]]; this.interfaceGroups.push({ id: this.nextGroupId++, componentId: this.draggedComponent.id, componentName: this.draggedComponent.name, interfaces: interfaces }); this.$message.success(成功加载${this.draggedComponent.name}接口); }, 500); //this.draggedComponent = null; }, // 删除接口组 removeGroup(groupId) { this.interfaceGroups = this.interfaceGroups.filter(group => group.id !== groupId); this.$message.success('接口组已移除'); } }, watch: { }, beforeDestroy() { }, async created() { }, }; </script> <style scoped lang="less"> * { margin: 0; padding: 0; box-sizing: border-box; } html, body { height: 100%; font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Microsoft YaHei', sans-serif; background-color: #f5f7fa; overflow: hidden; } #app { height: 100%; display: flex; flex-direction: column; } /* 头部样式 */ .header { height: 60px; background: linear-gradient(135deg, #1e3c72, #2a5298); box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); display: flex; align-items: center; padding: 0 20px; color: white; z-index: 1000; } .header-left { display: flex; align-items: center; flex: 1; } .header-input { width: 280px; margin-right: 20px; background-color: rgba(255, 255, 255, 0.15); border-radius: 4px; border: none; } .header-input .el-input__inner { background-color: transparent; color: white; border: none; } .header-input .el-input__inner::placeholder { color: rgba(255, 255, 255, 0.6); } .header-right { display: flex; } .header-button { margin-left: 15px; background: linear-gradient(to right, #4facfe, #00f2fe); border: none; color: white; font-weight: bold; transition: all 0.3s; } .header-button:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } /* 主体样式 */ .main-container { flex: 1; display: flex; overflow: hidden; background-color: #f0f2f5; } /* 左侧区域 */ .left-section { flex: 0 0 40%; display: flex; position: relative; background-color: #fff; box-shadow: 2px 0 8px rgba(0, 0, 0, 0.05); z-index: 1; } /* 中间区域 */ .center-section { flex: 0 0 40%; background-color: #fff; margin: 10px; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); display: flex; flex-direction: column; align-items: center; justify-content: center; color: #909399; font-size: 18px; position: relative; overflow: hidden; } .center-placeholder { text-align: center; } .center-placeholder i { font-size: 48px; margin-bottom: 20px; color: #c0c4cc; } /* 右侧区域 */ .right-section { flex: 0 0 20%; background-color: #fff; margin: 10px 10px 10px 0; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); display: flex; flex-direction: column; align-items: center; justify-content: center; color: #909399; font-size: 18px; } .right-placeholder { text-align: center; } .right-placeholder i { font-size: 48px; margin-bottom: 20px; color: #c0c4cc; } /* 抽屉样式 */ .drawer-container { height: 100%; display: flex; position: relative; } .drawer-wrapper { height: 100%; overflow: hidden; transition: all 0.3s; } .components-drawer { width: 280px; height: 100%; border-right: 1px solid #ebeef5; background-color: #fff; box-shadow: 2px 0 8px rgba(0, 0, 0, 0.05); } .interfaces-drawer { width: 500px; height: 100%; background-color: #fff; border-right: 1px solid #ebeef5; } .drawer-toggle { position: absolute; top: 50%; transform: translateY(-50%); right: -15px; width: 30px; height: 60px; background-color: #1e3c72; color: white; display: flex; align-items: center; justify-content: center; border-radius: 0 15px 15px 0; cursor: pointer; z-index: 10; box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1); transition: all 0.3s; } .drawer-toggle:hover { background-color: #2a5298; } .drawer-toggle i { transition: transform 0.3s; } .drawer-toggle.collapsed i { transform: rotate(180deg); } /* 部件区域样式 */ .components-container { height: 100%; display: flex; flex-direction: column; padding: 15px; } .components-header { margin-bottom: 15px; font-weight: bold; color: #1e3c72; border-bottom: 1px solid #ebeef5; padding-bottom: 10px; font-size: 16px; } .component-item { display: flex; align-items: center; padding: 12px 15px; margin-bottom: 8px; border-radius: 4px; cursor: move; transition: all 0.2s; border: 1px solid #ebeef5; background-color: #f9fafc; } .component-item:hover { background-color: #ecf5ff; border-color: #c6e2ff; transform: translateX(5px); } .component-item .icon { width: 24px; height: 24px; margin-right: 10px; background-color: #1e3c72; border-radius: 4px; display: flex; align-items: center; justify-content: center; color: white; font-size: 14px; } .component-item .name { font-size: 14px; color: #606266; } /* 接口选项区域 */ .interfaces-container { height: 100%; display: flex; flex-direction: column; padding: 15px; } .interfaces-header { margin-bottom: 15px; font-weight: bold; color: #1e3c72; border-bottom: 1px solid #ebeef5; padding-bottom: 10px; font-size: 16px; } .tree-container { flex: 1; overflow-y: auto; padding: 10px; border: 1px solid #ebeef5; border-radius: 4px; background-color: #f9fafc; } .tree-node { margin-bottom: 10px; border-radius: 4px; overflow: hidden; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); } .tree-header { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; background: linear-gradient(to right, #4facfe, #00f2fe); color: white; font-weight: bold; } .delete-btn { cursor: pointer; transition: all 0.2s; } .delete-btn:hover { transform: scale(1.2); } .tree-content { padding: 10px; background-color: white; } .interface-item { display: flex; align-items: center; padding: 8px 10px; border-bottom: 1px dashed #ebeef5; } .interface-item:last-child { border-bottom: none; } .interface-name { margin-left: 8px; font-size: 14px; color: #606266; } .interface-id { margin-left: 8px; font-size: 12px; color: #909399; font-family: monospace; } /* 拖拽区域 */ .drop-area { height: 100%; display: flex; align-items: center; justify-content: center; color: #909399; font-size: 16px; flex-direction: column; } .drop-area i { font-size: 48px; margin-bottom: 15px; color: #c0c4cc; } .drop-hint { text-align: center; max-width: 300px; } /* 动画效果 */ .fade-enter-active, .fade-leave-active { transition: opacity 0.5s; } .fade-enter, .fade-leave-to { opacity: 0; } </style>

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>首页</title> </head> <body> 首页 热门景点 特产美食 特产 美食 民俗文化 西河大鼓 吴桥杂技 河北梆子> 用户调研 石家庄 唐山 张家口 保定 秦皇岛 ——河北宣传片—— 这片土地既丰富又神秘
没有人知道
还有多少未知的物种等待去发现
而即便是那些已经被广泛知晓的物种
以我们目前的认知
也仅仅只掌握了密码的一小部分
每种生命都是复杂而珍贵的
尊重和爱护它们的密码
也是在保护我们自身的未来
人们未来美好生活的蓝图
建立在生物多样性的繁盛之上
这张蓝图宏伟且谦卑
它既承载着中国智慧
也承载着世界生态文明的未来
视频来源:河北文旅
电话:1234567890
邮箱:[email protected]
©河北文旅
<script src="js/js.js"></script> </body> </html>每行代码都是什么意思,每行代码全部打出来

<template> <el-dialog title="设备导入" :visible.sync="dialogVisible" width="600px" custom-class="ota-dialog" :close-on-click-modal="false" > <el-upload action="#" :auto-upload="false" :before-upload="beforeUpload" :on-change="handleFileChange" :limit="1" :on-exceed="handleExceed" :file-list="fileList" drag > 点击或拖拽文件到此处上传 支持.xlsx、.xls格式文件 </el-upload> {{ fileList[0].name }} {{ formatFileSize(fileList[0].size) }} <el-tooltip effect="dark" :content="firstRowString" placement="top"> 首行数据: {{ truncateString(firstRowString) }} </el-tooltip> <el-button v-else type="danger" icon="el-icon-delete" circle @click="clearFile" ></el-button> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="handleConfirm" :disabled="!fileList.length || loading" > {{ loading ? '处理中...' : '确 定' }} </el-button> </el-dialog> </template> <script> import * as XLSX from 'xlsx'; export default { data() { return { dialogVisible: false, fileList: [], firstRowString: '', loading: false }; }, methods: { init() { this.dialogVisible = true; this.fileList = []; this.firstRowString = ''; }, beforeUpload(file) { const isValidType = [ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel' ].includes(file.type); if (!isValidType) { this.$message.error('请上传Excel格式的文件 (.xlsx 或 .xls)'); } return isValidType; }, // 处理文件选择变化 handleFileChange(file) { if (!file) return; const validTypes = [ 'application/vnd.ms-excel', // .xls 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' // .xlsx ]; if (!validTypes.includes(file.raw.type)) { this.$message.error('请上传Excel格式的文件 (.xlsx 或 .xls)'); this.clearFile(); return; } this.fileList = [file]; this.readExcelFirstRow(file.raw); }, // 读取Excel文件第一行 readExcelFirstRow(file) { this.loading = true; const reader = new FileReader(); reader.onload = (e) => { try { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); // 获取第一个工作表 const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; // 获取第一行数据 const range = XLSX.utils.decode_range(worksheet['!ref']); const firstRow = []; // 遍历第一行的所有列 for (let col = range.s.c; col <= range.e.c; col++) { const cellAddress = XLSX.utils.encode_cell({ r: 0, c: col }); const cell = worksheet[cellAddress]; firstRow.push(cell ? cell.v : ''); } // 用分号拼接第一行数据 this.firstRowString = firstRow.join(';'); this.$message.success('Excel文件解析成功'); } catch (error) { console.error('Excel解析错误:', error); this.$message.error('Excel文件解析失败,请检查文件格式'); this.firstRowString = ''; } finally { this.loading = false; } }; reader.onerror = () => { this.$message.error('文件读取失败'); this.loading = false; }; reader.readAsArrayBuffer(file); }, // 处理确认操作 handleConfirm() { if (!this.firstRowString) { this.$message.warning('未解析到有效数据'); return; } this.$message.success(已获取首行数据: ${this.firstRowString}); // 这里可以添加将数据发送到服务器的逻辑 // this.otaBatchUpgradeConfirm(this.firstRowString); // 关闭对话框 this.dialogVisible = false; }, // 清空文件 clearFile() { this.fileList = []; this.firstRowString = ''; }, handleExceed() { this.$message.warning('每次只能上传一个文件'); }, formatFileSize(size) { if (size < 1024) return size + ' B'; if (size < 1024 * 1024) return (size / 1024).toFixed(1) + ' KB'; return (size / (1024 * 1024)).toFixed(1) + ' MB'; }, // 截断长字符串 truncateString(str, maxLength = 30) { if (str.length <= maxLength) return str; return str.substring(0, maxLength) + '...'; } } }; </script> <style scoped> .action-section { display: flex; flex-direction: column; gap: 20px; } .upload-section { position: relative; display: flex; justify-content: center; } .file-card { margin-top: 15px; padding: 15px; border-radius: 8px; background-color: #f5f7fa; display: flex; align-items: center; justify-content: space-between; border: 1px solid #ebeef5; } .file-info { display: flex; align-items: center; gap: 12px; flex: 1; } .file-info i { font-size: 28px; color: #409EFF; } .file-details { line-height: 1.5; flex: 1; } .file-name { font-weight: 500; max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-size { font-size: 12px; color: #909399; } .file-data { font-size: 12px; color: #67C23A; margin-top: 5px; max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-actions { margin-left: 10px; } .dialog-footer { display: flex; justify-content: flex-end; padding-top: 15px; border-top: 1px solid #ebeef5; } .has-file >>> .el-upload-dragger { border: 1px dashed #67C23A; background-color: rgba(103, 194, 58, 0.05); } .el-icon-loading { font-size: 20px; color: #409EFF; margin-right: 10px; } </style> 上传文件后布局混乱

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>硬件运维系统 - 报告管理</title> </head> <body> 报告管理 <input type="text" id="search-report" placeholder="搜索报告名称/类型"> <button class="btn" id="search-btn">搜索</button> <button class="btn" id="sort-by-date">按日期排序</button> <button class="btn btn-download" id="download-all">下载全部报告</button> <button class="btn" id="add-report">新增报告</button> 新增报告 × <form id="report-form"> <input type="hidden" id="report-id"> <label for="report-name">报告名称</label> <input type="text" id="report-name" required> <label for="report-type">报告类型</label> <select id="report-type" required> <option value="硬件故障处理报告">硬件故障处理报告</option> <option value="软件运维报告">软件运维报告</option> <option value="设备健康度报告">设备健康度报告</option> <option value="产线运行分析报告">产线运行分析报告</option> <option value="硬件日志采集报告">硬件选择 - 获取指定时间段的日志</option> </select> <label for="log-start-date">日志开始日期</label> <input type="date" id="log-start-date" required> <label for="log-end-date" style="margin-top: 10px;">日志结束日期</label> <input type="date" id="log-end-date" required> <label for="report-date">报告生成日期</label> <input type="date" id="report-date" required> <label for="report-content">报告内容</label> 请根据报告类型填写内容... <textarea id="report-content" required></textarea> <button type="button" class="btn" id="cancel-btn">取消</button> <button type="submit" class="btn">保存</button> </form> <script src="style/js/jquery.min.js"></script> <script> // 检查登录状态 if (localStorage.getItem('isLogin') !== '1') { window.location.href = 'login.html'; } // 初始化报告数据和硬件日志数据 let reports = []; let hardwareLogs = []; // DOM 元素缓存 const $reportList = $('#report-list'); const $reportModal = $('#report-modal'); const $modalTitle = $('#modal-title'); const $reportForm = $('#report-form'); const $reportId = $('#report-id'); const $reportName = $('#report-name'); const $reportType = $('#report-type'); const $reportDate = $('#report-date'); const $reportContent = $('#report-content'); const $addReportBtn = $('#add-report'); const $cancelBtn = $('#cancel-btn'); const $closeBtn = $('.close'); const $searchBtn = $('#search-btn'); const $searchInput = $('#search-report'); const $sortByDateBtn = $('#sort-by-date'); const $downloadAllBtn = $('#download-all'); const $logTimeRange = $('.log-time-range'); const $contentDesc = $('#content-desc'); // 报告类型模板映射 const typeTemplates = { '硬件故障处理报告': 1. 故障现象: 2. 故障排查过程: 3. 处理方案: 4. 处理结果: 5. 预防建议:, '软件运维报告': 1. 运维内容: 2. 操作过程: 3. 运行状态: 4. 遗留问题: 5. 后续计划:, '设备健康度报告': 1. 设备状态: 2. 检查项目: 3. 异常项: 4. 维护建议: 5. 预测分析:, '产线运行分析报告': 1. 生产数据: 2. 设备表现: 3. 瓶颈分析: 4. 改进措施: 5. 提升建议:, '硬件日志采集报告': ### 日志采集说明 - 采集时间段:{startDate} 至 {endDate} - 涉及设备:自动从日志中提取 - 异常日志数量:{errorCount} ### 关键日志摘要 {logSummary} }; // 从API加载报告数据 function loadReports() { $.ajax({ url: 'api/reports.php', method: 'GET', dataType: 'json', success: function (data) { reports = data || []; renderReports(reports); }, error: function (xhr, status, error) { console.error('加载报告失败:', error); $reportList.html('加载报告数据失败,请稍后重试'); } }); } // 加载硬件日志数据 function loadHardwareLogs() { $.getJSON('data/hardware_logs.json', (data) => { hardwareLogs = data.logs || []; console.log('硬件日志加载成功'); }).fail((xhr, status, error) => { console.error('加载硬件日志失败:', error); hardwareLogs = []; }); } // 渲染报告列表 function renderReports(reportData) { $reportList.empty(); // 解绑之前的事件处理器,避免重复绑定 $reportList.off('click', '.edit-btn'); $reportList.off('click', '.delete-btn'); $reportList.off('click', '.download-btn'); if (reportData.length === 0) { $reportList.html('暂无报告数据,请点击"新增报告"创建'); return; } reportData.forEach(report => { const $card = $( ${report.name} ${report.type} | 生成日期:${report.date} <button class="action-btn download-btn">下载</button> <button class="action-btn edit-btn">编辑</button> <button class="action-btn delete-btn">删除</button> ); $reportList.append($card); }); // 绑定事件 $reportList.on('click', '.edit-btn', function () { const reportId = $(this).closest('.report-card').data('id'); editReport(reportId); }); $reportList.on('click', '.delete-btn', function () { const reportId = $(this).closest('.report-card').data('id'); deleteReport(reportId); }); $reportList.on('click', '.download-btn', function () { const reportId = $(this).closest('.report-card').data('id'); downloadReport(reportId); }); } // 打开模态框 function openModal(isEdit = false, report = null) { $reportForm[0].reset(); $logTimeRange.hide(); $reportContent.val(''); if (isEdit && report) { $modalTitle.text('编辑报告'); $reportId.val(report.id); $reportName.val(report.name); $reportType.val(report.type); $reportDate.val(report.date); $reportContent.val(report.content); if (report.type === '硬件日志采集报告') { $logTimeRange.show(); $('#log-start-date').val(report.logStartDate || ''); $('#log-end-date').val(report.logEndDate || ''); } } else { $modalTitle.text('新增报告'); $reportId.val(''); $reportDate.val(new Date().toISOString().split('T')[0]); } $reportModal.show(); } // 关闭模态框 function closeModal() { $reportModal.hide(); } // 编辑报告 function editReport(id) { console.log('编辑报告:', reports); console.log('报告ID:', id); const stringId = String(id); const report = reports.find(r => r.id === stringId); console.log('编辑报告:', report); // console.log(r.id); if (report) { openModal(true, report); } else { alert('未找到该报告'); loadReports(); } } // 删除报告 function deleteReport(id) { const stringId = String(id); const report = reports.find(r => r.id === stringId); if (!report) { alert('未找到该报告'); loadReports(); return; } if (confirm(确定要删除"${report.name}"这份报告吗?删除后无法恢复!)) { $.ajax({ url: 'api/reports.php', method: 'DELETE', contentType: 'application/json', data: JSON.stringify({ id: id }), dataType: 'json', success: function (response) { if (response.success) { loadReports(); // 重新加载数据 } else { alert('删除失败:' + (response.message || '未知错误')); } }, error: function (xhr, status, error) { console.error('删除报告失败:', error); alert('删除报告失败,请检查网络连接'); } }); } } // 下载单个报告 function downloadReport(id) { const report = reports.find(r => r.id === id); if (!report) return; let content = 报告名称:${report.name} 报告类型:${report.type} 生成日期:${report.date} 报告内容: ${report.content} .trim(); if (report.type === '硬件日志采集报告' && report.attachments && report.attachments.length) { content += \n\n=== 日志附件 ===\n; report.attachments.forEach(attach => { content += \n【附件:${attach.filename}】\n${attach.content}\n; }); } const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = $('').attr({ href: url, download: ${report.name.replace(/[\/:*?"<>|]/g, '-')}.txt }); $('body').append(a); a[0].click(); a.remove(); URL.revokeObjectURL(url); } // 下载全部报告 function downloadAllReports() { if (reports.length === 0) { alert('没有报告可下载'); return; } let allContent = '=== 所有报告汇总 ===\n\n'; reports.forEach((report, idx) => { allContent += 【报告 ${idx + 1}】\n; allContent += 名称:${report.name}\n类型:${report.type}\n日期:${report.date}\n\n; allContent += 内容:\n${report.content}\n\n; if (report.type === '硬件日志采集报告' && report.attachments && report.attachments.length) { allContent += === 日志附件 ===\n; report.attachments.forEach(attach => { allContent += \n【附件:${attach.filename}】\n${attach.content}\n; }); } allContent += '========================================\n\n'; }); const blob = new Blob([allContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = $('').attr({ href: url, download: 所有报告汇总_${new Date().toISOString().split('T')[0]}.txt }); $('body').append(a); a[0].click(); a.remove(); URL.revokeObjectURL(url); } // 保存报告 $reportForm.on('submit', function (e) { e.preventDefault(); const formData = { id: $reportId.val(), name: $reportName.val(), type: $reportType.val(), date: $reportDate.val(), content: $reportContent.val(), attachments: [] }; if (formData.type === '硬件日志采集报告') { const startDate = $('#log-start-date').val(); const endDate = $('#log-end-date').val(); formData.logStartDate = startDate; formData.logEndDate = endDate; const filteredLogs = hardwareLogs.filter(log => { const logTime = new Date(log.timestamp); const start = new Date(startDate); const end = new Date(endDate); return logTime >= start && logTime <= end; }); if (filteredLogs.length > 0) { const errorCount = filteredLogs.filter(log => log.level === 'ERROR').length; const logSummary = filteredLogs.map(log => [${log.timestamp}] [${log.device}] [${log.level}]:${log.content} ).join('\n'); formData.content = typeTemplates['硬件日志采集报告'] .replace('{startDate}', startDate) .replace('{endDate}', endDate) .replace('{errorCount}', errorCount) .replace('{logSummary}', logSummary); formData.attachments.push({ filename: hardware_logs_${startDate}_${endDate}.txt, content: filteredLogs.map(log => ${log.timestamp}\n${log.device}\n${log.level}\n${log.content}\n-----\n ).join('') }); } else { formData.content = '未找到指定时间段的日志数据'; } } const method = formData.id ? 'PUT' : 'POST'; $.ajax({ url: 'api/reports.php', method: method, contentType: 'application/json', data: JSON.stringify(formData), dataType: 'json', success: function (response) { if (response.success) { loadReports(); closeModal(); } else { alert('保存失败:' + (response.message || '未知错误')); } }, error: function (xhr, status, error) { console.error('保存报告失败:', error); alert('保存报告失败,请检查网络连接'); } }); }); // 搜索报告 function handleSearch() { const keyword = $searchInput.val().toLowerCase(); const filtered = reports.filter(report => report.name.toLowerCase().includes(keyword) || report.type.toLowerCase().includes(keyword) ); renderReports(filtered); } // 按日期排序 function sortReportsByDate() { const sorted = [...reports].sort((a, b) => new Date(b.date) - new Date(a.date) ); renderReports(sorted); } // 事件绑定 function bindEvents() { // 报告类型切换 // / 修改报告类型切换事件 $reportType.on('change', function () { const type = $(this).val(); const $startDate = $('#log-start-date'); const $endDate = $('#log-end-date'); $logTimeRange.hide(); $contentDesc.text('请根据报告类型填写内容...'); if (type === '硬件日志采集报告') { $logTimeRange.show(); $contentDesc.text('选择时间段后将自动生成日志摘要'); $reportContent.val(''); // 仅在日志类型下添加必填属性 $startDate.attr('required', true); $endDate.attr('required', true); } else { $reportContent.val(typeTemplates[type] || ''); // 其他类型下移除必填属性 $startDate.removeAttr('required'); $endDate.removeAttr('required'); } }); // 新增报告 $addReportBtn.on('click', () => openModal()); // 关闭模态框 $closeBtn.on('click', closeModal); $cancelBtn.on('click', closeModal); // 点击模态框外部关闭 $(window).on('click', (e) => { if ($(e.target).is($reportModal)) closeModal(); }); // 搜索 $searchBtn.on('click', handleSearch); $searchInput.on('keypress', (e) => { if (e.key === 'Enter') handleSearch(); }); // 排序 $sortByDateBtn.on('click', sortReportsByDate); // 下载全部 $downloadAllBtn.on('click', downloadAllReports); } // 初始化 function init() { bindEvents(); loadHardwareLogs(); loadReports(); } // 页面加载完成后初始化 $(document).ready(init); </script> </body> </html> 优化代码.让拟态窗更加好看

<script setup> import { ref, onMounted } from 'vue'; import { onShow } from '@dcloudio/uni-app'; // 响应式数据 const surveyList = ref([]); const total = ref(0); const loading = ref(false); // 获取问卷数据 const fetchSurveyData = async () => { try { loading.value = true; // 使用uni.request发送请求 const [error, res] = await uni.request({ url: 'http://172.26.26.43/dev-api/wjdc/wj/listTx', method: 'GET', data: { pageNum: 1, pageSize: 10, dcWjTitle: '', dcId: '', dcDept: '' } }); if (error) throw error; // 处理响应数据 const response = res.data; if (response.code === 200) { surveyList.value = response.rows; total.value = response.total; } else { throw new Error(response.msg || '请求失败'); } } catch (error) { uni.showToast({ title: error.message || '加载失败', icon: 'none', duration: 2000 }); } finally { loading.value = false; } }; // 使用onShow替代onMounted确保每次进入页面都刷新 onShow(() => { fetchSurveyData(); }); </script> <template> <view class="container"> <view v-if="loading" class="loading-container"> <view class="loading-spinner"></view> <text class="loading-text">加载中...</text> </view> <template v-else> <text class="total">共 {{ total }} 条记录</text> <view v-for="(item, index) in surveyList" :key="index" class="card"> <view class="title">{{ item.dcWjTitle }}</view> <view class="info"> <text>部门: {{ item.dcDept }}</text> <text>创建人: {{ item.createBy }}</text> </view> <view class="meta"> <text>创建时间: {{ item.createTime }}</text> <text class="score">得分: {{ item.score }}</text> </view> </view> <view v-if="surveyList.length === 0" class="empty"> <text>暂无数据</text> </view> </template> </view> </template> <style scoped> .container { padding: 20rpx; background-color: #f5f5f5; min-height: 100vh; } /* 自定义加载状态样式 */ .loading-container { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40rpx 0; } .loading-spinner { width: 60rpx; height: 60rpx; border: 6rpx solid #f3f3f3; border-top: 6rpx solid #3498db; border-radius: 50%; animation: spin 1s linear infinite; margin-bottom: 20rpx; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading-text { color: #666; font-size: 28rpx; } /* 数据样式 */ .total { display: block; margin: 20rpx 0; padding: 0 20rpx; color: #888; font-size: 28rpx; } .card { padding: 30rpx; margin-bottom: 30rpx; border-radius: 16rpx; background-color: #fff; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05); } .title { font-size: 34rpx; font-weight: bold; margin-bottom: 20rpx; color: #333; } .info { display: flex; justify-content: space-between; color: #666; font-size: 28rpx; margin-bottom: 15rpx; } .meta { display: flex; justify-content: space-between; color: #999; font-size: 26rpx; margin-top: 15rpx; } .score { color: #e74c3c; font-weight: bold; } .empty { text-align: center; padding: 100rpx 0; color: #999; font-size: 32rpx; } </style> 我的数据加载板块参照代码:<template> <el-card class="index-card"> <el-form :model="formData" label-position="top" ref="indexForm" class="mobile-form" > <el-form-item label="问卷标题:" prop="dcWjTitle"> <el-input v-model="formData.dcWjTitle" placeholder="请输入问卷标题" clearable :prefix-icon="Document" /> </el-form-item> <el-form-item label="被测评人:" prop="dcId" class="inline-form-item"> <el-select v-model="formData.dcId" multiple filterable remote reserve-keyword clearable placeholder="请选择被测评人" :remote-method="searchBdr" :loading="bdrLoading" @focus="handleBdrFocus" > <el-option v-for="item in bdrOptions" :key="item.dcId" :label="item.dcName" :value="item.dcId" /> </el-select> </el-form-item> <el-form-item label="人员部门:" prop="dcDept" class="inline-form-item"> <el-input v-model="formData.dcDept" placeholder="请输入人员部门" clearable :prefix-icon="OfficeBuilding" /> </el-form-item> <el-form-item label="提交状态:" prop="state"> <el-select v-model="formData.state" placeholder="请选择提交状态" clearable class="mobile-select" > <el-option label="已提交" :value="1" /> <el-option label="未提交" :value="0" /> </el-select> </el-form-item> <el-form-item class="button-group"> <el-button type="primary" @click="handleSearch" class="action-button" :icon="Search" > 搜索 </el-button> <el-button @click="handleReset" class="action-button" :icon="Refresh" > 重置 </el-button> </el-form-item> </el-form> </el-card> <el-card class="data-card"> <template #header> <el-button type="primary" size="small" :icon="Refresh" @click="fetchData" > 刷新数据 </el-button> </template> {{ item.dcWjTitle }} 被测评人: {{ item.dcName }} 部门: {{ item.dcDept }} 创建时间: {{ item.createTime }} 提交时间: {{ item.updateTime || '-' }} <el-tag :type="item.state === '1' ? 'success' : 'info'"> {{ item.state === '1' ? '已提交' : '未提交' }} </el-tag> 总分: {{ item.score || '0' }} <el-button size="small" type="primary" @click="handleView(item)" class="action-btn" > 编辑/查看 </el-button> <el-empty v-if="tableData.length === 0" description="暂无数据" /> <el-pagination v-model:current-page="pagination.current" v-model:page-size="pagination.size" :page-sizes="[5, 10, 20, 50]" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" @size-change="handleSizeChange" @current-change="handlePageChange" /> </el-card> </template> <script setup> // 确保正确导入所有 Vue 函数 import { ref, reactive, onMounted, onUnmounted } from 'vue'; import axios from 'axios'; import { Document, User, OfficeBuilding, Search, Refresh } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus'; import { useRouter } from 'vue-router'; const router = useRouter(); // 环境变量管理API地址 const API_BASE = import.meta.env.VITE_API_BASE || 'http://172.26.26.43/dev-api'; const API_URL = ${API_BASE}/wjdc/wj/listTx; const BDR_API_URL = ${API_BASE}/wjdc/wj/getBdrList; // 被测评人相关数据 const bdrOptions = ref([]); // 被测评人选项列表 const bdrLoading = ref(false); // 加载状态 const bdrCache = ref([]); // 缓存所有被测评人数据 // 表单数据 const formData = reactive({ dcWjTitle: '', dcId: [], dcDept: '', state: null }); // 表格数据 const tableData = ref([]); const loading = ref(false); // 分页配置 const pagination = reactive({ current: 1, size: 10, total: 0 }); // 表单引用 const indexForm = ref(null); // 请求取消令牌 let cancelTokenSource = axios.CancelToken.source(); // 处理被测评人输入框获取焦点 const handleBdrFocus = () => { if (bdrCache.value.length === 0) { fetchBdrList(''); } }; // 获取被测评人列表 const fetchBdrList = async (keyword = '') => { const token = getAuthToken(); if (!token) return; bdrLoading.value = true; try { const response = await axios.get(BDR_API_URL, { headers: { 'Authorization': Bearer ${token} } }); // 判断返回的数据是否是数组 if (Array.isArray(response.data)) { // 缓存所有数据 bdrCache.value = response.data; // 根据关键字过滤 if (keyword) { const searchTerm = keyword.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName && item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); // 最多显示10条 } else { // 未输入关键字时显示前10条 bdrOptions.value = bdrCache.value.slice(0, 10); } } else { // 如果不是数组,则按照原有格式处理(假设有code和data) if (response.data && response.data.code === 200) { bdrCache.value = response.data.data || []; // 同样的过滤逻辑 if (keyword) { const searchTerm = keyword.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); } else { bdrOptions.value = bdrCache.value.slice(0, 10); } } else { const msg = response.data?.msg || '返回数据格式不正确'; ElMessage.error('获取被测评人列表失败: ' + msg); } } } catch (error) { console.error('获取被测评人列表失败:', error); ElMessage.error('获取被测评人列表失败'); } finally { bdrLoading.value = false; } }; // 搜索被测评人(防抖) let searchBdrTimer = null; const searchBdr = (query) => { if (searchBdrTimer) clearTimeout(searchBdrTimer); searchBdrTimer = setTimeout(() => { if (bdrCache.value.length === 0) { fetchBdrList(query); } else { // 本地过滤 if (query) { const searchTerm = query.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); } else { bdrOptions.value = bdrCache.value.slice(0, 10); } } }, 300); }; // 获取认证令牌 const getAuthToken = () => { const token = localStorage.getItem('token'); if (!token) { ElMessage.warning('请先登录'); router.push('/login'); return null; } return token; }; // 搜索按钮处理函数 - 防抖 let searchTimer = null; const handleSearch = () => { // 检查被测评人选择数量 if (formData.dcId.length > 1) { ElMessage.warning({ message: '当前只能搜索一个被测人员', duration: 3000 }); return; } if (searchTimer) clearTimeout(searchTimer); searchTimer = setTimeout(() => { pagination.current = 1; fetchData(); }, 300); }; // 重置按钮处理函数 const handleReset = () => { if (indexForm.value) { indexForm.value.resetFields(); // 确保重置后 dcId 是空数组 formData.dcId = []; } handleSearch(); }; // 编辑/查看 const handleView = (row) => { router.push({ name: 'Operation', // 路由名称 params: { id: row.dcWjId // 传递问卷ID作为参数 } }); }; // 分页大小改变 const handleSizeChange = (size) => { pagination.size = size; fetchData(); }; // 页码改变 const handlePageChange = (page) => { pagination.current = page; fetchData(); }; // 获取数据 const fetchData = async () => { // 获取认证令牌 const token = getAuthToken(); if (!token) return; // 取消之前的请求 if (cancelTokenSource) { cancelTokenSource.cancel('请求被取消'); } cancelTokenSource = axios.CancelToken.source(); loading.value = true; try { // 构造请求参数 const params = { pageNum: pagination.current, pageSize: pagination.size, ...formData, // 安全处理:确保 dcId 是数组再 join dcId: Array.isArray(formData.dcId) ? formData.dcId.join(',') : '' // 将数组转换为逗号分隔的字符串 }; // 调用API - 添加认证头 const response = await axios.get(API_URL, { params, cancelToken: cancelTokenSource.token, headers: { 'Content-Type': 'application/json', 'Authorization': Bearer ${token} } }); // 处理响应数据 const { data } = response; if (data && data.code === 200) { // 修改点:直接使用 data.rows 和 data.total tableData.value = data.rows || []; pagination.total = data.total || 0; // 空数据提示 if (tableData.value.length === 0) { ElMessage.info('没有找到匹配的数据'); } } else { const errorMsg = data?.msg || '未知错误'; console.error('API返回错误:', errorMsg); ElMessage.error(请求失败: ${errorMsg}); tableData.value = []; pagination.total = 0; } } catch (error) { // 处理认证失败 if (error.response && error.response.status === 401) { ElMessage.error('认证过期,请重新登录'); localStorage.removeItem('token'); router.push('/login'); return; } // 忽略取消请求的错误 if (!axios.isCancel(error)) { console.error('获取数据失败:', error); const errorMsg = error.response?.data?.message || '网络请求失败'; ElMessage.error(请求失败: ${errorMsg}); tableData.value = []; pagination.total = 0; } } finally { loading.value = false; } }; // 页面加载时获取初始数据 onMounted(() => { fetchData(); }); // 组件卸载时取消所有请求 onUnmounted(() => { if (cancelTokenSource) { cancelTokenSource.cancel('组件卸载,取消请求'); } }); </script> <style scoped> .form-row { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 16px; } .inline-form-item { flex: 1; min-width: 250px; } .inline-form-item :deep(.el-form-item__label) { float: left; width: auto; padding-right: 12px; line-height: 32px; } .inline-form-item :deep(.el-form-item__content) { display: flex; flex: 1; } /* 移动端响应式 */ @media (max-width: 768px) { .form-row { flex-direction: column; gap: 16px; } .inline-form-item { min-width: 100%; } .inline-form-item :deep(.el-form-item__label) { float: none; width: 100%; padding-right: 0; padding-bottom: 8px; } } /* 卡片容器样式 */ .card-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 16px; } /* 单个卡片样式 */ .data-card-item { background: #fff; border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); padding: 16px; display: flex; flex-direction: column; transition: all 0.3s ease; border: 1px solid #ebeef5; } .data-card-item:hover { transform: translateY(-4px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); } /* 卡片头部(序号+标题) */ .card-header-section { padding-bottom: 12px; border-bottom: 1px solid #f0f2f5; margin-bottom: 12px; } .card-id { font-size: 14px; color: #909399; margin-bottom: 4px; } .card-title { font-size: 16px; font-weight: 600; color: #303133; line-height: 1.4; word-break: break-word; } /* 卡片主体(其他信息) */ .card-body-section { flex: 1; margin-bottom: 12px; } .card-row { display: flex; margin-bottom: 8px; font-size: 14px; } .card-label { color: #606266; min-width: 70px; text-align: right; } .card-value { color: #303133; flex: 1; word-break: break-word; } /* 卡片底部(状态+按钮) */ .card-footer-section { display: flex; justify-content: space-between; align-items: center; padding-top: 12px; border-top: 1px solid #f0f2f5; } .status-container { display: flex; align-items: center; gap: 8px; } .score { font-size: 14px; color: #e6a23c; font-weight: 500; } .action-btn { flex-shrink: 0; } /* 移动端响应式 */ @media (max-width: 768px) { .card-container { grid-template-columns: 1fr; } .card-row { flex-direction: column; margin-bottom: 12px; } .card-label { text-align: left; margin-bottom: 4px; font-weight: 500; } .card-footer-section { flex-direction: column; align-items: stretch; gap: 12px; } .status-container { justify-content: space-between; } } /* 添加选择器样式 */ :deep(.el-select) .el-input__inner { height: auto !important; min-height: 44px; padding: 5px 15px; } /* 标签样式 */ :deep(.el-tag) { margin: 2px 6px 2px 0; } /* 下拉菜单样式 */ :deep(.el-select-dropdown) { max-height: 300px; overflow-y: auto; } .index-card { border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .card-header { font-size: 18px; font-weight: 600; color: #1a1a1a; } .mobile-form { :deep(.el-form-item__label) { font-weight: 500; margin-bottom: 6px; } :deep(.el-input__inner) { height: 44px; border-radius: 8px; } } .mobile-select { width: 100%; :deep(.el-input__inner) { height: 44px; } } /* 按钮区域样式 */ .button-group { display: flex; gap: 12px; margin-top: 16px; } .action-button { flex: 1; height: 46px; font-size: 16px; border-radius: 8px; } /* 移动端响应式调整 */ @media (max-width: 480px) { .button-group { flex-direction: column; gap: 10px; } .action-button { width: 100%; } } </style>

最新推荐

recommend-type

基于等式约束的车辆纵向动力学模型预测控制及其Matlab数值仿真实验研究 指南

内容概要:本文探讨了车辆纵向动力学模型预测控制,特别是引入等式约束条件下的实现方法,并通过Matlab数值仿真实验验证了其有效性和优越性。文章首先介绍了车辆纵向动力学模型的基本概念,包括牵引力、空气阻力、轮胎与地面的摩擦力等因素对车辆速度的影响。接着详细阐述了预测控制算法的工作原理,即通过优化算法寻找最佳的牵引力和制动力,以实现最佳行驶效果。最后展示了Matlab数值仿真实验的具体步骤和结果,对比了不同控制策略的性能,证明了基于模型的预测控制策略在复杂道路和交通环境下具有更高的准确性和鲁棒性。 适合人群:从事汽车工程、自动化控制领域的研究人员和技术人员,尤其是关注车辆动力学建模和预测控制算法的人士。 使用场景及目标:适用于希望深入了解车辆纵向动力学模型预测控制理论并掌握其实现方法的研究人员和技术人员。目标是提高车辆的安全性、节能性和驾驶辅助系统的智能化水平。 阅读建议:读者可以重点关注等式约束条件下的预测控制算法设计思路,以及Matlab数值仿真实验的设计和结果分析部分,以便更好地理解和应用这一先进技术。
recommend-type

Python打造的Slaee管理系统升级版发布

由于提供的文件信息中,文件名《基于python的slaee管理系统 (15).zip》与描述《基于python的slaee管理系统 (15).zip》相同,并且给出的压缩包文件名称列表中只有一个文件《基于python的slaee管理系统 (14).zip》,该信息表明我们正在讨论两个不同版本的Python系统管理软件的压缩包。以下知识点将根据这些信息详细展开: 知识点一:Python编程语言基础 Python是一种高级编程语言,以其简洁的语法和强大的库支持而闻名。它是解释型语言,具有动态类型系统和垃圾回收功能,适用于多种编程范式,包括面向对象、命令式、函数式和过程式编程。Python广泛应用于系统管理、网络服务器、开发脚本、科学计算、数据挖掘和人工智能等领域。 知识点二:系统管理相关知识 系统管理指的是对计算机系统进行配置、监控和维护的过程,包括硬件资源、软件资源和数据资源的管理。在Python中,系统管理通常涉及操作系统级别的任务,如进程管理、文件系统管理、网络配置、系统日志监控等。Python的系统管理库(例如psutil、fabric、paramiko等)提供了丰富的API来简化这些任务。 知识点三:项目版本控制 从文件名《基于python的slaee管理系统 (14).zip》和《基于python的slaee管理系统 (15).zip》可以看出,这是一个项目在不同版本之间的迭代。版本控制是一种记录一个或多个文件随时间变化的方式,它允许用户可以回到特定版本。在软件开发中,版本控制非常重要,它有助于团队协作、代码合并、分支管理和错误跟踪。常见的版本控制系统包括Git、Subversion (SVN)、Mercurial等。 知识点四:打包与部署 提到“压缩包子文件”,这通常意味着文件已经被压缩打包成一个ZIP文件。在软件开发中,打包是为了便于文件传输、存档保存和分发。在Python项目中,打包也是部署过程的一部分。一个Python项目通常需要包含源代码、依赖关系、配置文件和安装脚本等。打包成ZIP文件后,可以通过各种方式部署到服务器上运行,如使用Fabric或Ansible等自动化部署工具。 知识点五:项目命名及版本命名规则 文件命名中的“基于python的slaee管理系统”表明这是一个与Python语言相关的系统管理项目。而数字“15”和“14”则代表着项目的版本号,这表明项目在持续发展,不同的数字代表了项目在不同时期的迭代。版本号的命名规则通常遵循语义化版本控制(SemVer),这种版本控制系统以 MAJOR.MINOR.PATCH 的形式表示版本号。 知识点六:文件压缩与解压缩技术 ZIP是一种常用的文件压缩格式,它通过减少文件大小来提高存储效率和传输速度。ZIP文件通常是无损压缩,意味着文件在压缩和解压缩的过程中不会丢失信息。Python标准库提供了zipfile模块,允许用户在Python程序中创建ZIP文件、读取ZIP文件内容、提取ZIP文件中的文件等操作。用户可以使用各种图形界面工具(如WinRAR、7-Zip)或命令行工具来处理ZIP文件。 总结以上内容,从文件信息中我们可以得知该内容涉及了Python编程语言、系统管理知识、版本控制、打包与部署、命名规则以及文件压缩技术等多方面的知识点。这些知识点对于理解和应用Python进行系统管理软件开发以及软件的版本迭代、打包与部署均具有重要意义。
recommend-type

深入解析PCB走线传输延时:关键因素与实用公式

# 1. PCB走线传输延时基础 在电子工程领域,尤其是在印刷电路板(PCB)设计中,走线传输延时是一个不可忽视的重要概念。传输延时主要指的是电信号通过PCB上的导电路径从源头传送到目的地所耗费的时间。本章将介绍PCB走线传输延时的基础知识点,为后续章节的深入探讨打下坚实的基础。 首先,了解什么是传输延时是至关重要的。简单来说,它反
recommend-type

gpio很弱是什么意思

<think>嗯,用户的问题是关于GPIO信号弱的概念及其影响。用户似乎对硬件或嵌入式系统有一定了解,但需要更深入的解释。从用户提到的"信号弱"来看,ta可能遇到了实际电路设计中的驱动能力问题,或者在学习GPIO原理时遇到了术语困惑。 用户引用了四篇资料,其中提到GPIO的模拟输入输出模式、施密特触发器的作用、上拉下拉电阻的配置,以及信号线串联电阻的作用。这些内容都与GPIO的驱动能力和信号质量相关。特别是引用[4]中提到的"信号线串联小电阻"和"低频电路不考虑反射",暗示用户可能正在处理实际电路中的信号完整性问题。 用户真正想知道的可能是:为什么我的GPIO输出无法正确驱动某个设备?或者
recommend-type

Python打造的Slaee管理系统升级版发布

标题中的“基于python的slaee管理系统”表明这是一个使用Python编程语言开发的系统。Python是一种广泛使用的高级编程语言,以其易读性和简洁的语法而闻名。SLAEE管理系统可能是指一个特定类型的管理软件,但由于没有给出缩写的完整解释,我们可以假设SLAEE可能是某机构或系统名称的缩写。 从标题和描述来看,存在一处笔误:“基于python的slaee管理系统 (19).zip”和“基于python的slaee管理系统 (18).zip”所指的似乎是同一软件系统,只是版本号不同。根据文件名称列表中的两个文件名,可以推断系统至少有两个版本,一个是版本18,一个是版本19。通常情况下,版本号的增加表示软件进行了更新或改进。 接下来,根据这些信息,我们可以阐述一些相关的知识点: 1. Python编程基础:Python是一种解释型、面向对象、高级编程语言。Python支持多种编程范式,包括过程式、面向对象和函数式编程。Python由于其简洁和易于学习的特性,被广泛应用于网络开发、数据分析、人工智能、机器学习和科学计算等领域。 2. 文件压缩与打包:文件压缩是将文件的大小减小以节省存储空间或网络传输时间的技术。常见的文件压缩格式包括ZIP、RAR、7Z等。文件打包通常指的是将多个文件或文件夹压缩成一个单独的文件。这在数据备份、软件分发和档案管理中非常常见。 3. 版本控制:在软件开发中,“版本”通常指软件的特定状态,版本号则用来标识这些状态。版本控制是一种记录文件、目录或集合随着时间变化的方式,以便将来可以检索特定版本。对于软件项目来说,版本控制是至关重要的,它不仅允许开发者追踪和管理代码的变化,而且还能帮助团队协作,解决冲突,并回滚到旧版本。 4. 软件管理系统的开发:一个软件管理系统可能是针对特定业务领域而设计的,它可能包括用户界面、数据库管理、业务逻辑处理、报告生成和其他许多功能。软件管理系统的开发通常涉及需求分析、系统设计、编程、测试和维护等多个阶段。 5. Python在软件开发中的应用:Python因为具有丰富的库和框架,被广泛用于开发各种类型的软件。例如,Django和Flask是用于Web开发的流行Python框架;而对于数据分析和数据科学任务,Pandas、NumPy和Matplotlib等库提供了强大的数据处理和可视化工具;对于机器学习和人工智能,TensorFlow、PyTorch等库使得复杂算法的实现变得更为简单。 6. 系统更新与维护:随着软件的使用和发展,需求可能会变化,新的问题可能会出现,所以软件系统需要定期进行更新和维护。软件更新可能包括修复已知问题、改进现有功能、增加新功能或优化性能。开发者需要评估是否需要为修复安全漏洞或提高系统性能而更新系统,以及更新之后对用户体验的影响。 由于文件名中只提到了“基于python的slaee管理系统”,没有提供该系统具体功能的详细描述,我们无法提供更加具体的技术知识点。如果需要分析系统的工作原理或具体的技术实现细节,还需要更多的信息。
recommend-type

【Keil-ARM编程艺术】:如何编写可维护且高效的代码

# 摘要 本文旨在为读者提供ARM微控制器编程和Keil开发环境的全面指南。第一章概览了ARM微控制
recommend-type

应用层协议概述

<think>首先,用户的问题是:“我想了解应用层协议的基本概念和常见类型 请问应用层协议简介 常见应用层协议概述”。这翻译成:“I want to understand the basic concepts of application layer protocols and common types. Please introduce application layer protocols and overview common application layer protocols.” 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式使用$$...$$格式
recommend-type

Delphi 12 TeeChartVCLFMX控件包下载及功能介绍

标题中提到的"Delphi 12 控件之TeeChartVCLFMX-2024.40.rar"指的是Delphi 12版本中使用的TeeChartVCLFMX图表控件的特定版本(2024.40版本)。Delphi是由Embarcadero Technologies开发的一款流行的集成开发环境(IDE),专门用于使用Object Pascal和C++语言开发软件应用程序。该标题强调了Delphi 12环境下TeeChartVCLFMX控件的使用,这表明Delphi的图形用户界面(GUI)组件库中包含了一个专门用于创建复杂图表和图形的组件。 从描述中仅能得到的关于文件的名称是"TeeChartVCLFMX-2024.40.rar",这意味着文件是一个压缩包,具体包含了一个TeeChartVCLFMX的图表控件,版本号为2024.40。它可能包含了在Delphi 12版本中使用该图表控件所需的所有文件,包括库文件、二进制文件、文档等。 标签"delphi 控件"简单而直接地指出了该文件属于Delphi编程环境中的一个控件类别,表明了目标用户是Delphi开发者,他们通常使用这些控件来丰富他们的应用程序界面或增强应用程序的功能。 文件名称列表提供了关于TeeChartVCLFMX压缩包内包含的具体文件及其用途的详细信息: 1. TeeChartVCLFMX-2024.40.exe:这个文件很可能是一个安装程序或可执行文件,用于安装或运行TeeChartVCLFMX图表控件。 2. Keygen.exe:这个文件名表明它可能是一个密钥生成器(Key Generator),用于生成软件的注册码或激活码,使得控件可以脱离试用限制或进行合法授权。 3. Delphi29Binaries-2024.40-windows.pak:这个文件名暗示它包含了特定于Windows平台的Delphi 29(可能指的是Delphi 12的内部版本号)的二进制文件。pak文件是压缩包的一种格式,可能包含了运行TeeChartVCLFMX图表控件所需的库文件、DLLs、组件文件等。 4. TeeChartVCLFMX-2024.40 - D12.pdf:这是一个PDF格式的文件,很可能是用户手册或帮助文档,提供了对TeeChartVCLFMX图表控件版本2024.40在Delphi 12中的使用说明,安装指南,功能介绍或示例代码等。 综合以上信息,可以推断TeeChartVCLFMX-2024.40压缩包是为Delphi 12的开发人员提供了一个专业的图表解决方案,使得用户能够将图表功能集成到他们用Delphi开发的应用程序中。TeeChartVCLFMX可能包含各种图表类型(如条形图、折线图、饼图等),以及丰富的定制选项,如颜色、样式、图例、数据绑定、交互式功能等。开发者可以利用TeeChartVCLFMX提供的图表控件在应用程序中创建强大的数据可视化功能,这对数据分析、科学计算、商业智能、财务报告等领域特别有用。 开发者需要使用Delphi 12 IDE配合提供的组件安装程序或执行文件安装和配置TeeChartVCLFMX控件,通过阅读PDF文档来了解如何使用控件,并在需要时使用Keygen.exe激活控件。Delphi29Binaries-2024.40-windows.pak文件可能包含了控件运行所需的核心二进制组件。通过合理使用这些资源,开发者可以将TeeChartVCLFMX控件集成到自己的项目中,快速构建功能丰富的图表和数据可视化组件。
recommend-type

【Keil-ARM性能优化全解】:代码监控与优化工具的实用技巧

# 摘要 本文对基于Keil-ARM平台的性能优化进行了系统性探讨,涵盖了性能监控工具的介绍、代码优化策略、系统资源管理以及综合案例分析。首先,介绍了Keil-ARM的性能监控工具及其在性能分析中的重要性,包括工具的配置和性能数据解读方法。其次,文中讨论了代码层面的优化,包括高效循环和条件语句的编写,函数内联与尾调用优化,以及编译器优化选项的应用。然后,深入分析了ARM系统资源分配、
recommend-type

电子邮箱协议

<think>首先,用户的问题是:“我想了解电子邮箱相关的协议 请问电子邮件协议有哪些”。这直接询问电子邮件协议的种类。 从系统级指令中,我需要: - 使用中文回答。 - 结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 - 在行内数学表达式使用 $...$,但这里可能没有数学内容。 - 独立公式使用 $$...$$,但可能不需要。 - 生成相关问题。 - 在引用的段落末尾添加引用标识如 [^1]。 参考提供的引用: - 引用[1]: 讨论了SMTP、POP3和IMAP。 - 引用[2]: 提到电子邮件系统采用客户机/服务器模式,涉及接收和发送邮件。 - 引用[3]: 详细描述了P