关键词:iFlyCode Figma
开发工具:
iFlyCode版本号:V3.5.2
VS Code版本号:vscode 1.103.2
Node.js 版本:v23.3.0
npx 版本:10.9.0
模型:kimi-k2
智能对话模式:智能体
(一)注册
去figma官网(https://www.figma.com/files/team/1544985652898311117/recents-and-sharing?fuid=1544985650614603067)完成注册
(二) 生成access token
具体步骤,左上角Setting -> Security -> Generate new token
注意保存好token,记住token失效日期
*点击可查看大图
(一)添加MCP Server
在VS Code中MCP市场中安装figma-ai-bridge服务,并把上一步生成的token放入FIGMA_API_KEY中
*点击可查看大图
出现如图所示,表示MCP服务连接成功
(一)复制设计稿的链接
前往 Figma 设计稿页面,选中设计稿并右击,然后在菜单中选择 Copy/Paste as > Copy link to selection
*点击可查看大图
(二)发起对话,生成代码
在 AI 对话输入框中,粘贴所复制的设计稿的链接。
在设计稿链接的标签后输入你的需求并发送。例如:"还原选中的UI设计稿"。
在设计稿链接的标签后输入prompt并发送
https://www.figma.com/design/oiiyTw7rzEoPOLT47mAI8I/Data-Table--Community-?node-id=1381-2210&t=pxInJtXSFXNTgknx-4使用HTML+CSS+JS还原这个页面
智能体开始调用Figma MCP中的工具和服务,读取设计稿的内容,自动生成文件,填入前端代码,并生成一个 index.html 文件供你预览效果。以下输出过程供参考:
*点击可查看大图
生成后发现BALANCE列缺少颜色样式,继续和智能体沟通:
BALANCE列和设计图比起来样式缺少颜色,请修改
(三) 效果展示
<html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Data Table - Customer Management</title> <link rel="stylesheet" href="style.css"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet"></head><body> <div class="container"> <!-- Header Section --> <div class="header"> <h1>Customer Management</h1> <div class="header-actions"> <div class="search-bar"> <input type="text" placeholder="Search" id="searchInput"> <svg class="search-icon" width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M9 2C5.13 2 2 5.13 2 9s3.13 7 7 7 7-3.13 7-7-3.13-7-7-7zm0 12c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="#6F809E"/> <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5z" fill="#6F809E"/> </svg> </div> <button class="filter-btn"> <svg width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M3 4h14v2H3V4zm2 5h10v2H5V9zm-2 5h14v2H3v-2z" fill="#6F809E"/> </svg> </button> <button class="add-customer-btn"> <svg width="20" height="20" viewBox="0 0 20 20" fill="none"> <path d="M10 2a8 8 0 100 16 8 8 0 000-16zm0 10a2 2 0 110-4 2 2 0 010 4zm-4 0a2 2 0 110-4 2 2 0 010 4zm8 0a2 2 0 110-4 2 2 0 010 4z" fill="#fff"/> </svg> Add Customer </button> </div> </div>
<!-- Table Section --> <div class="table-container"> <table class="data-table"> <thead> <tr> <th> <input type="checkbox" id="selectAll"> </th> <th> <div class="th-content"> <span>name</span> <svg class="sort-icon" width="8" height="11" viewBox="0 0 8 11" fill="none"> <path d="M4 0l3 4H1l3-4zm0 11l-3-4h6l-3 4z" fill="#7D90B2"/> </svg> </div> </th> <th> <div class="th-content"> <span>description</span> <svg class="sort-icon" width="8" height="11" viewBox="0 0 8 11" fill="none"> <path d="M4 0l3 4H1l3-4zm0 11l-3-4h6l-3 4z" fill="#7D90B2"/> </svg> </div> </th> <th> <div class="th-content"> <span>Rate</span> <svg class="sort-icon" width="8" height="11" viewBox="0 0 8 11" fill="none"> <path d="M4 0l3 4H1l3-4zm0 11l-3-4h6l-3 4z" fill="#7D90B2"/> </svg> </div> </th> <th> <div class="th-content"> <span>balance</span> <svg class="sort-icon" width="8" height="11" viewBox="0 0 8 11" fill="none"> <path d="M4 0l3 4H1l3-4zm0 11l-3-4h6l-3 4z" fill="#7D90B2"/> </svg> </div> </th> <th> <div class="th-content"> <span>Deposit</span> <svg class="sort-icon" width="8" height="11" viewBox="0 0 8 11" fill="none"> <path d="M4 0l3 4H1l3-4zm0 11l-3-4h6l-3 4z" fill="#7D90B2"/> </svg> </div> </th> <th> <div class="th-content"> <span>Status</span> </div> </th> <th> <div class="th-content"> <span>Actions</span> </div> </th> </tr> </thead> <tbody id="tableBody"> <!-- Customer rows will be populated by JavaScript --> </tbody> </table> </div>
<!-- Table Footer --> <div class="table-footer"> <div class="footer-left"> <span>active customers: 479/706</span> </div> <div class="footer-right"> <div class="pagination"> <button class="page-btn prev-btn"> <svg width="6" height="10" viewBox="0 0 6 10" fill="none"> <path d="M5 1L1 5l4 4" stroke="#606F89" stroke-width="1.5"/> </svg> </button> <span class="page-info">1-10 of 706</span> <button class="page-btn next-btn"> <svg width="6" height="10" viewBox="0 0 6 10" fill="none"> <path d="M1 9l4-4-4-4" stroke="#606F89" stroke-width="1.5"/> </svg> </button> </div> <div class="rows-per-page"> <span>Rows per page: 10</span> <svg width="8" height="5" viewBox="0 0 8 5" fill="none"> <path d="M0 0l4 5 4-5H0z" fill="#606F89"/> </svg> </div> </div> </div> </div>
<script src="script.js"></script></body></html>
// Customer data based on Figma designconst customerData = [ { id: 1, name: "Kadin Herwitz", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: -270.00, deposit: 500.00, status: "active", accountNumber: "5684236583" }, { id: 2, name: "Cristofer Korsgaard", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: 270.00, deposit: 500.00, status: "active", accountNumber: "5684236583" }, { id: 3, name: "Omar Workman", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 80.00, balance: -20.00, deposit: 500.00, status: "inactive", accountNumber: "5684236583" }, { id: 4, name: "Tatiana Westervelt", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: 600.00, deposit: 500.00, status: "inactive", accountNumber: "5684236583" }, { id: 5, name: "Jakob Bergson", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 75.00, balance: -270.00, deposit: 500.00, status: "active", accountNumber: "5684236583" }, { id: 6, name: "Miracle Septimus", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: -270.00, deposit: 500.00, status: "inactive", accountNumber: "5684236583" }, { id: 7, name: "Carter Rosser", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: -2070.00, deposit: 500.00, status: "inactive", accountNumber: "5684236583" }, { id: 8, name: "Haylie Rosser", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: 0.00, deposit: 500.00, status: "active", accountNumber: "5684236583" }, { id: 9, name: "Kianna Baptista", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: 460.00, deposit: 500.00, status: "inactive", accountNumber: "5684236583" }, { id: 10, name: "Lela Lubowitz", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rate: 70.00, balance: 0.00, deposit: 500.00, status: "active", accountNumber: "5684236583" }];// DOM Elementsconst tableBody = document.getElementById('tableBody');const searchInput = document.getElementById('searchInput');const selectAllCheckbox = document.getElementById('selectAll');const addCustomerBtn = document.querySelector('.add-customer-btn');const filterBtn = document.querySelector('.filter-btn');// Statelet selectedRows = new Set();let filteredData = [...customerData];// Initialize the tablefunction initializeTable(){ renderTable(); setupEventListeners();}// Render table rowsfunction renderTable(){ tableBody.innerHTML = ''; filteredData.forEach(customer => { const row = createTableRow(customer); tableBody.appendChild(row); });}// Create individual table rowfunction createTableRow(customer) { const row = document.createElement('tr'); row.dataset.id = customer.id; const isSelected = selectedRows.has(customer.id); row.innerHTML = ` <td> <input type="checkbox" class="row-checkbox" ${isSelected ? 'checked' : ''}> </td> <td class="name-cell">${customer.name}</td> <td class="description-cell">${customer.description}</td> <td class="rate-cell"> ${customer.rate.toFixed(2)} <span class="currency">INR</span> </td> <td class="balance-cell ${customer.balance < 0 ? 'negative' : customer.balance > 0 ? 'positive' : 'zero'}"> ${customer.balance.toFixed(2)} <span class="currency">INR</span> </td> <td class="deposit-cell"> ${customer.deposit.toFixed(2)} <span class="currency">INR</span> </td> <td> <span class="status-badge status-${customer.status}"> ${customer.status} </span> </td> <td class="actions-cell"> <button class="action-btn edit-btn" title="Edit"> <svg viewBox="002020" fill="currentColor"> <path d="M12.33.7l4 4L4 20H0v-4L12.33.7zM15.32.3c.8-.82-.82.80l1.41.4c.8.8.8202.8l-1.41.4-4-41.4-1.4z"/> </svg> </button> <button class="action-btn delete-btn" title="Delete"> <svg viewBox="002020" fill="currentColor"> <path d="M8 2a2 2000-22H3a1 101002h1v9a2 200022h8a2 20002-2V6h1a1 10100-2h-3a2 2000-2-2H8zM6 6h8v9H6V6zm2 2v7h2V8H8zm4 0v7h2V8h-2z"/> </svg> </button> <button class="action-btn more-btn" title="More"> <svg viewBox="002020" fill="currentColor"> <path d="M10 6a2 20100-42200004zM10 12a2 20100-42200004zM10 18a2 20100-42200004z"/> </svg> </button> </td> `; // Add event listeners const checkbox = row.querySelector('.row-checkbox'); checkbox.addEventListener('change', (e) => handleRowSelection(customer.id, e.target.checked)); const editBtn = row.querySelector('.edit-btn'); editBtn.addEventListener('click', () => handleEdit(customer)); const deleteBtn = row.querySelector('.delete-btn'); deleteBtn.addEventListener('click', () => handleDelete(customer)); const moreBtn = row.querySelector('.more-btn'); moreBtn.addEventListener('click', () => handleMore(customer)); return row;}// Handle row selectionfunction handleRowSelection(id, isSelected) { if (isSelected) { selectedRows.add(id); } else { selectedRows.delete(id); } updateSelectAllCheckbox();}// Handle select allfunction handleSelectAll(isSelected) { if (isSelected) { filteredData.forEach(customer => selectedRows.add(customer.id)); } else { selectedRows.clear(); } renderTable();}// Update select all checkbox statefunction updateSelectAllCheckbox() { const checkboxes = document.querySelectorAll('.row-checkbox'); const checkedBoxes = document.querySelectorAll('.row-checkbox:checked'); selectAllCheckbox.checked = checkboxes.length === checkedBoxes.length && checkboxes.length > 0; selectAllCheckbox.indeterminate = checkedBoxes.length > 0 && checkedBoxes.length < checkboxes.length;}// Handle searchfunction handleSearch(query) { const searchTerm = query.toLowerCase(); if (searchTerm === '') { filteredData = [...customerData]; } else { filteredData = customerData.filter(customer => customer.name.toLowerCase().includes(searchTerm) || customer.description.toLowerCase().includes(searchTerm) || customer.accountNumber.includes(searchTerm) ); } renderTable();}// Handle edit actionfunction handleEdit(customer) { console.log('Edit customer:', customer); alert(`Edit customer: ${customer.name}`);}// Handle delete actionfunction handleDelete(customer) { if (confirm(`Are you sure you want to delete ${customer.name}?`)) { console.log('Delete customer:', customer); }}// Handle more actionfunction handleMore(customer) { console.log('More options for:', customer); alert(`More options for: ${customer.name}`);}// Handle add customerfunction handleAddCustomer() { console.log('Add new customer'); alert('Add new customer form');}// Handle filterfunction handleFilter() { console.log('Open filter options'); alert('Filter options');}// Setup event listenersfunction setupEventListeners() { // Select all checkbox selectAllCheckbox.addEventListener('change', (e) => { handleSelectAll(e.target.checked); }); // Search input searchInput.addEventListener('input', (e) => { handleSearch(e.target.value); }); // Add customer button addCustomerBtn.addEventListener('click', handleAddCustomer); // Filter button filterBtn.addEventListener('click', handleFilter); // Pagination buttons document.querySelector('.prev-btn').addEventListener('click', () => { console.log('Previous page'); }); document.querySelector('.next-btn').addEventListener('click', () => { console.log('Next page'); });}// Initialize the applicationdocument.addEventListener('DOMContentLoaded', initializeTable);
* { margin: 0; padding: 0; box-sizing: border-box;}body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background-color: #f8fafc; color: #2E3B52; line-height: 1.5;}.container { max-width: 1020px; margin: 0auto; background: #FFFFFF; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15), 0px 3px 6px rgba(75, 81, 91, 0.15); border-radius: 6px; overflow: hidden;}/* Header Styles */.header { display: flex; justify-content: space-between; align-items: center; padding: 20px 30px; background: #FFFFFF; border-bottom: 1px solid #E5E7EB;}.header h1 { font-size: 24px; font-weight: 600; color: #2E3B52;}.header-actions { display: flex; align-items: center; gap: 12px;}.search-bar { position: relative; width: 300px;}.search-bar input { width: 100%; height: 40px; padding: 10px 40px 10px 10px; background: #DAE1EC; border: none; border-radius: 4px; font-family: 'Inter', sans-serif; font-size: 14px; color: #2E3B52;}.search-bar input::placeholder { color: #7D90B2;}.search-icon { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); cursor: pointer;}.filter-btn, .add-customer-btn { display: flex; align-items: center; justify-content: center; border: none; cursor: pointer; transition: all 0.2s ease;}.filter-btn { width: 40px; height: 40px; background: #DAE1EC; border-radius: 4px;}.add-customer-btn { padding: 020px; height: 40px; background: #0A65FF; color: white; border-radius: 4px; font-size: 14px; font-weight: 600; gap: 8px;}.add-customer-btn:hover { background: #0957E6;}/* Table Styles */.table-container { overflow-x: auto;}.data-table { width: 100%; border-collapse: collapse;}.data-table thead { background: #F4F7FC;}.data-table th { padding: 15px; text-align: left; font-size: 12px; font-weight: 600; color: #606F89; text-transform: uppercase; letter-spacing: 0.05em;}.data-table th:first-child { padding-left: 30px;}.th-content { display: flex; align-items: center; gap: 4px;}.sort-icon { cursor: pointer;}.data-table tbody tr { border-bottom: 1px solid #F1F5F9; transition: background-color 0.2s ease;}.data-table tbody tr:hover { background: #F8FAFC;}.data-table td { padding: 12px 15px; font-size: 14px; color: #2E3B52;}.data-table td:first-child { padding-left: 30px;}.checkbox { width: 20px; height: 20px; cursor: pointer;}.name-cell { font-weight: 500;}.description-cell { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}.rate-cell, .balance-cell, .deposit-cell { text-align: right; font-family: 'Inter', sans-serif;}.currency { color: #606F89; font-size: 12px; font-weight: 400;}.balance-cell.negative { color: #E01A1A ;}.balance-cell.positive { color: #2E7D32 ;}.balance-cell.zero { color: #606F89 ;}.status-badge { display: inline-block; padding: 4px 12px; border-radius: 11px; font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em;}.status-active { background: #0A65FF; color: white;}.status-inactive { background: transparent; color: #606F89; border: 1px solid #606F89;}.actions-cell { display: flex; gap: 8px; justify-content: flex-end; padding-right: 30px;}.action-btn { width: 20px; height: 20px; background: none; border: none; cursor: pointer; padding: 0;}.action-btn svg { width: 16px; height: 16px;}.edit-btn svg { fill: #7D90B2;}.delete-btn svg { fill: #7D90B2;}.more-btn svg { fill: #7D90B2;}.action-btn:hover svg { fill: #0A65FF;}/* Footer Styles */.table-footer { display: flex; justify-content: space-between; align-items: center; padding: 15px 30px; background: #F4F7FC; border-top: 1px solid #E5E7EB;}.footer-left span { font-size: 10px; color: #606F89; text-transform: uppercase; letter-spacing: 0.05em;}.footer-right { display: flex; align-items: center; gap: 20px;}.pagination { display: flex; align-items: center; gap: 12px;}.page-btn { width: 20px; height: 20px; background: none; border: none; cursor: pointer; padding: 0;}.page-info { font-size: 12px; font-weight: 600; color: #606F89;}.rows-per-page { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; color: #606F89;}/* Responsive Design */@media (max-width: 768px) { .container { margin: 10px; } .header { flex-direction: column; align-items: stretch; gap: 16px; } .header-actions { flex-wrap: wrap; } .search-bar { width: 100%; } .data-table { font-size: 12px; } .data-table th, .data-table td { padding: 8px; } .table-footer { flex-direction: column; gap: 12px; text-align: center; }}
(四)总结
从Figma中复制链接配上简单提示词,借助iFlyCode智能体+MCP的快速生成能力,只需要短短几分钟的时间,就可以得到相似度极高的页面,并且可以借助提示词继续对页面进行调整,而前端工程师手动开发通常需耗费2天(涉及布局搭建、交互逻辑编写、样式调试等多项工作)。iFlyCode提升了95%以上的界面开发效率,让开发者把省下来的时间更聚焦于复杂业务逻辑与体验优化,极大释放了前端开发生产力。
文末留言有奖
往期内容 点击直达
点击“阅读原文”,进入iFlyCode官网





