AI 驱动 · 智能匹配 · 高效对接

让 AI 为您精准
匹配 最优服务商

用自然语言描述您的需求,AI 引擎智能解析,秒级匹配认证服务商

热门搜索: AI客服开发 GPU算力租赁 企业官网建设 数据分析平台 品牌VI设计

优质服务商

汇聚 AI 算力、软件开发、设计创意等领域认证服务商

分类:
评分:
地区:
0 个服务商
📰

AI 行业资讯

紧跟人工智能行业前沿动态,把握技术趋势与市场机遇

📋

AI 项目标讯

实时追踪人工智能领域招投标项目,不错过每一个商业机会

0 正在招标
0 近期中标
0 采购意向
0 立项项目
💰

AI 投融资动态

聚焦人工智能领域融资事件,洞察资本流向与产业热点

0 近期融资总额
0 融资事件
0 平均融资额
📚

高质量数据集

AI训练与应用的高质量数据集供需对接,覆盖智慧文旅、工业、医疗等27+产业场景

0 数据集总量
0 可供给
0 需求中
🏛️

WAIC 2026 展商名录

2026.07.17-07.20 · 上海世博

世界人工智能大会 1,100+参展企业 · 三地四馆同步开展 · 覆盖算力、芯片、大模型、具身智能等全产业链

1,100+ 参展企业
4 展馆
100,000㎡ 展览面积
4,000+ 展品
🚀

OPC一人公司

一个人也能创业!发布你的创新Idea或技术需求,寻找合作伙伴和资源支持

0 创意/Idea
0 创新Idea
0 技术需求
🛒

AI+终端商城

AI智能穿戴 · 终端交易

AI眼镜、智能戒指、智能手表等前沿AI终端产品发布与交易,连接厂商与买家

0 在售商品
0 入驻商家
0 累计成交

为什么选择我们

六大核心优势,为您构建智能、高效的供需对接体验

🧠
AI 精准匹配
基于自然语言处理和深度学习,智能理解需求语义,精准匹配最适合的服务商,匹配准确率达 96.8%
🛡️
认证服务商
所有服务商经过严格的资质审核和企业认证,确保服务质量,降低合作风险
💰
透明比价
多维度价格对比,支持预算筛选,让您用最优的成本获取最合适的服务
高效对接
AI 助手 7x24 小时在线,从需求发布到服务商匹配,全程智能辅助,平均匹配时间仅需 30 秒
📊
全程保障
项目进度跟踪、资金托管、争议调解,为您提供从需求到交付的全流程保障服务
🌐
丰富生态
覆盖 AI、云计算、软件开发、设计创意等 15+ 领域,120+ 城市,1250+ 认证服务商
0
认证服务商
0
已发布需求
0
项目标讯
0
高质量数据集
合作伙伴
💬 微信支付
惠捷同城(内蒙古)科技有限公司
¥0.00
请使用微信扫码支付
📌 请在 30分钟 内完成支付
📌 支付成功后页面将自动刷新
📌 如遇支付问题,请联系客服
AI 供需助手
您好!我是 AI 供需助手 🤖
我可以帮您:
• 智能搜索匹配服务商
• 分析需求并推荐方案
• 查询 AI 行业最新资讯
• 追踪项目招投标标讯
• 了解 AI 投融资动态
• 解答平台使用问题

请告诉我您需要什么帮助?
💬 咨询沟通
💬
选择左侧会话开始沟通
浏览服务商或需求,点击「立即咨询」即可发起对话
块 html = html.replace(/]*>[\s\S]*?<\/script>/gi, ''); // 移除 html/head/body 标签但保留内部内容 html = html.replace(/<\/?(?:html|head|body)[^>]*>/gi, ''); // 移除 声明 html = html.replace(/]*>/gi, ''); // 移除 link、meta 等标签 html = html.replace(/<(?:link|meta)[^>]*\/?>/gi, ''); // 清理重复的空段落 html = html.replace(/]*>\s*<\/p>/gi, ''); // 合并连续换行 html = html.replace(/(\s*){2,}/gi, '
'); return html.trim(); } // 为清洗后的公告内容添加作用域样式(仅作用于 .procurement-notice 内部) function wrapProcurementNotice(html) { if (!html) return ''; return '
' + html + '
'; } // 将纯文本中的换行格式化为段落(用于项目 content 等字段) function formatTextBlocks(text) { if (!text) return ''; var paragraphs = String(text) .replace(/\r\n/g, '\n') .replace(/\r/g, '\n') .split('\n') .map(function(s) { return s.trim(); }) .filter(function(s) { return s.length > 0; }); if (!paragraphs.length) return ''; return paragraphs.map(function(p) { return '

' + escHtml(p) + '

'; }).join(''); } // 从“采购需求概况”文本中拆分出 content / quantity / mainGoal / requirements function parseProcurementProfile(text) { var result = { content: '', quantity: '', mainGoal: '', requirements: '' }; if (!text) return result; var contentMatch = text.match(/采购内容[::]\s*([\s\S]*?)(?=采购数量|主要功能|需满足|$)/); var qtyMatch = text.match(/采购数量[::]\s*([\s\S]*?)(?=主要功能|需满足|$)/); var goalMatch = text.match(/主要功能或目标[::]\s*([\s\S]*?)(?=需满足|$)/); var reqMatch = text.match(/需满足的要求[::]\s*([\s\S]*)/); if (contentMatch) result.content = contentMatch[1].trim(); if (qtyMatch) result.quantity = qtyMatch[1].trim(); if (goalMatch) result.mainGoal = goalMatch[1].trim(); if (reqMatch) result.requirements = reqMatch[1].trim(); if (!result.content && !result.mainGoal && !result.requirements) { result.content = text; } return result; } // 从采购公告 HTML 的表格中解析出采购项目明细(当 items 为空时作为兜底) function parseProcurementItemsFromNote(noteHtml) { if (!noteHtml || typeof noteHtml !== 'string' || noteHtml.indexOf('= 0; }); var idxName = headers.findIndex(function(h) { return h.indexOf('采购项目名称') >= 0; }); var idxProfile = headers.findIndex(function(h) { return h.indexOf('采购需求') >= 0 || h.indexOf('概况') >= 0; }); var idxBudget = headers.findIndex(function(h) { return h.indexOf('预算') >= 0 || h.indexOf('金额') >= 0; }); var idxTime = headers.findIndex(function(h) { return h.indexOf('预计') >= 0 && h.indexOf('时间') >= 0; }); var idxRemark = headers.findIndex(function(h) { return h.indexOf('备注') >= 0; }); if (idxName < 0 && idxProfile < 0) return []; var items = []; for (var i = 1; i < rows.length; i++) { var cells = Array.from(rows[i].querySelectorAll('td, th')); if (cells.length < 2) continue; var profileText = idxProfile >= 0 ? (cells[idxProfile].textContent || '').trim() : ''; var parsed = parseProcurementProfile(profileText); var budgetText = idxBudget >= 0 ? (cells[idxBudget].textContent || '').trim() : ''; var budgetVal = parseFloat(budgetText.replace(/[^\d.]/g, '')) || 0; var item = { seq: idxSeq >= 0 ? parseInt((cells[idxSeq].textContent || '').trim(), 10) || i : i, projectName: idxName >= 0 ? (cells[idxName].textContent || '').trim() : '', content: parsed.content, quantity: parsed.quantity, mainGoal: parsed.mainGoal, requirements: parsed.requirements, budget: budgetVal, estimatedTime: idxTime >= 0 ? (cells[idxTime].textContent || '').trim() : '', remarks: idxRemark >= 0 ? (cells[idxRemark].textContent || '').trim() : '' }; items.push(item); } return items; } catch (e) { console.error('parseProcurementItemsFromNote failed:', e); return []; } } function showProcurementDetailData(p) { // 同时兼容下划线字段名与驼峰字段名 var getField = function(obj, snake, camel) { if (obj == null) return ''; if (snake in obj) return obj[snake]; if (camel in obj) return obj[camel]; return ''; }; var region = p.region || (p.source_note ? String(p.source_note).split('|').pop().trim() : '') || (p.province ? (p.province + (p.city || '')) : ''); var entity = p.entity || p.cg_company || ''; var pubDate = p.publish_date || p.publishDate || p.created_at || ''; var views = p.views || p.view_count || 0; // 若 items 为空,尝试从公告原文表格中解析 var parsedItems = (p.items && p.items.length) ? p.items : parseProcurementItemsFromNote(p.note || ''); var itemCount = parsedItems.length; var totalBudget = 0; // 构建单个项目明细卡片 var renderItemSection = function(label, icon, bodyHtml) { if (!bodyHtml) return ''; return '
' + '' + '
' + bodyHtml + '
' + '
'; }; var itemsHtml = ''; if (parsedItems && parsedItems.length) { itemsHtml = '
' + '
📦 采购需求明细 (' + parsedItems.length + '个项目)
' + parsedItems.map(function(item, idx) { var budgetVal = parseFloat(getField(item, 'budget', 'estimatedBudget')) || 0; totalBudget += budgetVal; var budgetDisplay = budgetVal > 0 ? formatMoneyCN(budgetVal) + '万元' : ''; var projectName = getField(item, 'project_name', 'projectName') || getField(item, 'name', 'name') || '未命名项目'; var rawContent = getField(item, 'content', 'description'); var contentHtml = rawContent ? (rawContent.indexOf('<') >= 0 ? cleanProcurementHtml(rawContent) : formatTextBlocks(rawContent)) : ''; var mainGoal = getField(item, 'main_goal', 'mainGoal'); var requirements = getField(item, 'requirements', 'requirements'); var quantity = getField(item, 'quantity', 'quantity'); var estimatedTime = getField(item, 'estimated_time', 'estimatedTime'); var remarks = getField(item, 'remarks', 'remarks'); var subItemsHtml = ''; var subItems = item.subItems || item.sub_items; if (subItems && subItems.length) { subItemsHtml = '' + '' + '' + subItems.map(function(sub) { var k = escHtml(sub.label || sub.key || sub.name || '—'); var v = escHtml(sub.value || sub.content || sub.val || ''); return ''; }).join('') + '' + '
名称/指标说明/内容
' + k + '' + (v || '') + '
'; } var metaTags = []; if (budgetDisplay) metaTags.push('💰 ' + escHtml(budgetDisplay) + ''); if (quantity) metaTags.push('📦 数量:' + escHtml(quantity) + ''); if (estimatedTime) metaTags.push('📅 预计采购时间:' + escHtml(estimatedTime) + ''); if (remarks && String(remarks).trim() && String(remarks).trim() !== '无') metaTags.push('📝 备注:' + escHtml(remarks) + ''); return '
' + '
' + '
' + (item.seq || (idx + 1)) + '
' + '
' + escHtml(projectName) + '
' + '
' + (contentHtml ? renderItemSection('采购内容', '📋', contentHtml) : '') + (mainGoal ? renderItemSection('主要功能或目标', '🎯', '

' + escHtml(mainGoal) + '

') : '') + (requirements ? renderItemSection('需满足的要求', '✅', '

' + escHtml(requirements) + '

') : '') + (subItemsHtml ? renderItemSection('细分项', '🔍', subItemsHtml) : '') + (metaTags.length ? '
' + metaTags.join('') + '
' : '') + '
'; }).join('') + '
'; } // 顶部汇总栏 var summaryHtml = '
' + '
📁 项目数量:' + itemCount + '
' + '
💰 预算总额:' + (totalBudget > 0 ? formatMoneyCN(totalBudget) : '—') + ' ' + (totalBudget > 0 ? '万元' : '') + '
' + '
👁 浏览量:' + views + '
' + '
'; // 公告原文:清洗 HTML 后以作用域容器包裹渲染,保留表格等结构 var noteRaw = p.note || ''; var noteHtml = noteRaw ? '
📄 公告原文
' + wrapProcurementNotice(cleanProcurementHtml(noteRaw)) + '
' : ''; // 来源链接 var sourceUrl = p.source_url || p.sourceUrl || ''; var sourceHtml = sourceUrl ? '
🔗 查看政府采购网原文
' : ''; var body = '' + summaryHtml + detailSection('📋 基本信息', '
' + detailField('采购单位', entity || '—') + detailField('发布日期', pubDate || '—') + detailField('地区', region || '—') + detailField('状态', p.status || '发布') + detailField('信息类型', p.type || '采购意向') + '
') + itemsHtml + noteHtml + sourceHtml + (p.tags && p.tags.length ? detailSection('🏷 标签', detailTags(p.tags)) : '') + '
' + '' + '
'; openDetail(p.title, body); } function showInvestmentDetail(id) { const inv = platformData.investments.find(x => x.id === id); if (!inv) return; const hasUrl = inv.sourceUrl && inv.sourceUrl.trim(); const roundClass = inv.round.includes('A')||inv.round.includes('天使') ? 'angel' : inv.round.includes('B') ? 'B' : inv.round.includes('C')||inv.round.includes('D')||inv.round.includes('战略')||inv.round.includes('IPO') ? 'C' : ''; const primaryBtn = hasUrl ? `` : ''; const body = `

${escHtml(inv.company)}

${escHtml(inv.round)} · 📂 ${escHtml(inv.category)} · 📅 ${inv.date}
${escHtml(inv.amount)}
融资金额
${detailSection('📝 公司/项目介绍', `

${escHtml(inv.description)}

`)} ${detailSection('🤝 投资方', `

${escHtml(inv.investors)}

`)} ${hasUrl ? `

🔗 原文链接:${escHtml(inv.sourceUrl)}

` : ''} ${inv.sourceNote ? `

📋 数据来源:${escHtml(inv.sourceNote)}

` : ''} ${detailSection('🏷 标签', detailTags(inv.tags, 'tag--gold'))}
${primaryBtn}
`; openDetail(inv.company + ' - ' + inv.round, body); } function showDatasetDetail(id) { const d = platformData.datasets.find(x => x.id === id); if (!d) return; const typeLabel = d.type === 'supply' ? '📤 数据供给' : '📥 数据需求'; const priceText = d.priceRange.min && d.priceRange.max ? '¥' + (d.priceRange.min/10000).toFixed(1) + '万 - ¥' + (d.priceRange.max/10000).toFixed(1) + '万' : '面议'; const fields = [ detailField('数据类型', typeLabel), detailField('数据规模', d.scale), detailField('数据格式', d.format), detailField('所属分类', d.category), detailField('价格范围', priceText), detailField('发布日期', d.postedDate), detailField('发布方', d.postedBy), detailField('联系电话', d.contact && d.contact.phone ? '' + escHtml(d.contact.phone) + '' : '暂无'), ].join(''); const body = `

${d.name}

${typeLabel}
${detailSection('📋 基本信息', `
${fields}
`)} ${detailSection('📝 详细描述', `

${d.description}

`)} ${detailSection('🏷 标签', detailTags(d.tags))}
`; openDetail(d.name, body); } function showOpcDetail(id) { const o = platformData.opc.find(x => x.id === id); if (!o) return; const typeIcon = o.type === 'idea' ? '💡' : '🛠️'; const typeLabel = o.type === 'idea' ? '创新Idea' : '技术需求'; const typeColor = o.type === 'idea' ? 'var(--indigo-500)' : 'var(--warning)'; const body = `

${typeIcon} ${o.title}

${typeLabel} 📂 ${o.category}
${detailSection('📝 详细描述', `

${o.description}

`)} ${detailSection('🤝 寻找合作', `

${o.seeking}

`)} ${detailSection('ℹ️ 发布信息', `
${detailField('发布人', o.postedBy)} ${detailField('发布日期', o.postedDate)}
`)} ${detailSection('🏷 标签', detailTags(o.tags))}
`; openDetail(o.title, body); } function showWaicDetail(id) { const e = platformData.waic.find(x => x.id === id); if (!e) return; const hallMap = {H1:'🖥️ H1 应用与生态馆',H2:'🔬 H2 基础技术与模型馆',H3:'🤖 H3 智能机器人馆',Zhangjiang:'💎 张江科学城',West:'🌊 西岸艺术中心'}; const body = `

${escHtml(e.name)}

📂 ${escHtml(e.category)} · 📍 ${escHtml(e.booth)} · ${hallMap[e.hall] || e.hall}
${detailSection('📝 展商介绍', `

${escHtml(e.description)}

`)} ${detailSection('🎁 展示产品/方案', `

${escHtml(e.products)}

`)} ${detailSection('🏷 标签', detailTags(e.tags))}
`; openDetail(e.name, body); } // ============================================================ // 行业资讯渲染 // ============================================================ let currentNewsFilter = 'all'; function renderNews(filter) { currentNewsFilter = filter || currentNewsFilter; const grid = document.getElementById('newsGrid'); let data = currentNewsFilter === 'all' ? platformData.news : platformData.news.filter(n => n.category === currentNewsFilter || n.tags.includes(currentNewsFilter)); grid.innerHTML = data.map(n => `
${n.icon}
${n.title}
📰 ${n.source} 📅 ${n.date}

${n.summary}

`).join(''); } // ============================================================ // 招投标标讯渲染 // ============================================================ let currentBiddingFilter = 'all'; let biddingDisplayLimit = 6; // 默认展示条数 const BIDDING_PAGE_SIZE = 6; // 每次“查看更多”加载条数 function renderBiddings(filter, options) { options = options || {}; currentBiddingFilter = filter || currentBiddingFilter; const grid = document.getElementById('biddingGrid'); // 更新筛选按钮激活状态 document.querySelectorAll('#biddingFilters .bidding-filter-btn').forEach(function(btn) { btn.classList.toggle('active', btn.dataset.filter === currentBiddingFilter); }); // 切换分类时重置展示条数 if (options.resetLimit) { biddingDisplayLimit = BIDDING_PAGE_SIZE; } // 立项项目独立渲染 if (currentBiddingFilter === '立项项目') { renderProjects(grid); updateBiddingStats(); return; } let data = platformData.biddings; if (currentBiddingFilter !== 'all') { data = data.filter(b => { if (currentBiddingFilter === '采购意向') return b.type === '预告' || b.type === '采购意向'; return b.type === currentBiddingFilter; }); } // 将 procurements 转换为兼容格式并合并到列表 if (currentBiddingFilter === 'all' || currentBiddingFilter === '采购意向') { var procItems = (platformData.procurements || []).map(function(p) { var budget = ''; var totalBudget = 0; // 若 items 为空,尝试从公告原文表格解析 var procItemsList = (p.items && p.items.length) ? p.items : parseProcurementItemsFromNote(p.note || ''); if (procItemsList && procItemsList.length) { procItemsList.forEach(function(item) { var b = parseFloat(item.budget) || parseFloat(item.estimatedBudget) || 0; totalBudget += b; }); if (totalBudget > 0) { var bn = parseFloat(totalBudget); budget = (bn === Math.floor(bn) ? '' + bn : bn.toFixed(2).replace(/\.?0+$/, '')) + '万元'; } else if (procItemsList[0].quantity) { budget = procItemsList[0].quantity + ' / ' + (procItemsList[0].unit || ''); } else { budget = '详见公告'; } } // source_note 格式如 "采购意向 | 内蒙古呼伦贝尔市" var region = p.region || ''; if (!region && p.source_note) { var noteParts = String(p.source_note).split('|'); region = noteParts[noteParts.length - 1] ? noteParts[noteParts.length - 1].trim() : ''; } // 兼容后端下划线字段名 var pubDate = p.publish_date || p.publishDate || p.created_at || ''; return { id: p.id, title: p.title, type: '采购意向', owner: p.entity || '', region: region, publishDate: pubDate, deadline: p.deadline || '待定', budget: budget || '详见公告', totalBudget: totalBudget, tags: p.tags ? (Array.isArray(p.tags) ? p.tags : String(p.tags).split(',').map(function(t){ return t.trim(); }).filter(Boolean)) : [], winner: '', _fromProcurements: true, _raw: p }; }); data = data.concat(procItems); } // 按发布日期降序排列 data.sort(function(a, b) { return (b.publishDate || '').localeCompare(a.publishDate || ''); }); var totalCount = data.length; var displayData = data.slice(0, biddingDisplayLimit); grid.innerHTML = displayData.map(b => { var displayType = b.type === '预告' ? '采购意向' : b.type; const typeClass = b.type === '招标' ? 'bidding-card__type--bid' : (b.type === '中标'||b.type==='成交') ? 'bidding-card__type--win' : 'bidding-card__type--pre'; const typeIcon = b.type === '招标' ? '📢' : (b.type === '中标'||b.type==='成交') ? '🏆' : '📣'; return `
${typeIcon} ${displayType}
${b.title}
🏢 ${b.owner} 📍 ${b.region} 📅 ${b.publishDate} ${(b.type === '中标'||b.type==='成交') ? `✅ ${b.winner||''}` : ''} ${(b.type !== '采购意向' && b.type !== '中标' && b.type !== '成交') ? `⏰ 截止:${b.deadline}` : ''}
${(b.tags||[]).map(t => `${t}`).join('')}
${b.budget}
预算金额
`; }).join(''); // 查看更多按钮 if (totalCount > biddingDisplayLimit) { var remain = totalCount - biddingDisplayLimit; grid.innerHTML += `
查看更多(还剩 ${remain} 条)
`; } if (data.length === 0) { grid.innerHTML = '

📭

该分类下暂无标讯

查看全部标讯

'; } updateBiddingStats(); } function loadMoreBiddings() { biddingDisplayLimit += BIDDING_PAGE_SIZE; renderBiddings(currentBiddingFilter, { resetLimit: false }); } function isAdminProject(p) { return p && p.docType && !p.type; } function renderProjects(grid) { var data = platformData.projects || []; grid.innerHTML = data.map(p => { // —— 管理员后台格式(备案 / 批复) —— if (isAdminProject(p)) { var adocClass = p.docType==='备案' ? 'project-card__type--record' : 'project-card__type--approval'; var adocIcon = p.docType==='备案' ? '📋' : '📜'; var sourceHtml = p.sourceUrl ? '🔗 查看原文' : (p.sourceNote ? ''+p.sourceNote+'' : ''); return `
${adocIcon} ${p.docType} ${p.projectName||p.title} ${p.projectCode||''}
🏢 项目单位:${p.projectUnit||'—'}
📍 ${p.constructionLocation||'—'} ${p.authority ? '| 审批机关:'+p.authority : ''}
📅 ${p.publishDate||'—'} | 🏗️ ${p.constructionPeriod||'—'}
${(p.tags||[]).map(t => ''+t+'').join('')}
${p.totalInvestment||'—'}
总投资
${sourceHtml ? '
'+sourceHtml+'
' : ''}
`; } // —— 旧格式(中标/成交/招标等) —— var typeClass = p.type==='中标'||p.type==='成交' ? 'project-card__type--win' : p.type==='招标' ? 'project-card__type--bid' : 'project-card__type--intent'; var typeIcon = p.type==='中标' ? '🏆' : p.type==='成交' ? '✅' : p.type==='招标' ? '📢' : '📣'; return `
${typeIcon} ${p.type} ${p.title} ${p.projectNo||''}
🏢 采购单位:${p.purchaser||''}
🎯 中标供应商:${p.winner||'(待定)'}
📍 ${p.region||''}  📅 ${p.publishDate||''}  ${p.bidItemsSummary ? '📦 '+p.bidItemsSummary : ''}
${(p.tags||[]).map(t => ''+t+'').join('')}
${p.budget||''}
${p.type==='中标'||p.type==='成交' ? '中标金额' : '预算金额'}
${p.reviewScore ? '
⭐ 评审得分:'+p.reviewScore+'
' : ''}
`; }).join('') || '

📭

暂无立项项目数据

查看全部标讯

'; } function showProjectDetail(id) { var p = (platformData.projects||[]).find(function(x){return x.id===id;}); if (!p) return; var overlay = document.getElementById('templateContractOverlay'); var body = document.getElementById('templateContractBody'); // —— 管理员后台格式(备案 / 批复) —— if (isAdminProject(p)) { var adocClass = p.docType==='备案' ? 'project-card__type--record' : 'project-card__type--approval'; var adocIcon = p.docType==='备案' ? '📋' : '📜'; var sectionStyle = 'background:#f8fafc;border-radius:12px;padding:16px 18px;margin-bottom:16px;border:1px solid var(--gray-100);'; var rowStyle = 'display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px dashed #e2e8f0;font-size:13px;'; var labelStyle = 'color:var(--gray-600);font-weight:600;min-width:110px;flex-shrink:0;'; var valueStyle = 'color:var(--gray-900);text-align:right;flex:1;'; body.innerHTML = '
' + '
' + '
'+(p.title||'')+'
' + ''+adocIcon+' '+p.docType+'' + '
' + '
' + (p.projectName||'—') + '
' + '
项目代码:' + (p.projectCode||'—') + ' | ' + (p.publishDate||'') + '
' + '
' + '

一、基本信息

' + '
项目单位'+(p.projectUnit||'—')+'
' + '
批文类型'+adocIcon+' '+p.docType+'
' + (p.docNumber ? '
文号'+p.docNumber+'
' : '') + '
机关名称'+(p.authority||'—')+'
' + '
' + '
' + '

二、建设信息

' + '
建设地点'+(p.constructionLocation||'—')+'
' + '
总投资'+(p.totalInvestment||'—')+'
' + '
资金来源'+(p.fundingSource||'—')+'
' + '
建设工期'+(p.constructionPeriod||'—')+'
' + '
' + '
' + '

三、建设规模及内容

' + '

'+(p.scaleAndContent||'—')+'

' + '
' + (p.supplementaryNote ? '
' + '

四、补充说明

' + '

'+p.supplementaryNote+'

' + '
' : '') + '
' + '' + '
' + (p.tags && p.tags.length ? '
'+(p.tags||[]).map(function(t){ return ''+t+''; }).join('')+'
' : '') + '
'; // 隐藏页脚"取消"和"生成合同"按钮 var ft = document.getElementById('templateContractFooter'); if (ft) { ft.style.display = 'none'; } overlay.querySelector('.modal__title').textContent = '立项项目详情'; overlay.classList.remove('hidden'); overlay.style.display = 'flex'; overlay.scrollTop = 0; return; } // —— 旧格式(中标/成交/招标等) —— var attHtml = ''; if (p.attachments && p.attachments.length) { attHtml = '
📎 相关附件:
    '; p.attachments.forEach(function(a){ attHtml += '
  • '+a+'
  • '; }); attHtml += '
'; } var typeClass = p.type==='中标'||p.type==='成交' ? 'project-card__type--win' : p.type==='招标' ? 'project-card__type--bid' : 'project-card__type--intent'; var typeIcon = p.type==='中标' ? '🏆' : p.type==='成交' ? '✅' : p.type==='招标' ? '📢' : '📣'; body.innerHTML = '
' + '
' + p.title + '
' + '
项目编号:' + (p.projectNo||'') + ' | 公告日期:' + (p.publishDate||'') + '
' + '
'+typeIcon+' '+p.type+'
' + '

一、项目概况

' + '' + '' + '' + '' + '' + '' + '
项目编号'+(p.projectNo||'—')+'
项目名称'+p.title+'
'+(p.type==='中标'||p.type==='成交'?'中标(成交)金额':'预算金额')+''+p.budget+'
项目类别'+(p.category||'')+(p.categoryExtra?' · '+p.categoryExtra:'')+'
所属地区'+p.region+'
' + '

二、采购结果

' + '' + '' + '
供应商名称供应商地址评审方法评审得分
'+(p.winner||'(待定)')+''+(p.winnerAddress||'—')+''+(p.reviewMethod||'—')+''+(p.reviewScore||'—')+'
' + '

三、主要标的信息

' + '

采购内容概要:'+(p.bidItemsSummary||'—')+'

' + '

'+(p.description||'')+'

' + '

四、评审专家

' + '

'+(p.experts||'')+'

' + '

五、代理服务费

' + '

'+(p.agencyFee||'')+'

' + '

六、采购人及代理机构信息

' + '' + '' + '' + '' + '' + '
采购人'+(p.purchaser||'')+'
代理机构'+(p.agency||'')+'
联系人'+(p.contactPerson||'')+'
联系电话'+(p.contactPhone||'')+'
' + attHtml + '
' + '' + '
'; // 切换 footer 按钮:项目详情模式 var footer = document.getElementById('templateContractFooter'); if (footer) { if (!footer._originalHTML) footer._originalHTML = footer.innerHTML; footer.innerHTML = ''; } overlay.classList.remove('hidden'); overlay.style.display = 'flex'; overlay.querySelector('.modal__title').textContent = '立项项目详情'; overlay.scrollTop = 0; } function updateBiddingStats() { const bidCount = platformData.biddings.filter(b => b.type === '招标').length; const winCount = platformData.biddings.filter(b => b.type === '中标' || b.type === '成交').length; const intentFromBiddings = platformData.biddings.filter(b => b.type === '预告' || b.type === '采购意向').length; const intentFromProcurements = (platformData.procurements || []).length; const intentCount = intentFromBiddings + intentFromProcurements; const projectCount = (platformData.projects || []).length; document.getElementById('biddingCount').textContent = bidCount; document.getElementById('winCount').textContent = winCount; document.getElementById('intentCount').textContent = intentCount; document.getElementById('projectCount').textContent = projectCount; } // ============================================================ // 项目投资信息渲染 // ============================================================ let currentInvestFilter = 'all'; function renderInvestments(filter) { currentInvestFilter = filter || currentInvestFilter; const grid = document.getElementById('investGrid'); let data = currentInvestFilter === 'all' ? platformData.investments : platformData.investments.filter(inv => inv.category === currentInvestFilter || inv.tags.includes(currentInvestFilter)); // 计算统计数据 let totalAmount = 0; data.forEach(inv => { const amt = inv.amount; if (amt.includes('亿')) { totalAmount += parseFloat(amt) * (amt.includes('美元') ? 7.2 : 1); } }); document.getElementById('investTotalAmount').textContent = '≈' + (totalAmount > 10 ? totalAmount.toFixed(0) : totalAmount.toFixed(1)) + ' 亿元'; document.getElementById('investTotalCount').textContent = data.length; document.getElementById('investAvgAmount').textContent = data.length > 0 ? '≈' + (totalAmount/data.length).toFixed(1) + ' 亿元' : '0'; grid.innerHTML = data.map(inv => { let roundClass = 'invest-card__round--C'; if (inv.round.includes('A') || inv.round.includes('天使')) roundClass = 'invest-card__round--angel'; else if (inv.round.includes('B')) roundClass = 'invest-card__round--B'; else if (inv.round.includes('C') || inv.round.includes('D') || inv.round.includes('战略') || inv.round.includes('IPO')) roundClass = 'invest-card__round--A'; else if (inv.round.includes('种子')) roundClass = 'invest-card__round--seed'; return `
${inv.round.replace('轮','')}
${inv.company}

${inv.description}

${inv.tags.map(t => `${t}`).join('')}
${inv.amount}
投资方:${inv.investors.split('、').map(i => `${i}`).join('、')}
📅 ${inv.date} 📂 ${inv.category}
`; }).join(''); } // ============================================================ // MODULE 7: EVENT HANDLERS & INTERACTIONS // ============================================================ function performSearch() { const input = document.getElementById('heroSearchInput').value.trim(); if (!input) { showToast('请输入您的需求描述'); return; } const query = AIEngine.parseQuery(input); let results; if (AppState.searchMode === 'provider') { results = AIEngine.matchProviders(query); switchTab('providers'); } else { results = AIEngine.matchRequirements(query); switchTab('requirements'); } AppState.searchResults = results; if (AppState.activeTab === 'providers') { renderProviders(results); } else { renderRequirements(results); } document.getElementById('providerMarket').scrollIntoView({ behavior:'smooth', block:'start' }); if (results.length > 0) { showToast(`AI 为您匹配到 ${results.length} 个结果`, 'success'); } else { showToast('未找到匹配结果,请尝试其他关键词'); } } function quickSearch(term) { document.getElementById('heroSearchInput').value = term; performSearch(); } function switchSearchMode(mode) { AppState.searchMode = mode; document.getElementById('modeProvider').classList.toggle('active', mode==='provider'); document.getElementById('modeRequirement').classList.toggle('active', mode==='requirement'); const input = document.getElementById('heroSearchInput'); input.placeholder = mode === 'provider' ? '描述您需要的服务,如:我需要一个能做智能客服的AI团队,预算3万左右...' : '描述您要寻找的需求类型,如:寻找AI客服系统开发项目...'; input.value = ''; } function switchTab(tab) { AppState.activeTab = tab; document.getElementById('tabProviders').classList.toggle('active', tab==='providers'); document.getElementById('tabRequirements').classList.toggle('active', tab==='requirements'); if (tab === 'providers') { document.getElementById('providerGrid').style.display = ''; document.getElementById('requirementGrid').style.display = 'none'; document.getElementById('providerFilters').style.display = ''; document.getElementById('emptyState').style.display = 'none'; renderProviders(platformData.providers); } else { document.getElementById('providerGrid').innerHTML = ''; document.getElementById('providerGrid').style.display = 'none'; document.getElementById('requirementGrid').style.display = 'grid'; document.getElementById('providerFilters').style.display = 'none'; document.getElementById('emptyState').style.display = 'none'; renderRequirements(platformData.requirements); } } function applyFilters() { const cat = document.getElementById('filterCategory').value; const rating = document.getElementById('filterRating').value; const loc = document.getElementById('filterLocation').value; AppState.filters = { category:cat, rating, location:loc }; let results = AppState.searchResults.length > 0 ? [...AppState.searchResults] : [...MOCK_PROVIDERS]; if (cat !== 'all') results = results.filter(p => p.category === cat); if (rating !== 'all') results = results.filter(p => p.rating >= parseFloat(rating)); if (loc !== 'all') results = results.filter(p => p.location === loc); renderProviders(results); } function openPublishModal() { // 1. 检查登录 if (!AuthManager.currentUser) { showToast('请先登录后再发布需求', 'info'); openAuthModal('login'); return; } // 2. 检查认证 const certStatus = AuthManager.getCertStatus(); if (certStatus !== 'approved') { let msg = '发布需求需要完成企业认证'; if (certStatus === 'pending') msg = '您的认证申请正在审核中,请耐心等待'; else if (certStatus === 'none') msg = '发布需求需要先完成企业认证(上传营业执照 + 缴纳保证金)'; else if (certStatus === 'expired') msg = '您的认证已过期,请重新认证后再发布'; showToast(msg, 'error'); openCertCenter('cert'); return; } // 3. 检查保证金 if (!AuthManager.currentUser.depositPaid) { showToast('请先缴纳保证金后再发布需求', 'error'); openCertCenter('cert'); return; } document.getElementById('publishModalOverlay').style.display = 'flex'; wizard.reset(); // 增强:注入AI文件上传和补录 enhancePublishModal(); } function closePublishModal(e) { if (e && e.target !== document.getElementById('publishModalOverlay')) return; document.getElementById('publishModalOverlay').style.display = 'none'; wizard.reset(); uploadedRequirementFiles = []; } function closeDetailModal(e) { if (e && e.target !== e.currentTarget) return; var overlay = document.getElementById('detailModalOverlay'); if (overlay) overlay.style.display = 'none'; document.body.style.overflow = ''; } function toggleMenu() { document.getElementById('navLinks').classList.toggle('open'); } // ============================================================ // MODULE: VERIFICATION CODE (验证码管理) // ============================================================ const VerificationCodeManager = { pending: {}, CODE_LENGTH: 6, CODE_EXPIRY_MS: 5 * 60 * 1000, RESEND_COOLDOWN_SEC: 60, generateCode() { let code = ''; for (let i = 0; i < this.CODE_LENGTH; i++) { code += Math.floor(Math.random() * 10); } return code; }, sendCode(phone, btnId) { if (!this.validatePhone(phone)) { return { success: false, message: '请输入正确的手机号' }; } this.startCountdown(btnId); const code = this.generateCode(); this.pending[phone] = { code: code, expiresAt: Date.now() + this.CODE_EXPIRY_MS }; showToast('【惠捷同城】验证码:' + code + ',5分钟内有效', 'info'); return { success: true, code: code }; }, verifyCode(phone, inputCode) { const record = this.pending[phone]; if (!record) { return { success: false, message: '请先获取验证码' }; } if (Date.now() > record.expiresAt) { delete this.pending[phone]; return { success: false, message: '验证码已过期,请重新获取' }; } if (record.code !== inputCode) { return { success: false, message: '验证码错误' }; } delete this.pending[phone]; return { success: true }; }, startCountdown(btnId) { const btn = document.getElementById(btnId); if (!btn) return; let remaining = this.RESEND_COOLDOWN_SEC; btn.disabled = true; btn.textContent = remaining + 's 后重发'; const timer = setInterval(() => { remaining--; if (remaining <= 0) { clearInterval(timer); btn.disabled = false; btn.textContent = '获取验证码'; } else { btn.textContent = remaining + 's 后重发'; } }, 1000); }, validatePhone(phone) { return /^1[3-9]\d{9}$/.test(phone); } }; // ============================================================ // MODULE: AUTH SYSTEM (登录/注册) // ============================================================ const AuthManager = { users: [], currentUser: null, // 认证配置常量 CERT_DEPOSIT: 10000, CERT_VALID_YEARS: 1, PRODUCT_LIMIT: 10, PUBLISH_TOTAL_LIMIT: 10, EXTRA_PRODUCT_FEE: 1000, init() { const savedUsers = localStorage.getItem('hj_users'); if (savedUsers) { this.users = JSON.parse(savedUsers); // 为旧用户补充认证字段(向后兼容) this.users.forEach(u => this.ensureCertFields(u)); } const savedSession = localStorage.getItem('hj_session'); const remembered = localStorage.getItem('hj_remember'); if (savedSession) { const user = this.users.find(u => u.id === savedSession); if (user) { this.checkCertExpiry(user); this.currentUser = user; this.updateNavUI(); } } else if (remembered) { const sessionUser = sessionStorage.getItem('hj_session'); if (sessionUser) { const user = this.users.find(u => u.id === sessionUser); if (user) { this.checkCertExpiry(user); this.currentUser = user; this.updateNavUI(); } } } }, // 确保用户对象有完整的认证字段 ensureCertFields(u) { if (u.certStatus === undefined) u.certStatus = 'none'; if (u.certAppliedAt === undefined) u.certAppliedAt = null; if (u.certApprovedAt === undefined) u.certApprovedAt = null; // 动态计算到期日期(certApprovedAt + 有效期),覆盖旧缓存 if (u.certStatus === 'approved' && u.certApprovedAt) { var exp = new Date(u.certApprovedAt); exp.setFullYear(exp.getFullYear() + this.CERT_VALID_YEARS); u.certExpiresAt = exp.toISOString(); } if (u.certExpiresAt === undefined) u.certExpiresAt = null; if (u.businessLicense === undefined) u.businessLicense = null; if (u.depositPaid === undefined) u.depositPaid = false; if (u.depositPaidAt === undefined) u.depositPaidAt = null; if (u.depositAmount === undefined) u.depositAmount = this.CERT_DEPOSIT; if (u.paymentMethod === undefined) u.paymentMethod = 'bank'; if (u.products === undefined) u.products = []; if (u.productLimit === undefined) u.productLimit = this.PRODUCT_LIMIT; if (u.extraProductFees === undefined) u.extraProductFees = 0; if (u.licenseUploaded === undefined) u.licenseUploaded = false; if (u.paymentVoucher === undefined) u.paymentVoucher = null; if (u.paymentVoucherUploaded === undefined) u.paymentVoucherUploaded = false; return u; }, saveUsers() { localStorage.setItem('hj_users', JSON.stringify(this.users)); }, saveCurrentUser() { if (this.currentUser) { const idx = this.users.findIndex(u => u.id === this.currentUser.id); if (idx >= 0) { this.users[idx] = this.currentUser; this.saveUsers(); } // 同步到数据库API this.syncUserToApi(); } }, // 从API数据构建本地用户对象 buildLocalUser: function (apiUser, extraFields) { extraFields = extraFields || {}; var user = { id: apiUser.id, name: apiUser.realName || apiUser.real_name || extraFields.name || '', nick: extraFields.nick || '', account: apiUser.username || apiUser.phone || extraFields.account || '', password: '', avatar: (apiUser.realName || extraFields.name || 'U').charAt(0).toUpperCase(), createdAt: apiUser.createdAt || extraFields.createdAt || new Date().toISOString(), role: apiUser.role || 'user', certStatus: apiUser.certStatus || 'none', certAppliedAt: null, certApprovedAt: null, certExpiresAt: null, businessLicense: null, depositPaid: false, depositPaidAt: null, depositAmount: this.CERT_DEPOSIT, paymentMethod: 'bank', products: [], productLimit: this.PRODUCT_LIMIT, extraProductFees: 0, licenseUploaded: false, paymentVoucher: null, paymentVoucherUploaded: false }; // 解析products if (apiUser.products) { try { user.products = typeof apiUser.products === 'string' ? JSON.parse(apiUser.products) : apiUser.products; } catch (e) {} } if (extraFields.products) { user.products = extraFields.products; } // 解析certInfo var ci = null; if (apiUser.certInfo) { try { ci = typeof apiUser.certInfo === 'string' ? JSON.parse(apiUser.certInfo) : apiUser.certInfo; } catch (e) {} } if (extraFields.certInfo) { ci = extraFields.certInfo; } if (ci) { if (ci.certAppliedAt) user.certAppliedAt = ci.certAppliedAt; if (ci.certApprovedAt) user.certApprovedAt = ci.certApprovedAt; if (ci.certExpiresAt) user.certExpiresAt = ci.certExpiresAt; if (ci.businessLicense !== undefined) user.businessLicense = ci.businessLicense; if (ci.depositPaid !== undefined) user.depositPaid = ci.depositPaid; if (ci.depositPaidAt) user.depositPaidAt = ci.depositPaidAt; if (ci.depositAmount !== undefined) user.depositAmount = ci.depositAmount; if (ci.paymentMethod) user.paymentMethod = ci.paymentMethod; if (ci.licenseUploaded !== undefined) user.licenseUploaded = ci.licenseUploaded; if (ci.paymentVoucher !== undefined) user.paymentVoucher = ci.paymentVoucher; if (ci.paymentVoucherUploaded !== undefined) user.paymentVoucherUploaded = ci.paymentVoucherUploaded; } // 覆盖extraFields中的值 Object.keys(extraFields).forEach(function (k) { if (user.hasOwnProperty(k) && extraFields[k] !== undefined && extraFields[k] !== null) { user[k] = extraFields[k]; } }); return user; }, // 从API登录成功后设置当前用户 loginFromApi: function (apiUser, remember) { var user = this.buildLocalUser(apiUser, {}); // 更新或添加到本地用户列表 var existingIdx = this.users.findIndex(function (u) { return u.id === user.id || u.account === user.account; }); if (existingIdx >= 0) { user.password = this.users[existingIdx].password; // 保留本地密码字段 this.users[existingIdx] = user; } else { this.users.push(user); } this.saveUsers(); this.setCurrentUser(user, remember); return user; }, // 将用户在API注册成功后保存到本地 registerFromApi: function (apiUser, name, nick, account) { var user = this.buildLocalUser(apiUser, { name: name, nick: nick, account: account }); this.users.push(user); this.saveUsers(); this.setCurrentUser(user, true); return user; }, // 同步用户认证信息到数据库 syncUserToApi: function () { if (!this.currentUser || !this.currentUser.id) return; if (typeof window.apiSaveUser !== 'function') return; var u = this.currentUser; window.apiSaveUser({ id: u.id, certStatus: u.certStatus, certInfo: { certAppliedAt: u.certAppliedAt, certApprovedAt: u.certApprovedAt, certExpiresAt: u.certExpiresAt, businessLicense: u.businessLicense, depositPaid: u.depositPaid, depositPaidAt: u.depositPaidAt, depositAmount: u.depositAmount, paymentMethod: u.paymentMethod, licenseUploaded: u.licenseUploaded, paymentVoucher: u.paymentVoucher, paymentVoucherUploaded: u.paymentVoucherUploaded }, products: u.products, realName: u.name, phone: u.account }); }, // 从数据库加载用户列表(后台调用) loadUsersFromApi: function () { if (typeof window.apiListUsers !== 'function') return; var self = this; window.apiCall({ action: 'get_users', method: 'GET' }, function (res) { if (res.code === 200 && res.data && res.data.length) { res.data.forEach(function (apiUser) { // 不在本地用户列表中的才添加 if (!self.users.some(function (u) { return u.id === apiUser.id; })) { var localUser = self.buildLocalUser(apiUser, {}); localUser.password = ''; self.users.push(localUser); } }); self.saveUsers(); } }); }, register(name, company, account, password) { if (this.users.some(u => u.account === account)) { return { success: false, message: '该手机号已被注册' }; } const user = this.ensureCertFields({ id: 'u_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8), name: name, nick: company, account: account, password: password, avatar: name.charAt(0).toUpperCase(), createdAt: new Date().toISOString(), role: 'user' }); this.users.push(user); this.saveUsers(); return { success: true, user: user }; }, login(account, password, remember) { const user = this.users.find(u => u.account === account); if (!user) { return { success: false, message: '账号不存在,请先注册' }; } if (user.password !== password) { return { success: false, message: '密码错误,请重试' }; } this.checkCertExpiry(user); this.currentUser = user; if (remember) { localStorage.setItem('hj_remember', '1'); localStorage.setItem('hj_session', user.id); } else { sessionStorage.setItem('hj_session', user.id); } this.updateNavUI(); return { success: true, user: user }; }, loginWithCode(phone, code, remember) { const user = this.users.find(u => u.account === phone); if (!user) { return { success: false, message: '该手机号未注册,请先注册' }; } const result = VerificationCodeManager.verifyCode(phone, code); if (!result.success) { return { success: false, message: result.message }; } this.checkCertExpiry(user); this.currentUser = user; if (remember) { localStorage.setItem('hj_remember', '1'); localStorage.setItem('hj_session', user.id); } else { sessionStorage.setItem('hj_session', user.id); } this.updateNavUI(); return { success: true, user: user }; }, logout() { this.currentUser = null; localStorage.removeItem('hj_session'); localStorage.removeItem('hj_remember'); sessionStorage.removeItem('hj_session'); this.updateNavUI(); }, // ========== 认证方法 ========== uploadLicense(fileName) { if (!this.currentUser) return { success: false, message: '请先登录' }; this.currentUser.licenseUploaded = true; this.currentUser.businessLicense = fileName || '营业执照.jpg'; this.saveCurrentUser(); return { success: true, message: '营业执照已上传' }; }, deleteLicense() { if (!this.currentUser) return { success: false, message: '请先登录' }; this.currentUser.licenseUploaded = false; this.currentUser.businessLicense = null; // 清除依赖执照的后续状态 this.currentUser.paymentVoucherUploaded = false; this.currentUser.paymentVoucher = null; this.currentUser.depositPaid = false; this.currentUser.depositPaidAt = null; this.currentUser.paymentMethod = 'bank'; this.saveCurrentUser(); return { success: true, message: '营业执照已删除,请重新上传' }; }, uploadPaymentVoucher(fileName) { if (!this.currentUser) return { success: false, message: '请先登录' }; if (!this.currentUser.licenseUploaded) return { success: false, message: '请先上传营业执照' }; this.currentUser.paymentVoucherUploaded = true; this.currentUser.paymentVoucher = fileName || '汇款凭证.jpg'; this.currentUser.depositPaid = true; this.currentUser.depositPaidAt = new Date().toISOString(); this.saveCurrentUser(); return { success: true, message: '汇款凭证已上传,保证金确认缴纳' }; }, payDeposit() { if (!this.currentUser) return { success: false, message: '请先登录' }; if (!this.currentUser.licenseUploaded) return { success: false, message: '请先上传营业执照' }; if (!this.currentUser.paymentVoucherUploaded) return { success: false, message: '请先上传汇款凭证' }; this.currentUser.depositPaid = true; this.currentUser.depositPaidAt = new Date().toISOString(); this.currentUser.paymentMethod = 'bank'; this.saveCurrentUser(); return { success: true, message: '保证金缴纳成功' }; }, payDepositWechat() { if (!this.currentUser) return { success: false, message: '请先登录' }; if (!this.currentUser.licenseUploaded) return { success: false, message: '请先上传营业执照' }; this.currentUser.depositPaid = true; this.currentUser.depositPaidAt = new Date().toISOString(); this.currentUser.paymentMethod = 'wechat'; this.saveCurrentUser(); return { success: true, message: '微信支付成功,保证金已缴纳' }; }, submitCertification() { if (!this.currentUser) return { success: false, message: '请先登录' }; if (!this.currentUser.licenseUploaded) return { success: false, message: '请先上传营业执照' }; if (!this.currentUser.depositPaid) return { success: false, message: '请先缴纳保证金' }; this.currentUser.certStatus = 'pending'; this.currentUser.certAppliedAt = new Date().toISOString(); this.saveCurrentUser(); // 模拟审核:3秒后自动通过 setTimeout(() => this.approveCertification(), 3000); return { success: true, message: '认证申请已提交,等待审核' }; }, approveCertification() { if (!this.currentUser || this.currentUser.certStatus !== 'pending') return; const now = new Date(); const expiry = new Date(now); expiry.setFullYear(expiry.getFullYear() + this.CERT_VALID_YEARS); this.currentUser.certStatus = 'approved'; this.currentUser.certApprovedAt = now.toISOString(); this.currentUser.certExpiresAt = expiry.toISOString(); this.currentUser.certNo = 'HJ-CERT-' + now.getFullYear() + '-' + String(Date.now()).slice(-6); this.saveCurrentUser(); this.updateNavUI(); showToast('恭喜!企业认证已通过', 'success'); }, getCertExpiryDate(user) { if (!user || !user.certApprovedAt) return null; var d = new Date(user.certApprovedAt); d.setFullYear(d.getFullYear() + this.CERT_VALID_YEARS); return d; }, checkCertExpiry(user) { if (!user || user.certStatus !== 'approved') return; var exp = this.getCertExpiryDate(user); if (exp && exp < new Date()) { user.certStatus = 'expired'; } }, getCertStatus() { if (!this.currentUser) return 'none'; this.checkCertExpiry(this.currentUser); return this.currentUser.certStatus || 'none'; }, getCertRemainDays() { if (!this.currentUser || !this.currentUser.certApprovedAt) return 0; const exp = this.getCertExpiryDate(this.currentUser); if (!exp) return 0; const diff = exp - new Date(); return Math.max(0, Math.ceil(diff / (1000 * 60 * 60 * 24))); }, // ========== 产品管理方法 ========== getProductCount() { if (!this.currentUser) return 0; return (this.currentUser.products || []).length; }, getTotalPublishCount() { if (!this.currentUser) return 0; const userName = this.currentUser.nick || this.currentUser.name || ''; const productCount = (this.currentUser.products || []).length; const datasetCount = (platformData.datasets || []).filter(d => d.postedBy === userName || d.postedBy === this.currentUser.name ).length; const opcCount = (platformData.opc || []).filter(d => d.postedBy === userName || d.postedBy === this.currentUser.name ).length; return productCount + datasetCount + opcCount; }, getExtraProductCount() { const count = this.getProductCount(); return Math.max(0, count - this.PRODUCT_LIMIT); }, getExtraProductFee() { return this.getExtraProductCount() * this.EXTRA_PRODUCT_FEE; }, addProduct(name, category, intro, scenario, priceType, price) { if (!this.currentUser) return { success: false, message: '请先登录' }; if (this.getCertStatus() !== 'approved') return { success: false, message: '请先完成企业认证' }; const count = this.getProductCount(); if (count >= this.PRODUCT_LIMIT) { // 超出额度,需要缴纳额外费用 this.currentUser.extraProductFees += this.EXTRA_PRODUCT_FEE; } const product = { id: 'prod_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6), name: name, category: category, intro: intro, scenario: scenario, priceType: priceType || 'negotiable', price: priceType === 'custom' ? price : '', createdAt: new Date().toISOString() }; if (!this.currentUser.products) this.currentUser.products = []; this.currentUser.products.push(product); this.saveCurrentUser(); return { success: true, message: '产品发布成功', product: product }; }, removeProduct(productId) { if (!this.currentUser || !this.currentUser.products) return { success: false, message: '操作失败' }; const idx = this.currentUser.products.findIndex(p => p.id === productId); if (idx < 0) return { success: false, message: '产品不存在' }; // 如果删除的是额外产品,退还额外费用 if (this.getExtraProductCount() > 0) { this.currentUser.extraProductFees = Math.max(0, this.currentUser.extraProductFees - this.EXTRA_PRODUCT_FEE); } this.currentUser.products.splice(idx, 1); this.saveCurrentUser(); return { success: true, message: '产品已删除' }; }, updateNavUI() { const btn = document.getElementById('navAuthBtn'); const badge = document.getElementById('navUserBadge'); const avatar = document.getElementById('navUserAvatar'); const name = document.getElementById('navUserName'); const certIcon = document.getElementById('navCertIcon'); if (this.currentUser) { btn.style.display = 'none'; badge.classList.add('show'); avatar.textContent = this.currentUser.avatar; name.textContent = this.currentUser.name || this.currentUser.nick; // 认证状态标识 if (certIcon) { const status = this.getCertStatus(); if (status === 'approved') { certIcon.style.display = 'inline-flex'; certIcon.title = '已认证企业'; } else { certIcon.style.display = 'none'; } } } else { btn.style.display = ''; badge.classList.remove('show'); if (certIcon) certIcon.style.display = 'none'; } } }; function openAuthModal(tab) { document.getElementById('authModalOverlay').style.display = 'flex'; switchAuthTab(tab || 'login'); // 清空错误 document.querySelectorAll('.auth-error').forEach(e => e.classList.remove('show')); document.querySelectorAll('.auth-input-error').forEach(e => e.classList.remove('auth-input-error')); } function closeAuthModal(e) { // 如果是从 overlay 点击触发,只响应点击 overlay 本身(不响应点击内部 modal) if (e && e.target !== e.currentTarget) return; document.getElementById('authModalOverlay').style.display = 'none'; } function switchAuthTab(tab) { const loginTab = document.getElementById('tabLogin'); const regTab = document.getElementById('tabRegister'); const loginForm = document.getElementById('loginForm'); const regForm = document.getElementById('registerForm'); const title = document.getElementById('authModalTitle'); const switchText = document.getElementById('authSwitchText'); // 清空错误 document.querySelectorAll('.auth-error').forEach(e => e.classList.remove('show')); document.querySelectorAll('.auth-input-error').forEach(e => e.classList.remove('auth-input-error')); if (tab === 'login') { loginTab.classList.add('active'); regTab.classList.remove('active'); loginForm.classList.add('active'); regForm.classList.remove('active'); title.textContent = '登录'; switchText.innerHTML = '还没有账号?立即注册'; } else { loginTab.classList.remove('active'); regTab.classList.add('active'); loginForm.classList.remove('active'); regForm.classList.add('active'); title.textContent = '注册'; switchText.innerHTML = '已有账号?去登录'; } if (tab === 'login') { switchLoginMode('password'); } } function switchLoginMode(mode) { const tabPwd = document.getElementById('loginTabPwd'); const tabCode = document.getElementById('loginTabCode'); const pwdFields = document.getElementById('loginPwdFields'); const codeFields = document.getElementById('loginCodeFields'); document.querySelectorAll('.auth-error').forEach(e => e.classList.remove('show')); document.querySelectorAll('.auth-input-error').forEach(e => e.classList.remove('auth-input-error')); if (mode === 'password') { tabPwd.classList.add('active'); tabCode.classList.remove('active'); pwdFields.style.display = ''; codeFields.style.display = 'none'; } else { tabPwd.classList.remove('active'); tabCode.classList.add('active'); pwdFields.style.display = 'none'; codeFields.style.display = ''; } } function sendRegCode() { const phone = document.getElementById('regAccount').value.trim(); clearFieldError('regAccount', 'regAccountError'); if (!phone) { showFieldError('regAccount', 'regAccountError', '请输入手机号'); return; } if (!VerificationCodeManager.validatePhone(phone)) { showFieldError('regAccount', 'regAccountError', '请输入正确的手机号'); return; } if (AuthManager.users.some(u => u.account === phone)) { showFieldError('regAccount', 'regAccountError', '该手机号已被注册'); return; } VerificationCodeManager.sendCode(phone, 'regCodeBtn'); } function sendLoginCode() { const phone = document.getElementById('loginAccount').value.trim(); clearFieldError('loginAccount', 'loginAccountError'); if (!phone) { showFieldError('loginAccount', 'loginAccountError', '请输入手机号'); return; } if (!VerificationCodeManager.validatePhone(phone)) { showFieldError('loginAccount', 'loginAccountError', '请输入正确的手机号'); return; } if (!AuthManager.users.some(u => u.account === phone)) { showFieldError('loginAccount', 'loginAccountError', '该手机号未注册'); return; } VerificationCodeManager.sendCode(phone, 'loginCodeBtn'); } function togglePwd(inputId, el) { const input = document.getElementById(inputId); if (input.type === 'password') { input.type = 'text'; el.textContent = '🙈'; } else { input.type = 'password'; el.textContent = '👁'; } } function checkPwdStrength(pwd) { const bar = document.getElementById('pwdStrengthBar'); if (!pwd) { bar.style.width = '0'; bar.style.background = 'var(--gray-200)'; return; } let score = 0; if (pwd.length >= 6) score++; if (pwd.length >= 10) score++; if (/[A-Z]/.test(pwd) && /[a-z]/.test(pwd)) score++; if (/\d/.test(pwd)) score++; if (/[^A-Za-z0-9]/.test(pwd)) score++; const levels = [ { w: '20%', c: '#ef4444' }, // 弱 { w: '40%', c: '#f59e0b' }, // 一般 { w: '60%', c: '#eab308' }, // 中等 { w: '80%', c: '#84cc16' }, // 良好 { w: '100%', c: '#22c55e' } // 强 ]; const lv = levels[Math.min(score, 5) - 1] || levels[0]; bar.style.width = lv.w; bar.style.background = lv.c; } function showFieldError(fieldId, errorId, msg) { document.getElementById(fieldId).classList.add('auth-input-error'); const err = document.getElementById(errorId); err.textContent = msg; err.classList.add('show'); } function clearFieldError(fieldId, errorId) { document.getElementById(fieldId).classList.remove('auth-input-error'); document.getElementById(errorId).classList.remove('show'); } function validateAccount(account) { return VerificationCodeManager.validatePhone(account); } function handleLogin(e) { if (e) e.preventDefault(); const btn = document.getElementById('btnLoginSubmit'); const account = document.getElementById('loginAccount').value.trim(); const remember = document.getElementById('rememberMe').checked || document.getElementById('rememberMeCode').checked; const isCodeMode = document.getElementById('loginTabCode').classList.contains('active'); let valid = true; clearFieldError('loginAccount', 'loginAccountError'); if (!account) { showFieldError('loginAccount', 'loginAccountError', '请输入手机号'); valid = false; } else if (!validateAccount(account)) { showFieldError('loginAccount', 'loginAccountError', '请输入正确的手机号'); valid = false; } if (!valid) return; if (isCodeMode) { const code = document.getElementById('loginCode').value.trim(); clearFieldError('loginCode', 'loginCodeError'); if (!code) { showFieldError('loginCode', 'loginCodeError', '请输入验证码'); valid = false; } if (!valid) return; btn.disabled = true; btn.textContent = '登录中...'; btn.style.opacity = '0.7'; setTimeout(() => { const result = AuthManager.loginWithCode(account, code, remember); btn.disabled = false; btn.textContent = '登 录'; btn.style.opacity = '1'; if (result.success) { closeAuthModal(); showToast('欢迎回来,' + (result.user.name || result.user.nick) + '!', 'success'); document.getElementById('loginForm').reset(); } else { showFieldError('loginCode', 'loginCodeError', result.message); } }, 300); } else { const password = document.getElementById('loginPassword').value; clearFieldError('loginPassword', 'loginPasswordError'); if (!password) { showFieldError('loginPassword', 'loginPasswordError', '请输入密码'); valid = false; } if (!valid) return; btn.disabled = true; btn.textContent = '登录中...'; btn.style.opacity = '0.7'; window.apiAuth({ type: 'login', username: account, password: password }, function (res) { var user = AuthManager.loginFromApi(res.data, remember); btn.disabled = false; btn.textContent = '登 录'; btn.style.opacity = '1'; closeAuthModal(); showToast('欢迎回来,' + (user.name || user.nick || account) + '!', 'success'); document.getElementById('loginForm').reset(); }, function (err) { // API 失败时回退到本地登录 var result = AuthManager.login(account, password, remember); btn.disabled = false; btn.textContent = '登 录'; btn.style.opacity = '1'; if (result.success) { closeAuthModal(); showToast('欢迎回来,' + (result.user.name || result.user.nick) + '!', 'success'); document.getElementById('loginForm').reset(); } else { showFieldError('loginPassword', 'loginPasswordError', (err && err.message) || result.message || '登录失败'); } } ); } } function handleRegister(e) { if (e) e.preventDefault(); const btn = document.getElementById('btnRegisterSubmit'); const name = document.getElementById('regName').value.trim(); const nick = document.getElementById('regNick').value.trim(); const account = document.getElementById('regAccount').value.trim(); const code = document.getElementById('regCode').value.trim(); const password = document.getElementById('regPassword').value; const password2 = document.getElementById('regPassword2').value; const agree = document.getElementById('agreeTerms').checked; let valid = true; clearFieldError('regName', 'regNameError'); clearFieldError('regNick', 'regNickError'); clearFieldError('regAccount', 'regAccountError'); clearFieldError('regCode', 'regCodeError'); clearFieldError('regPassword', 'regPasswordError'); clearFieldError('regPassword2', 'regPassword2Error'); if (!name) { showFieldError('regName', 'regNameError', '请输入姓名'); valid = false; } else if (name.length < 2) { showFieldError('regName', 'regNameError', '姓名至少2个字符'); valid = false; } if (!nick) { showFieldError('regNick', 'regNickError', '请输入公司名称'); valid = false; } else if (nick.length < 2) { showFieldError('regNick', 'regNickError', '公司名称至少2个字符'); valid = false; } if (!account) { showFieldError('regAccount', 'regAccountError', '请输入手机号'); valid = false; } else if (!validateAccount(account)) { showFieldError('regAccount', 'regAccountError', '请输入正确的手机号'); valid = false; } if (!code) { showFieldError('regCode', 'regCodeError', '请输入验证码'); valid = false; } if (!password) { showFieldError('regPassword', 'regPasswordError', '请设置密码'); valid = false; } else if (password.length < 6) { showFieldError('regPassword', 'regPasswordError', '密码至少6位'); valid = false; } if (password !== password2) { showFieldError('regPassword2', 'regPassword2Error', '两次密码不一致'); valid = false; } if (!agree) { showToast('请先同意用户协议和隐私政策', 'error'); valid = false; } if (!valid) return; const codeResult = VerificationCodeManager.verifyCode(account, code); if (!codeResult.success) { showFieldError('regCode', 'regCodeError', codeResult.message); return; } btn.disabled = true; btn.textContent = '注册中...'; btn.style.opacity = '0.7'; setTimeout(() => { // 尝试API注册 window.apiAuth({ type: 'register', username: account, password: password, realName: name, phone: account, email: '' }, function (res) { // API注册成功 AuthManager.registerFromApi(res.data, name, nick, account); btn.disabled = false; btn.textContent = '注 册'; btn.style.opacity = '1'; closeAuthModal(); showToast('注册成功,欢迎加入惠捷同城!', 'success'); document.getElementById('registerForm').reset(); document.getElementById('pwdStrengthBar').style.width = '0'; }, function (err) { // API失败,回退到本地注册 var result = AuthManager.register(name, nick, account, password); if (result.success) { AuthManager.login(account, password, true); btn.disabled = false; btn.textContent = '注 册'; btn.style.opacity = '1'; closeAuthModal(); showToast('注册成功,欢迎加入惠捷同城!', 'success'); document.getElementById('registerForm').reset(); document.getElementById('pwdStrengthBar').style.width = '0'; } else { btn.disabled = false; btn.textContent = '注 册'; btn.style.opacity = '1'; showFieldError('regAccount', 'regAccountError', result.message || ((err && err.message) || '注册失败')); } } ); }, 300); } function handleLogout() { AuthManager.logout(); document.getElementById('userDropdown').classList.remove('show'); showToast('已安全退出登录', 'info'); } function toggleUserDropdown(e) { e.stopPropagation(); document.getElementById('userDropdown').classList.toggle('show'); } function socialLogin(platform) { showToast(platform + '登录功能开发中,请使用账号密码登录', 'info'); } // ============================================================ // 认证中心 // ============================================================ function openCertCenter(initialTab) { if (!AuthManager.currentUser) { showToast('请先登录', 'info'); openAuthModal('login'); return; } document.getElementById('userDropdown').classList.remove('show'); document.getElementById('certModalOverlay').style.display = 'flex'; switchCertTab(initialTab || 'profile'); } function closeCertCenter(e) { if (e && e.target !== e.currentTarget) return; document.getElementById('certModalOverlay').style.display = 'none'; } function switchCertTab(tab) { document.querySelectorAll('.cert-tab').forEach(t => t.classList.remove('active')); document.querySelectorAll('.cert-tab-content').forEach(c => c.classList.remove('active')); if (tab === 'profile') { document.getElementById('certTabProfile').classList.add('active'); document.getElementById('certContentProfile').classList.add('active'); renderCertProfile(); } else if (tab === 'cert') { document.getElementById('certTabCert').classList.add('active'); document.getElementById('certContentCert').classList.add('active'); renderCertBody(); } else if (tab === 'product') { document.getElementById('certTabProduct').classList.add('active'); document.getElementById('certContentProduct').classList.add('active'); renderCertProducts(); } else if (tab === 'requirements') { document.getElementById('certTabRequirements').classList.add('active'); document.getElementById('certContentRequirements').classList.add('active'); renderCertRequirements(); } else if (tab === 'publish') { document.getElementById('certTabPublish').classList.add('active'); document.getElementById('certContentPublish').classList.add('active'); renderCertPublish(); } } function getCertStatusBadge(status) { const map = { 'none': '未认证', 'pending': '⏳ 审核中', 'approved': '✓ 已认证', 'expired': '已过期' }; return map[status] || map['none']; } function renderCertProfile() { const u = AuthManager.currentUser; if (!u) return; const status = AuthManager.getCertStatus(); const remainDays = AuthManager.getCertRemainDays(); document.getElementById('certProfileBody').innerHTML = `
姓名
${u.name || '-'}
公司名称
${u.nick || '-'}
登录账号
${u.account || '-'}
注册时间
${u.createdAt ? new Date(u.createdAt).toLocaleDateString('zh-CN') : '-'}
认证状态
${getCertStatusBadge(status)}
发布数量
${AuthManager.getTotalPublishCount()} / ${AuthManager.PUBLISH_TOTAL_LIMIT}
${status === 'approved' ? `
认证编号
${u.certNo || '-'}
到期日期
${u.certExpiresAt ? new Date(u.certExpiresAt).toLocaleDateString('zh-CN') : '-'}(剩余${remainDays}天)
` : ''}
${status === 'none' || status === 'expired' ? '' : ''} `; } function renderCertBody() { const u = AuthManager.currentUser; if (!u) return; const status = AuthManager.getCertStatus(); let html = ''; if (status === 'none' || status === 'expired') { const licenseOk = u.licenseUploaded; const voucherOk = u.paymentVoucherUploaded; const depositOk = u.depositPaid; html = `

📋 企业认证说明

  • 上传公司营业执照进行企业实名认证
  • 缴纳 ¥${AuthManager.CERT_DEPOSIT} 保证金(有效期 ${AuthManager.CERT_VALID_YEARS} 年),支持银行对公转账或微信在线支付
  • 认证后可发布 ${AuthManager.PUBLISH_TOTAL_LIMIT} 项内容(产品方案/数据集/OPC共享额度)
  • 认证有效期到期后需重新认证
${licenseOk ? '✓' : '1'}
上传营业执照
请上传贵公司最新的营业执照照片或扫描件
${licenseOk ? `
📄 ${u.businessLicense || '营业执照.jpg'} 已上传
` : `
📎
点击上传营业执照(jpg/png/pdf)
` }
${depositOk ? '✓' : '2'}
缴纳保证金
选择支付方式缴纳 ¥${AuthManager.CERT_DEPOSIT} 保证金
${!licenseOk ? '
⚠️ 请先完成步骤1:上传营业执照
' : ''} ${depositOk ? `
✅ 保证金 ¥${u.depositAmount} 已缴纳(${u.paymentMethod === 'wechat' ? '微信支付' : '银行转账'})
` : licenseOk ? `
🏦
对公转账
银行汇款 + 上传凭证
💬
微信支付
在线支付,即时到账
${u.paymentMethod === 'wechat' ? `
💬 微信支付保证金
¥${AuthManager.CERT_DEPOSIT}.00
点击下方按钮,使用微信扫码完成支付
` : `
🏦 平台对公账户
账户名称惠捷同城(内蒙古)科技有限公司
账户号码471904095610006
开户银行招商银行股份有限公司呼和浩特新华广场支行
汇款金额¥${AuthManager.CERT_DEPOSIT}.00
${voucherOk ? `
📄 ${u.paymentVoucher || '汇款凭证.jpg'} 已上传
` : `
📎
上传汇款凭证(转账截图 / 回单)
支持 jpg/png/pdf,汇款完成后请上传
` }` }` : '' }
${status === 'pending' || status === 'approved' ? '✓' : '3'}
提交审核
提交后平台将在1-3个工作日内完成审核
${status === 'pending' ? '
⏳ 审核中,请耐心等待...
' : status === 'approved' ? '
✓ 认证已通过
' : `` }
`; html += status === 'expired' ? '
⚠️ 您的认证已过期,请重新完成认证流程
' : ''; } else if (status === 'pending') { html = `

认证审核中

您的认证申请已提交,平台正在审核中

预计1-3个工作日内完成审核

营业执照
📄 ${u.businessLicense || '已上传'}
保证金
✓ ¥${u.depositAmount} 已缴纳
汇款凭证
📄 ${u.paymentVoucher || '已上传'}
申请时间
${u.certAppliedAt ? new Date(u.certAppliedAt).toLocaleString('zh-CN') : '-'}
`; } else if (status === 'approved') { const remainDays = AuthManager.getCertRemainDays(); html = `

企业认证已通过

贵公司已完成企业实名认证

认证编号
${u.certNo || '-'}
保证金
¥${u.depositAmount} 已缴纳
汇款凭证
📄 ${u.paymentVoucher || '已上传'}
通过日期
${u.certApprovedAt ? new Date(u.certApprovedAt).toLocaleDateString('zh-CN') : '-'}
到期日期
${u.certExpiresAt ? new Date(u.certExpiresAt).toLocaleDateString('zh-CN') : '-'}
营业执照
📄 ${u.businessLicense || '已上传'}
剩余有效期
${remainDays} 天
${remainDays < 90 ? '
⚠️ 认证即将到期,请及时续期
' : ''} `; } document.getElementById('certBody').innerHTML = html; } function simulateUploadLicense() { // 模拟文件上传 const fakeNames = ['营业执照.jpg', '营业执照_2026.pdf', 'business_license.png', '工商执照.jpg']; const fileName = fakeNames[Math.floor(Math.random() * fakeNames.length)]; const result = AuthManager.uploadLicense(fileName); if (result.success) { showToast('营业执照上传成功', 'success'); renderCertBody(); } } function handleDeleteLicense() { if (!confirm('确定要删除已上传的营业执照吗?删除后需重新上传。')) return; const result = AuthManager.deleteLicense(); if (result.success) { showToast(result.message, 'success'); renderCertBody(); } } function handleReuploadLicense() { if (!confirm('确定要修正营业执照吗?修正后将更新为新的执照文件。')) return; // 修正执照:仅更新执照文件,不影响已有的凭证和保证金 simulateUploadLicense(); } function simulateUploadVoucher() { const fakeNames = ['汇款回单.png', '转账凭证.jpg', '银行回执.pdf', '汇款截图.png']; const fileName = fakeNames[Math.floor(Math.random() * fakeNames.length)]; const result = AuthManager.uploadPaymentVoucher(fileName); if (result.success) { showToast('汇款凭证上传成功', 'success'); renderCertBody(); } } function handleReuploadVoucher() { if (!confirm('确定要修正汇款凭证吗?修正后将更新为新的凭证文件。')) return; // 修正凭证:仅更新凭证文件,不影响其他状态 simulateUploadVoucher(); } function handlePayDeposit() { const result = AuthManager.payDeposit(); if (result.success) { showToast('保证金 ¥' + AuthManager.CERT_DEPOSIT + ' 缴纳成功', 'success'); renderCertBody(); } else { showToast(result.message, 'error'); } } // ============================================================ // 微信支付功能 // ============================================================ function switchPayMethod(method) { if (!AuthManager.currentUser) return; AuthManager.currentUser.paymentMethod = method; AuthManager.saveCurrentUser(); renderCertBody(); } function showWechatPayModal() { const overlay = document.getElementById('wechatPayOverlay'); const amountEl = document.getElementById('wechatPayAmount'); const statusEl = document.getElementById('wechatPayStatus'); const footerEl = document.getElementById('wechatPayFooter'); amountEl.textContent = '¥' + AuthManager.CERT_DEPOSIT + '.00'; statusEl.className = 'wechat-pay-modal__status wechat-pay-modal__status--waiting'; statusEl.innerHTML = '请使用微信扫码支付'; footerEl.style.display = 'none'; drawWechatQrCode(); overlay.classList.add('show'); callWechatPayAPI(AuthManager.CERT_DEPOSIT, AuthManager.currentUser.id); } function closeWechatPayModal(event) { if (event && event.target !== event.currentTarget) return; document.getElementById('wechatPayOverlay').classList.remove('show'); } function drawWechatQrCode() { const canvas = document.getElementById('wechatPayQrCanvas'); if (!canvas) return; const ctx = canvas.getContext('2d'); const size = 180; const cellSize = 5; const modules = size / cellSize; ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, size, size); // 模拟二维码图案(非真实二维码,仅用于展示) const seed = Date.now(); for (let y = 0; y < modules; y++) { for (let x = 0; x < modules; x++) { if (isQrPattern(x, y, modules, seed)) { ctx.fillStyle = '#000'; ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); } } } // 中心微信logo ctx.fillStyle = '#07c160'; ctx.fillRect(size/2 - 18, size/2 - 18, 36, 36); ctx.fillStyle = '#fff'; ctx.font = '20px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('微信', size/2, size/2 + 1); } function isQrPattern(x, y, modules, seed) { // 三个定位角 if (x < 7 && y < 7) return isFinderPattern(x, y); if (x >= modules - 7 && y < 7) return isFinderPattern(x - (modules - 7), y); if (x < 7 && y >= modules - 7) return isFinderPattern(x, y - (modules - 7)); // 随机填充(使用seed保持一致性) const h = (x * 31 + y * 37 + seed % 1000) % 7; return h < 3; } function isFinderPattern(x, y) { if (x === 0 || x === 6 || y === 0 || y === 6) return true; if (x >= 2 && x <= 4 && y >= 2 && y <= 4) return true; return false; } /** * 微信支付API调用(预留接口) * 后期接入真实支付API时,替换此函数实现 * @param {number} amount - 支付金额(元) * @param {string} userId - 用户ID * @returns {Promise} 支付结果 */ function callWechatPayAPI(amount, userId) { // ====== 当前:模拟模式 ====== // 模拟支付流程:3秒后显示"模拟完成"按钮 console.log('[微信支付] 模拟模式 - 金额:', amount, '用户ID:', userId); setTimeout(function() { var footer = document.getElementById('wechatPayFooter'); if (footer) footer.style.display = 'block'; }, 3000); // ====== 后期:真实API模式 ====== // 步骤1:后端创建预支付订单 // fetch('/api/wechat-pay/create-order', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ amount: amount, userId: userId, description: '企业认证保证金' }) // }) // .then(res => res.json()) // .then(data => { // if (data.codeUrl) { // // 用真实二维码替换canvas // drawRealQrCode(data.codeUrl); // // 轮询支付状态 // pollWechatPayStatus(data.orderId); // } // }) // .catch(err => { // showToast('支付请求失败,请重试', 'error'); // closeWechatPayModal(); // }); return Promise.resolve({ simulated: true }); } /** * 模拟确认支付完成 */ function confirmWechatPaySim() { var statusEl = document.getElementById('wechatPayStatus'); statusEl.className = 'wechat-pay-modal__status wechat-pay-modal__status--success'; statusEl.innerHTML = '✅ 支付成功'; setTimeout(function() { closeWechatPayModal(); var result = AuthManager.payDepositWechat(); if (result.success) { showToast('保证金 ¥' + AuthManager.CERT_DEPOSIT + ' 微信支付成功!', 'success'); renderCertBody(); renderCertProfile(); } else { showToast(result.message, 'error'); } }, 800); } /** * 轮询微信支付状态(预留接口) * 后期接入真实API时使用 */ function pollWechatPayStatus(orderId) { // var pollCount = 0; // var timer = setInterval(function() { // pollCount++; // fetch('/api/wechat-pay/query?orderId=' + orderId) // .then(res => res.json()) // .then(data => { // if (data.paid) { // clearInterval(timer); // var result = AuthManager.payDepositWechat(); // if (result.success) { // closeWechatPayModal(); // showToast('保证金微信支付成功!', 'success'); // renderCertBody(); // renderCertProfile(); // } // } // if (pollCount > 60) { // clearInterval(timer); // showToast('支付超时,请重试', 'error'); // closeWechatPayModal(); // } // }); // }, 2000); } function handleSubmitCert() { const result = AuthManager.submitCertification(); if (result.success) { showToast('认证申请已提交,正在审核...', 'success'); renderCertBody(); // 3秒后审核通过,刷新界面 setTimeout(() => { if (document.getElementById('certModalOverlay').style.display === 'flex') { renderCertBody(); renderCertProfile(); } AuthManager.updateNavUI(); }, 3500); } else { showToast(result.message, 'error'); } } // ============================================================ // 合同管理 & 保证金退费 — 用户端 // ============================================================ function getSharedData() { try { var raw = localStorage.getItem('ai_platform_admin_data'); return raw ? JSON.parse(raw) : null; } catch(e) { return null; } } function openContractModal() { if (!AuthManager.currentUser) { showToast('请先登录', 'error'); return; } document.getElementById('contractModalOverlay').style.display = 'flex'; renderUserContracts(); document.getElementById('userDropdown').classList.remove('show'); } function closeContractModal(event) { if (event && event.target !== document.getElementById('contractModalOverlay')) return; document.getElementById('contractModalOverlay').style.display = 'none'; } function canApplyDepositRefund(u) { if (!u.certApprovedAt) return { canApply: false, earliestDate: '请先完成认证', daysLeft: -1 }; var approvedDate = new Date(u.certApprovedAt); var oneYearLater = new Date(approvedDate); oneYearLater.setFullYear(oneYearLater.getFullYear() + 1); // 再加7个工作日 var earliest = addWorkingDays(oneYearLater, 7); var now = new Date(); if (now < earliest) { var diff = Math.ceil((earliest - now) / (1000 * 60 * 60 * 24)); return { canApply: false, earliestDate: earliest.toLocaleDateString('zh-CN'), daysLeft: diff }; } return { canApply: true, earliestDate: '', daysLeft: 0 }; } function addWorkingDays(startDate, days) { var result = new Date(startDate); var added = 0; while (added < days) { result.setDate(result.getDate() + 1); if (result.getDay() !== 0 && result.getDay() !== 6) added++; } return result; } function openDepositRefundModal() { if (!AuthManager.currentUser) { showToast('请先登录', 'error'); return; } var u = AuthManager.currentUser; if (!u.depositPaid) { showToast('您尚未缴纳保证金', 'error'); return; } var check = canApplyDepositRefund(u); if (!check.canApply) { if (check.daysLeft > 0) { showToast('保证金退费需认证满1年后的第7个工作日才能发起(距可申请还有约 ' + check.daysLeft + ' 天)', 'error'); } else { showToast(check.earliestDate, 'error'); } return; } document.getElementById('depositRefundOverlay').style.display = 'flex'; renderDepositRefundForm(); document.getElementById('userDropdown').classList.remove('show'); } function closeDepositRefundModal(event) { if (event && event.target !== document.getElementById('depositRefundOverlay')) return; document.getElementById('depositRefundOverlay').style.display = 'none'; } function renderUserContracts() { var shared = getSharedData(); var contracts = (shared && shared.contracts) ? shared.contracts : []; if (!contracts.length) { document.getElementById('contractModalBody').innerHTML = '
📜

暂无合作协议

当您的需求被服务商承接后,将自动生成合作协议

'; return; } var statusMap = { negotiating:'磋商中', pending_sign:'待签署', signing:'签署中', signed:'已签署', executing:'执行中', completed:'已完成', disputed:'纠纷中' }; var statusColor = { negotiating:'#f59e0b', pending_sign:'#3b82f6', signing:'#8b5cf6', signed:'#10b981', executing:'#6366f1', completed:'#1d4ed8', disputed:'#ef4444' }; var html = '
'; contracts.forEach(function(c) { // 签署信息 var signInfo = ''; if (c.signMode === 'online') { var sigCount = (c.signatories||[]).length; var signedCount = (c.signatories||[]).filter(function(s){return s.signStatus==='signed';}).length; signInfo = '🖊️ 电子签 · ' + signedCount + '/' + sigCount + ' 方已签'; } else { var attCount = (c.attachments||[]).length; signInfo = '📄 纸质签 · ' + attCount + ' 个附件'; } // 操作按钮 var actionBtn = ''; if (c.status === 'pending_sign' && c.signMode === 'online') { actionBtn = '
'; } else if (c.status === 'signing' && c.signMode === 'online') { actionBtn = '
'; } else if (c.status === 'pending_sign' && c.signMode === 'paper') { actionBtn = '
'; } html += '
' + '
' + '
' + (c.isTemplate ? '📝 ' : '') + escHtml(c.projectName||'未命名项目') + '
' + '
' + escHtml(c.providerName||'') + ' ↔ ' + escHtml(c.demanderName||'') + '
' + '
项目金额: ¥' + (c.projectAmount||0).toLocaleString('zh-CN') + ' · 平台服务费(5%): ¥' + (c.platformFee||0).toLocaleString('zh-CN') + '
' + // 付款进度预览(模板合同) (c.paymentSchedule && c.paymentSchedule.length ? '
' + c.paymentSchedule.map(function(ps) { return '' + escHtml(ps.label) + ' ' + ps.percentage + '%'; }).join('') + '
' : '') + // 服务内容预览 (c.serviceContent ? '
' + escHtml(c.serviceContent.slice(0,60)) + (c.serviceContent.length > 60 ? '...' : '') + '
' : '') + '
' + signInfo + '
' + (c.signedAt ? '
签署日期: ' + c.signedAt.slice(0,10) + '
' : '') + '
' + '
' + '' + (statusMap[c.status]||c.status) + '' + actionBtn + // 查看详情按钮 '
' + '
' + '
'; }); html += '
'; document.getElementById('contractModalBody').innerHTML = html; } function userSignOnline(id) { var shared = getSharedData(); if (!shared || !shared.contracts) return; var c = shared.contracts.find(function(x){return x.id===id;}); if (!c) return; if (!confirm('确认在线签署《' + escHtml(c.projectName) + '》?\n\n系统将发送短信验证码到您的注册手机号进行身份验证。\n\n📌 未来对接真实API后:\n GET /api/esign/sign-url?flowId='+(c.esignFlowId||'xxx')+'&signatory=current\n → 返回签署页面URL → 短信/人脸验证 → 完成签署')) return; // 模拟签署 c.status = 'signing'; // 标记当前用户对应的签署方已签 if (c.signatories && c.signatories.length) { var u = AuthManager.currentUser; var sig = c.signatories.find(function(s) { return s.name === (u.companyName || u.account || ''); }) || c.signatories[0]; sig.signStatus = 'signed'; sig.signedAt = new Date().toISOString().slice(0,10); // 检查是否全部签署完成 var allDone = c.signatories.every(function(s){return s.signStatus==='signed';}); if (allDone) { c.status = 'signed'; c.signedAt = new Date().toISOString().slice(0,10); } } localStorage.setItem('ai_platform_admin_data', JSON.stringify(shared)); showToast('✅ 签署完成!', 'success'); renderUserContracts(); } function viewContractSignDetail(id) { var shared = getSharedData(); if (!shared) return; var c = shared.contracts.find(function(x){return x.id===id;}); if (!c) return; var sigStatusMap = { pending:'待发送', sent:'已发送', viewed:'已查看', signed:'已签署', rejected:'已拒签' }; var detailHtml = '
' + '
' + '
📋 签署进度
' + '
流程ID: '+(c.esignFlowId||'N/A')+'
' + '
'; if (c.signatories && c.signatories.length) { detailHtml += '' + ''; c.signatories.forEach(function(s) { var roleLabel = s.role === 'provider' ? '供方' : (s.role === 'demander' ? '需方' : '平台'); var methodMap = { sms:'📱 短信验证', face:'👤 人脸识别', cert:'🔐 CA证书' }; var sigColor = { pending:'#f59e0b', sent:'#3b82f6', viewed:'#6366f1', signed:'#10b981', rejected:'#ef4444' }; detailHtml += '' + '' + '' + '' + '' + ''; }); detailHtml += '
角色签署方验证方式状态
'+roleLabel+''+escHtml(s.name)+''+(methodMap[s.signMethod]||s.signMethod)+''+(sigStatusMap[s.signStatus]||s.signStatus)+'
'; } document.getElementById('contractModalBody').innerHTML = detailHtml + ''; } // ---- 查看模板合同详情(AI生成专业版面) ---- function viewTemplateContractDetail(id) { var shared = getSharedData(); if (!shared) return; var c = shared.contracts.find(function(x) { return x.id === id; }); if (!c) return; var statusMap = { negotiating:'磋商中', pending_sign:'待签署', signing:'签署中', signed:'已签署', executing:'执行中', completed:'已完成', disputed:'纠纷中' }; // 合同详情使用专用滚动容器 document.getElementById('contractModalBody').style.maxHeight = '60vh'; document.getElementById('contractModalBody').style.overflowY = 'auto'; var cnAmount = toChineseAmountSimple(c.projectAmount || 0); var contentLines = (c.serviceContent || '').split('\n').filter(function(l) { return l.trim(); }); var contentClause = contentLines.map(function(l) { return '

' + escHtml(l.trim()) + '

'; }).join(''); var payRows = ''; if (c.paymentSchedule) { c.paymentSchedule.forEach(function(s) { payRows += '第' + s.stage + '期' + escHtml(s.label || '') + '' + (s.percentage || 0) + '%¥' + ((s.amount || 0)).toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '' + escHtml(s.condition || '') + ''; }); } var detailHtml = '
'; detailHtml += '
项 目 合 作 协 议
'; detailHtml += '
合同编号:' + escHtml(c.id) + (c.isTemplate ? '(模板生成)' : '') + '
'; detailHtml += '
'; detailHtml += '签订日期:' + (c.signedAt ? c.signedAt.slice(0,10) : c.createdAt.slice(0,10)) + ''; detailHtml += '签订地点:AI+供需对接平台(线上)'; detailHtml += '状态:' + (statusMap[c.status] || c.status) + ''; detailHtml += '
'; detailHtml += '
'; detailHtml += '

甲方(供方):' + escHtml(c.providerName || '') + '

'; detailHtml += '

乙方(需方):' + escHtml(c.demanderName || '') + '

'; detailHtml += '

监管平台:AI+供需对接平台

'; detailHtml += '
'; detailHtml += '

甲乙双方根据《中华人民共和国民法典》及相关法律法规,本着平等自愿、诚实信用的原则,经友好协商,就' + escHtml(c.projectName || '') + '事宜达成如下协议,以资共同信守。

'; // 第一条 detailHtml += '

第一条 项目概况与服务内容

'; detailHtml += '

1.1 项目名称:' + escHtml(c.projectName || '') + '。

'; detailHtml += '

1.2 服务内容及范围:

'; detailHtml += contentClause; // 第二条 detailHtml += '

第二条 合同金额与支付方式

'; detailHtml += '

2.1 本合同总金额为人民币 ¥' + (c.projectAmount || 0).toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '(大写:' + cnAmount + ')。

'; if (payRows) { detailHtml += '

2.2 付款进度安排如下:

'; detailHtml += '' + payRows + '
期次付款节点比例金额(元)付款条件
'; } detailHtml += '

2.3 本协议项下平台服务费为合同总金额的5%(即¥' + (c.platformFee || 0).toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '),由甲方承担。

'; // 第三条 detailHtml += '

第三条 双方权利与义务

'; detailHtml += '

3.1 甲方应按合同约定按时、保质完成各项服务工作,及时报告项目进展,并对乙方商业秘密承担保密义务。

'; detailHtml += '

3.2 乙方应按约定支付款项,为甲方提供必要协助和配合,及时组织验收。

'; // 第四条 detailHtml += '

第四条 交付与验收

'; detailHtml += '

4.1 甲方按约定标准交付服务成果,乙方应在收到后10个工作日内组织验收。

'; // 第五条 detailHtml += '

第五条 违约责任

'; detailHtml += '

5.1 任何一方违反本合同约定,给对方造成损失的,应当承担赔偿责任。

'; // 第六条 detailHtml += '

第六条 保密条款

'; detailHtml += '

6.1 双方对合作过程中获知的对方商业秘密和保密信息承担保密义务,保密期限为合同终止后三年。

'; // 第七条 detailHtml += '

第七条 争议解决

'; detailHtml += '

7.1 争议首先通过友好协商解决,协商不成的优先通过平台在线调解。调解不成的,可向合同签订地人民法院提起诉讼。

'; // 第八条 detailHtml += '

第八条 平台监管

'; detailHtml += '

8.1 AI+供需对接平台作为第三方监管机构,负责合同备案存档、履约进度跟踪、关键节点确认和纠纷调解。

'; // 第九条 detailHtml += '

第九条 合同生效与变更

'; detailHtml += '

9.1 本合同自双方' + (c.signMode === 'online' ? '通过平台完成电子签署' : '签署盖章并上传至平台') + '之日起生效。

'; // 签署页 detailHtml += '
'; detailHtml += '
(以下为签署页,无正文)
'; detailHtml += '
'; detailHtml += '

甲方(供方):' + escHtml(c.providerName || '') + '

授权代表:_______________

'; detailHtml += '

乙方(需方):' + escHtml(c.demanderName || '') + '

授权代表:_______________

'; detailHtml += '
'; detailHtml += '
AI+供需对接平台
备案编号:' + escHtml(c.id) + '
签署方式:' + (c.signMode === 'online' ? '线上电子签' : '线下纸质签') + '
'; detailHtml += '
'; detailHtml += '
'; // end contract-doc detailHtml += ''; detailHtml += ''; document.getElementById('contractModalBody').innerHTML = detailHtml; } function renderDepositRefundForm() { var u = AuthManager.currentUser; var shared = getSharedData(); var refunds = (shared && shared.depositRefunds) ? shared.depositRefunds : []; // 检查是否已有待审核的退费申请 var hasPending = refunds.some(function(r){return r.userId===u.id && r.status==='pending';}); var hasApproved = refunds.some(function(r){return r.userId===u.id && r.status==='approved';}); var hasRefunded = refunds.some(function(r){return r.userId===u.id && r.status==='refunded';}); if (hasRefunded) { document.getElementById('depositRefundBody').innerHTML = '

保证金已退款

您的保证金 ¥' + u.depositAmount + ' 已成功退还

'; return; } if (hasApproved) { document.getElementById('depositRefundBody').innerHTML = '

退费申请已批准

退款处理中,预计3-5个工作日到账

'; return; } if (hasPending) { document.getElementById('depositRefundBody').innerHTML = '
📝

退费申请审核中

平台将在1-3个工作日内审核您的退费申请

'; return; } var html = '
' + '
' + '
📋 退费说明
' + '
' + '• 保证金金额:¥' + u.depositAmount + '
' + '• 退费协议:保证金缴纳满 1 年后的第 7 个工作日方可发起退费申请
' + '• 退款周期:审核通过后3-5个工作日到账
' + '• 服务热线:400-XXX-XXXX' + '
' + '
' + '
' + '' + '
' + '
' + '' + '
' + '' + '
'; document.getElementById('depositRefundBody').innerHTML = html; } function submitDepositRefund() { var reason = (document.getElementById('dr_reason')||{}).value || ''; if (!reason.trim()) { showToast('请填写退费原因', 'error'); return; } var refundMethod = (document.getElementById('dr_refundMethod')||{}).value || 'bank'; var u = AuthManager.currentUser; var shared = getSharedData() || {}; if (!shared.depositRefunds) shared.depositRefunds = []; var newRefund = { id: 'dr-' + Date.now().toString(36), userId: u.id, userName: u.companyName || u.phone || u.account || '', contractId: '', depositAmount: u.depositAmount || 10000, refundAmount: u.depositAmount || 10000, refundMethod: refundMethod, reason: reason.trim(), status: 'pending', appliedAt: new Date().toISOString().slice(0,10), processedAt: null }; shared.depositRefunds.push(newRefund); localStorage.setItem('ai_platform_admin_data', JSON.stringify(shared)); showToast('✅ 退费申请已提交,请等待审核', 'success'); renderDepositRefundForm(); } // ============================================================ // MODULE: 通用合同模板 // ============================================================ // 合同模板默认付款进度 var DEFAULT_PAYMENT_SCHEDULE = [ { stage: 1, label: '首付款', percentage: 30, amount: 0, condition: '合同签署生效后7个工作日内支付', status: 'pending' }, { stage: 2, label: '中期款', percentage: 40, amount: 0, condition: '项目中期验收通过后5个工作日内支付', status: 'pending' }, { stage: 3, label: '尾款', percentage: 30, amount: 0, condition: '项目最终验收合格后10个工作日内支付', status: 'pending' } ]; // 模板预填数据(从咨询对话框传入) var tmplPreFill = null; var tmplFormData = null; function openTemplateContract(preFill) { tmplPreFill = preFill || null; if (!AuthManager.currentUser) { showToast('请先登录', 'error'); return; } // 重置付款进度为默认值 DEFAULT_PAYMENT_SCHEDULE = [ { stage: 1, label: '首付款', percentage: 30, amount: 0, condition: '合同签署生效后7个工作日内支付', status: 'pending' }, { stage: 2, label: '中期款', percentage: 40, amount: 0, condition: '项目中期验收通过后5个工作日内支付', status: 'pending' }, { stage: 3, label: '尾款', percentage: 30, amount: 0, condition: '项目最终验收合格后10个工作日内支付', status: 'pending' } ]; var feeRate = 0.05; // 从共享数据获取费率 var shared = getSharedData(); if (shared && shared.platformFeeRate) feeRate = shared.platformFeeRate; // 默认值 var u = AuthManager.currentUser; var providerName = (u.companyName || u.account || ''); var demanderName = ''; var projectName = ''; var serviceContent = ''; // 如果从咨询对话框打开,预填对方信息 if (tmplPreFill) { if (tmplPreFill.role === 'supply') { providerName = tmplPreFill.name || ''; demanderName = providerName; // 当前用户是需方 demanderName = (u.companyName || u.account || ''); providerName = tmplPreFill.name || ''; } else if (tmplPreFill.role === 'demand') { demanderName = tmplPreFill.name || ''; providerName = (u.companyName || u.account || ''); } projectName = (tmplPreFill.category || '') + '项目合作'; } var html = ''; // === Section 1: 甲乙双方基本信息 === html += '
'; html += '
1
合同主体信息
请确认甲乙双方的基本信息
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; // === Section 2: 服务内容 === html += '
'; html += '
2
服务内容与交付标准
详细描述服务范围、交付物和验收标准
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; // === Section 3: 合同金额与付款进度 === html += '
'; html += '
3
合同金额与付款进度
设定合同总金额和分期付款计划
'; html += '
'; html += '
'; html += '
'; html += '
'; // ⚠️ 金额确认提醒 html += '
'; html += '
⚠️
'; html += '
重要:合同金额确认义务
'; html += '
    '; html += '
  • 合同总金额须经甲乙双方共同确认,平台不代为议定价格
  • '; html += '
  • 双方应在平台见证下完成金额确认,确认后不可单方面修改
  • '; html += '
  • 平台仅按确认金额的 ' + (feeRate * 100) + '% 收取服务监管费用
  • '; html += '
'; html += '
'; // 付款进度表 html += '
'; html += ''; html += ''; html += '
'; html += '
'; html += ''; html += ''; html += ''; html += '
阶段付款节点比例(%)金额(¥)付款条件
'; html += '
'; html += '
'; // === Section 4: 平台监管与履约 === html += '
'; html += '
4
平台监管与履约保障
明确平台的监管角色和履约确认机制
'; html += '
'; html += '
🛡️ 平台监管职责
'; html += '
    '; html += '
  • 合同备案:平台作为第三方监管机构,对合同进行备案存档
  • '; html += '
  • 履约跟踪:平台跟踪合同执行进度,记录各阶段付款与交付情况
  • '; html += '
  • 纠纷调解:发生履约争议时,平台提供调解通道和证据支持
  • '; html += '
  • 保证金保障:供方缴纳的保证金作为履约担保,保障需方权益
  • '; html += '
  • 双向确认:关键节点(付款、验收)须双方在平台确认后生效
  • '; html += '
'; html += '
'; html += '
'; // === Section 5: 签署义务提醒 + 签署方式 === html += '
'; html += '
5
⚠️ 签署义务提醒
请务必阅读以下重要提示
'; html += '
'; html += '
🔔
'; html += '
供需双方签署义务告知书
'; html += '
    '; html += '
  • 根据平台规则,供需双方有义务在达成合作意向后签署正式合同
  • '; html += '
  • 您可以选择以下任一方式完成合同签署:
    方式一:线上电子签 — 在平台内完成电子签署,具有法律效力
    方式二:线下纸质签后上传 — 线下签署完成后,将合同扫描件上传至平台存档
  • '; html += '
  • 未签署合同的合作项目,平台无法提供履约监管和纠纷调解服务
  • '; html += '
  • 签署后的合同将作为法律依据,在纠纷发生时供平台仲裁参考
  • '; html += '
  • 平台鼓励双方优先选择线上电子签,更高效、更安全、更便捷
  • '; html += '
'; html += '
'; // 签署方式选择 html += '
'; html += '
'; html += ''; html += ''; html += '
'; // 电子签备注 html += '
'; html += '📌 选择线上电子签后,生成合同时将自动创建签署流程。双方通过短信验证码/人脸识别完成签署,合同即时生效。'; html += '
'; html += ''; html += '
'; // === Section 6: 双方确认 === html += '
'; html += '
最终确认
请甲乙双方分别确认合同条款
'; html += '
'; html += ''; html += ''; html += '
'; html += '
'; html += ''; html += ''; html += '
'; html += '
⏳ 等待双方确认...
'; html += '
'; document.getElementById('templateContractBody').innerHTML = html; document.getElementById('templateContractOverlay').style.display = 'flex'; // 初始化付款进度表 updateTmplPaymentSchedule(); // 初始化选中签署方式样式 selectTmplSignMode('online'); // 关闭合同弹窗(如果从合同弹窗打开的) if (document.getElementById('contractModalOverlay').style.display === 'flex') { document.getElementById('contractModalOverlay').style.display = 'none'; } } function closeTemplateContract(event) { if (event && event.target !== document.getElementById('templateContractOverlay')) return; document.getElementById('templateContractOverlay').style.display = 'none'; // 恢复原始 footer(如果被 showProjectDetail 改过或隐藏过) var footer = document.getElementById('templateContractFooter'); if (footer) { footer.style.display = ''; if (footer._originalHTML) { footer.innerHTML = footer._originalHTML; delete footer._originalHTML; } } tmplPreFill = null; tmplFormData = null; } // ---- 从咨询对话框打开模板 ---- function openTemplateFromConsult() { var preFill = null; if (consultCurrentId) { var c = CONSULT_CONVS.find(function(x) { return x.id === consultCurrentId; }); if (c) { preFill = { name: c.counterparty.name, role: c.counterparty.role, category: c.counterparty.category || '' }; } } openTemplateContract(preFill); } // ---- 签署方式切换 ---- function selectTmplSignMode(mode) { var onlineLabel = document.getElementById('tmplSignOnlineLabel'); var paperLabel = document.getElementById('tmplSignPaperLabel'); var esignNote = document.getElementById('tmplEsignNote'); var paperNote = document.getElementById('tmplPaperNote'); if (onlineLabel) { onlineLabel.style.borderColor = mode === 'online' ? 'var(--blue-500)' : 'var(--gray-200)'; onlineLabel.style.background = mode === 'online' ? 'var(--blue-50)' : 'white'; } if (paperLabel) { paperLabel.style.borderColor = mode === 'paper' ? 'var(--purple-500)' : 'var(--gray-200)'; paperLabel.style.background = mode === 'paper' ? 'var(--purple-50)' : 'white'; } if (esignNote) esignNote.style.display = mode === 'online' ? '' : 'none'; if (paperNote) paperNote.style.display = mode === 'paper' ? '' : 'none'; var radios = document.getElementsByName('tmplSignMode'); for (var i = 0; i < radios.length; i++) { radios[i].checked = (radios[i].value === mode); } } // ---- 付款进度管理 ---- function updateTmplPaymentSchedule() { var totalAmt = parseFloat(document.getElementById('tmpl_totalAmount').value) || 0; document.getElementById('tmpl_platformFee').value = Math.round(totalAmt * 0.05 * 100) / 100; var tbody = document.getElementById('tmplPaymentTbody'); if (!tbody) return; var html = ''; DEFAULT_PAYMENT_SCHEDULE.forEach(function(s, i) { s.amount = Math.round(totalAmt * s.percentage / 100 * 100) / 100; html += ''; html += '' + s.stage + ''; html += ''; html += ''; html += '¥' + s.amount.toLocaleString('zh-CN', {minimumFractionDigits: 2}) + ''; html += ''; html += ''; html += ''; }); tbody.innerHTML = html; // 更新合计 var totalPct = DEFAULT_PAYMENT_SCHEDULE.reduce(function(sum, s) { return sum + (s.percentage || 0); }, 0); var totalEl = document.getElementById('tmplPaymentTotal'); if (totalEl) { if (Math.abs(totalPct - 100) < 0.01) { totalEl.innerHTML = '合计比例:' + totalPct + '% ✓'; } else { totalEl.innerHTML = '合计比例:' + totalPct + '% (应为100%)'; } } } function updateTmplPaymentField(idx, field, value) { if (idx >= 0 && idx < DEFAULT_PAYMENT_SCHEDULE.length) { DEFAULT_PAYMENT_SCHEDULE[idx][field] = value; } } function addTmplPaymentStage() { var newStage = DEFAULT_PAYMENT_SCHEDULE.length + 1; DEFAULT_PAYMENT_SCHEDULE.push({ stage: newStage, label: '阶段' + newStage, percentage: 0, amount: 0, condition: '待定义', status: 'pending' }); updateTmplPaymentSchedule(); } function removeTmplPaymentStage(idx) { if (DEFAULT_PAYMENT_SCHEDULE.length <= 1) { showToast('至少保留一个付款阶段', 'error'); return; } DEFAULT_PAYMENT_SCHEDULE.splice(idx, 1); // 重新编号 DEFAULT_PAYMENT_SCHEDULE.forEach(function(s, i) { s.stage = i + 1; }); updateTmplPaymentSchedule(); } // ---- 双方确认检查 ---- function checkTmplConfirm() { var p = document.getElementById('tmpl_confirmProvider'); var d = document.getElementById('tmpl_confirmDemander'); var status = document.getElementById('tmplConfirmStatus'); var btn = document.getElementById('tmplGenerateBtn'); if (p && p.checked && d && d.checked) { status.innerHTML = '✅ 双方已确认,可以生成合同'; status.style.color = '#059669'; if (btn) { btn.disabled = false; btn.style.opacity = '1'; } } else if (p && p.checked) { status.innerHTML = '⏳ 甲方已确认,等待乙方确认...'; status.style.color = '#d97706'; if (btn) { btn.disabled = true; btn.style.opacity = '0.5'; } } else if (d && d.checked) { status.innerHTML = '⏳ 乙方已确认,等待甲方确认...'; status.style.color = '#d97706'; if (btn) { btn.disabled = true; btn.style.opacity = '0.5'; } } else { status.innerHTML = '⏳ 等待双方确认...'; status.style.color = '#d97706'; if (btn) { btn.disabled = true; btn.style.opacity = '0.5'; } } } // ---- 生成合同(AI生成专业合同版面) ---- function generateTemplateContract() { var providerName = (document.getElementById('tmpl_providerName') || {}).value || ''; var demanderName = (document.getElementById('tmpl_demanderName') || {}).value || ''; var projectName = (document.getElementById('tmpl_projectName') || {}).value || ''; var totalAmount = parseFloat((document.getElementById('tmpl_totalAmount') || {}).value) || 0; var platformFee = parseFloat((document.getElementById('tmpl_platformFee') || {}).value) || 0; var serviceContent = (document.getElementById('tmpl_serviceContent') || {}).value || ''; var signDate = (document.getElementById('tmpl_signDate') || {}).value || ''; var startDate = (document.getElementById('tmpl_startDate') || {}).value || ''; var endDate = (document.getElementById('tmpl_endDate') || {}).value || ''; if (!providerName || !demanderName || !projectName || !totalAmount) { showToast('请填写所有必填字段(供方、需方、项目名称、合同总金额)', 'error'); return; } if (!serviceContent.trim()) { showToast('请填写服务内容描述', 'error'); return; } var signModeRadio = document.querySelector('input[name="tmplSignMode"]:checked'); var signMode = signModeRadio ? signModeRadio.value : 'online'; var totalPct = DEFAULT_PAYMENT_SCHEDULE.reduce(function(sum, s) { return sum + (s.percentage || 0); }, 0); if (Math.abs(totalPct - 100) > 0.01) { showToast('付款进度比例合计必须为100%,当前为' + totalPct + '%', 'error'); return; } // 保存表单数据 tmplFormData = { providerName: providerName, demanderName: demanderName, projectName: projectName, totalAmount: totalAmount, platformFee: platformFee, serviceContent: serviceContent, signMode: signMode, signDate: signDate, startDate: startDate, endDate: endDate, paymentSchedule: JSON.parse(JSON.stringify(DEFAULT_PAYMENT_SCHEDULE)) }; var contractNo = 'TPL-' + Date.now().toString(36).toUpperCase(); var today = signDate || new Date().toISOString().slice(0, 10); var cnAmount = toChineseAmountSimple(totalAmount); // 处理服务内容为条款格式 var contentLines = serviceContent.split('\n').filter(function(l) { return l.trim(); }); var contentClause = contentLines.map(function(l) { return '

' + escHtml(l.trim()) + '

'; }).join(''); // 生成付款进度表格行 var payRows = ''; DEFAULT_PAYMENT_SCHEDULE.forEach(function(s) { s.amount = Math.round(totalAmount * s.percentage / 100 * 100) / 100; payRows += '第' + s.stage + '期' + escHtml(s.label) + '' + s.percentage + '%¥' + s.amount.toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '' + escHtml(s.condition) + ''; }); // ======== AI生成完整合同版面 ======== var previewHtml = '
'; // 合同标题 previewHtml += '
项 目 合 作 协 议
'; previewHtml += '
合同编号:' + contractNo + '
'; // 合同元信息 previewHtml += '
'; previewHtml += '签订日期:' + today + ''; previewHtml += '签订地点:AI+供需对接平台(线上)'; if (startDate) previewHtml += '服务期限:' + startDate + (endDate ? ' 至 ' + endDate : ' 起') + ''; previewHtml += '
'; // 甲乙双方 previewHtml += '
'; previewHtml += '

甲方(供方):' + escHtml(providerName) + '

'; previewHtml += '

乙方(需方):' + escHtml(demanderName) + '

'; previewHtml += '

监管平台:AI+供需对接平台

'; previewHtml += '
'; // 鉴于条款 previewHtml += '

甲乙双方根据《中华人民共和国民法典》及相关法律法规,本着平等自愿、诚实信用的原则,经友好协商,就' + escHtml(projectName) + '事宜达成如下协议,以资共同信守。

'; // === 第一条 项目概况与服务内容 === previewHtml += '

第一条 项目概况与服务内容

'; previewHtml += '

1.1 项目名称:' + escHtml(projectName) + '。

'; previewHtml += '

1.2 服务内容及范围:

'; previewHtml += contentClause; if (startDate) previewHtml += '

1.3 服务期限:自' + startDate + '起' + (endDate ? '至' + endDate + '止' : ',具体以双方协商为准') + '。

'; // === 第二条 合同金额与支付方式 === previewHtml += '

第二条 合同金额与支付方式

'; previewHtml += '

2.1 本合同总金额为人民币 ¥' + totalAmount.toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '(大写:' + cnAmount + ')。该金额为含税金额,包含甲方为完成本合同项下全部服务所需的一切费用。

'; previewHtml += '

2.2 付款进度安排如下:

'; previewHtml += '' + payRows + '
期次付款节点比例金额(人民币元)付款条件
'; previewHtml += '

2.3 乙方应在各付款条件满足后,按照上表约定的期限和金额向甲方支付相应款项。甲方应在收到款项后3个工作日内向乙方开具等额合法有效的增值税发票。

'; previewHtml += '

2.4 本协议项下平台服务费为合同总金额的5%(即¥' + platformFee.toLocaleString('zh-CN', {minimumFractionDigits: 2}) + '),由甲方承担,在合同签署后由平台从甲方保证金中扣除或另行收取。

'; // === 第三条 双方权利与义务 === previewHtml += '

第三条 双方权利与义务

'; previewHtml += '

3.1 甲方的权利与义务:

'; previewHtml += '

(1)按照本合同约定的服务内容和标准,按时、保质完成各项服务工作;

'; previewHtml += '

(2)及时向乙方报告项目进展情况,接受乙方的合理监督和检查;

'; previewHtml += '

(3)对在合作过程中获知的乙方商业秘密和保密信息承担保密义务;

'; previewHtml += '

(4)按照约定收取合同款项。

'; previewHtml += '

3.2 乙方的权利与义务:

'; previewHtml += '

(1)按照本合同约定的时间和金额向甲方支付相应款项;

'; previewHtml += '

(2)为甲方履行合同提供必要的协助和配合,及时提供相关资料和信息;

'; previewHtml += '

(3)按照约定的验收标准及时组织验收并出具验收意见;

'; previewHtml += '

(4)对在合作过程中获知的甲方商业秘密和保密信息承担保密义务。

'; // === 第四条 交付与验收 === previewHtml += '

第四条 交付与验收

'; previewHtml += '

4.1 甲方应按照约定的时间和标准向乙方交付服务成果。

'; previewHtml += '

4.2 乙方应在收到交付成果后10个工作日内组织验收。验收合格的,双方签署验收确认书;验收不合格的,乙方应书面说明理由,甲方应在收到通知后15个工作日内完成整改并重新提交验收。

'; previewHtml += '

4.3 乙方无正当理由逾期未组织验收或未提出书面异议的,视为验收通过。

'; // === 第五条 违约责任 === previewHtml += '

第五条 违约责任

'; previewHtml += '

5.1 任何一方违反本合同约定,给对方造成损失的,应当承担赔偿责任。

'; previewHtml += '

5.2 甲方逾期交付服务成果的,每逾期一日,应向乙方支付合同总金额万分之三的违约金,但违约金总额不超过合同总金额的10%。逾期超过30日的,乙方有权单方解除合同。

'; previewHtml += '

5.3 乙方逾期支付合同款项的,每逾期一日,应向甲方支付逾期金额万分之三的违约金。逾期超过30日的,甲方有权暂停服务并要求乙方承担相应责任。

'; previewHtml += '

5.4 因一方原因导致合同无法继续履行的,违约方应赔偿守约方因此遭受的全部损失。

'; // === 第六条 保密条款 === previewHtml += '

第六条 保密条款

'; previewHtml += '

6.1 双方应对在合同签订和履行过程中知悉的对方商业秘密、技术信息和其他保密信息(以下统称"保密信息")承担保密义务。未经对方书面同意,不得向任何第三方披露或用于本合同约定之外的任何用途。

'; previewHtml += '

6.2 本保密义务不因合同的变更、解除或终止而失效,保密期限为合同终止后三年。

'; // === 第七条 争议解决 === previewHtml += '

第七条 争议解决

'; previewHtml += '

7.1 因本合同引起的或与本合同有关的任何争议,双方应首先通过友好协商解决。

'; previewHtml += '

7.2 协商不成的,双方同意优先通过AI+供需对接平台提供的在线调解通道进行调解。

'; previewHtml += '

7.3 调解不成的,任何一方均可向合同签订地有管辖权的人民法院提起诉讼。

'; // === 第八条 平台监管 === previewHtml += '

第八条 平台监管

'; previewHtml += '

8.1 AI+供需对接平台作为本合同的第三方监管机构,负责对本合同的履约过程进行跟踪和监督。

'; previewHtml += '

8.2 平台监管职责包括但不限于:合同备案存档、履约进度跟踪、关键节点确认、付款节点见证、纠纷调解等。

'; previewHtml += '

8.3 双方同意,在平台记录的关键节点确认信息(包括但不限于付款确认、验收确认等)可作为履约证据使用。

'; previewHtml += '

8.4 平台不承担因一方违约造成的经济损失,但应提供调解支持和相关证据材料。

'; // === 第九条 合同生效与变更 === previewHtml += '

第九条 合同生效与变更

'; previewHtml += '

9.1 本合同自甲乙双方' + (signMode === 'online' ? '通过平台完成电子签署' : '签署盖章并将扫描件上传至平台') + '之日起生效。

'; previewHtml += '

9.2 本合同的任何修改、补充或变更,须经双方协商一致,并' + (signMode === 'online' ? '通过平台签署书面补充协议' : '签订书面补充协议并上传至平台备案') + '。补充协议与本合同具有同等法律效力。

'; previewHtml += '

9.3 本合同一式' + (signMode === 'online' ? '两份(电子版)' : '两份') + ',甲乙双方各执一份,平台备案一份,具有同等法律效力。

'; // === 签署页 === previewHtml += '
'; previewHtml += '
(以下为签署页,无正文)
'; previewHtml += '
'; previewHtml += '
'; previewHtml += '

甲方(供方):' + escHtml(providerName) + '

'; previewHtml += '

法定代表人/授权代表:_______________

'; previewHtml += '

联系电话:_______________

'; previewHtml += '

签署日期:____年____月____日

'; previewHtml += '
'; previewHtml += '
'; previewHtml += '
'; previewHtml += '

乙方(需方):' + escHtml(demanderName) + '

'; previewHtml += '

法定代表人/授权代表:_______________

'; previewHtml += '

联系电话:_______________

'; previewHtml += '

签署日期:____年____月____日

'; previewHtml += '
'; previewHtml += '
'; previewHtml += '
'; // 平台备案章 previewHtml += '
'; previewHtml += 'AI+供需对接平台
'; previewHtml += '本合同已于 ' + today + ' 在平台完成备案
'; previewHtml += '备案编号:' + contractNo + ' | 签署方式:' + (signMode === 'online' ? '线上电子签' : '线下纸质签') + '
'; previewHtml += '平台作为第三方监管机构,对本合同的真实性和完整性进行见证'; previewHtml += '
'; previewHtml += '
'; previewHtml += '
'; // end contract-doc // 操作按钮 previewHtml += '
'; previewHtml += ''; previewHtml += ''; previewHtml += ''; previewHtml += '
'; document.getElementById('templateContractBody').innerHTML = previewHtml; document.getElementById('templateContractFooter').style.display = 'none'; document.querySelector('.template-modal .modal__body').scrollTop = 0; } function downloadContractHtml(containerId, filename) { var container = document.getElementById(containerId); if (!container) { showToast('合同内容不存在', 'error'); return; } var contractEl = container.querySelector('.contract-doc'); if (!contractEl) { showToast('未找到合同内容', 'error'); return; } var contractHTML = contractEl.outerHTML; var standaloneDoc = '\n\n\n\n\n项目合作协议\n\n\n\n'; standaloneDoc += contractHTML; standaloneDoc += '\n\n'; var blob = new Blob([standaloneDoc], { type: 'text/html;charset=UTF-8' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = filename || '项目合作协议.html'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); showToast('📥 合同已下载!可用浏览器打开后打印为PDF', 'success'); } function saveTemplateContract() { if (!tmplFormData) { showToast('合同数据丢失,请重新填写', 'error'); return; } var d = tmplFormData; var shared = getSharedData() || {}; if (!shared.contracts) shared.contracts = []; var u = AuthManager.currentUser; var newContract = { id: 'ct-tpl-' + Date.now().toString(36), bidId: '', projectName: d.projectName, projectAmount: d.totalAmount, platformFee: d.platformFee, platformFeeRate: 0.05, providerId: '', providerName: d.providerName, demanderName: d.demanderName, signMode: d.signMode, esignProvider: null, esignFlowId: d.signMode === 'online' ? 'ESF-TPL-' + Date.now().toString(36).toUpperCase() : null, signatories: d.signMode === 'online' ? [ { name: d.providerName, role: 'provider', phone: '', signStatus: 'pending', signedAt: null, signMethod: 'sms' }, { name: d.demanderName, role: 'demander', phone: '', signStatus: 'pending', signedAt: null, signMethod: 'sms' } ] : [], attachments: [], paperVerifiedBy: null, paperSignedAt: null, status: 'pending_sign', createdAt: new Date().toISOString().slice(0, 10), signedAt: d.signDate || null, completedAt: null, disputeNote: '', serviceContent: d.serviceContent, paymentSchedule: d.paymentSchedule, isTemplate: true, confirmedByProvider: true, confirmedByDemander: true }; shared.contracts.push(newContract); localStorage.setItem('ai_platform_admin_data', JSON.stringify(shared)); showToast('✅ 合同模板已生成并保存!合同编号: ' + newContract.id, 'success'); closeTemplateContract(); // 重置付款进度为默认 DEFAULT_PAYMENT_SCHEDULE = [ { stage: 1, label: '首付款', percentage: 30, amount: 0, condition: '合同签署生效后7个工作日内支付', status: 'pending' }, { stage: 2, label: '中期款', percentage: 40, amount: 0, condition: '项目中期验收通过后5个工作日内支付', status: 'pending' }, { stage: 3, label: '尾款', percentage: 30, amount: 0, condition: '项目最终验收合格后10个工作日内支付', status: 'pending' } ]; } function renderCertProducts() { const u = AuthManager.currentUser; if (!u) return; const status = AuthManager.getCertStatus(); const count = AuthManager.getProductCount(); if (status !== 'approved') { document.getElementById('certProductBody').innerHTML = `
🔒

请先完成企业认证后再管理产品

`; return; } // 统一管理:产品 + 数据集 + OPC const userName = u.nick || u.name || ''; const myDatasets = (platformData.datasets || []).filter(d => d.postedBy === userName || d.postedBy === u.name ); const myOpc = (platformData.opc || []).filter(d => d.postedBy === userName || d.postedBy === u.name ); const totalCount = count + myDatasets.length + myOpc.length; let itemHtml = ''; // 产品列表 if (u.products && u.products.length > 0) { itemHtml += u.products.map(p => { const priceDisplay = p.priceType === 'custom' ? p.price : '面议'; const scenarioPreview = p.scenario ? (p.scenario.length > 40 ? p.scenario.slice(0, 40) + '...' : p.scenario) : ''; return `
产品方案${p.name}
${p.category || '未分类'} · ${priceDisplay} · ${new Date(p.createdAt).toLocaleDateString('zh-CN')}
${scenarioPreview ? `
🎯 ${scenarioPreview}
` : ''}
`}).join(''); } // 数据集列表 if (myDatasets.length > 0) { itemHtml += myDatasets.map(d => `
数据集${d.name}
${d.category || '未分类'} · ${d.scale || ''} · ${d.format || ''} · ${d.postedDate || ''}
${d.description ? `
📊 ${d.description.length > 40 ? d.description.slice(0,40)+'...' : d.description}
` : ''}
`).join(''); } // OPC列表 if (myOpc.length > 0) { itemHtml += myOpc.map(o => `
${o.type === 'idea' ? '创意' : '需求'}${o.title}
${o.category || '未分类'} · ${o.seeking || ''} · ${o.postedDate || ''}
${o.description ? `
🚀 ${o.description.length > 40 ? o.description.slice(0,40)+'...' : o.description}
` : ''}
`).join(''); } if (totalCount === 0) { itemHtml = '
暂无内容,点击下方按钮添加产品、数据集或创意需求
'; } document.getElementById('certProductBody').innerHTML = `
发布管理 共 ${totalCount} / ${AuthManager.PUBLISH_TOTAL_LIMIT} 项
📦 产品 ${count} 📚 数据集 ${myDatasets.length} 🚀 OPC ${myOpc.length}
${totalCount >= AuthManager.PUBLISH_TOTAL_LIMIT ? `
⚠️ 发布总数已达上限(${AuthManager.PUBLISH_TOTAL_LIMIT}个),请先删除部分内容再发布
` : `
还可发布 ${AuthManager.PUBLISH_TOTAL_LIMIT - totalCount} 项内容
`}

发布列表

${itemHtml}
`; } function showAddProductForm() { const total = AuthManager.getTotalPublishCount(); if (total >= AuthManager.PUBLISH_TOTAL_LIMIT) { showToast(`发布总数已达上限(${AuthManager.PUBLISH_TOTAL_LIMIT}个),请先删除部分内容再发布`, 'error'); return; } const form = document.getElementById('addProductForm'); form.style.display = 'block'; form.innerHTML = `

添加发布内容

录入常见问答,AI客服优先匹配知识库回复,未命中再转大模型
`; window._priceType = 'negotiable'; window._publishType = 'product'; } function switchPublishType(type) { window._publishType = type; ['product','dataset','opc'].forEach(t => { const el = document.getElementById('formFields_' + t); if (el) el.style.display = t === type ? 'block' : 'none'; const label = document.getElementById('ptLabel_' + t); if (label) label.style.border = t === type ? '2px solid var(--blue-500)' : '2px solid transparent'; }); } function handleAddUnified() { const total = AuthManager.getTotalPublishCount(); if (total >= AuthManager.PUBLISH_TOTAL_LIMIT) { showToast(`发布总数已达上限(${AuthManager.PUBLISH_TOTAL_LIMIT}个),请先删除部分内容再发布`, 'error'); return; } const type = window._publishType || 'product'; if (type === 'product') { handleAddProduct(); } else if (type === 'dataset') { handleAddDatasetFromPM(); } else if (type === 'opc') { handleAddOpcFromPM(); } } function handleAddDatasetFromPM() { const name = document.getElementById('pmDsName').value.trim(); const category = document.getElementById('pmDsCategory').value; const desc = document.getElementById('pmDsDesc').value.trim(); const scale = document.getElementById('pmDsScale').value; const format = document.getElementById('pmDsFormat').value.trim(); const dsType = document.querySelector('input[name="pmDsType"]:checked').value; if (!name) { showToast('请输入数据集名称', 'error'); return; } if (!category) { showToast('请选择分类', 'error'); return; } if (!desc) { showToast('请输入数据描述', 'error'); return; } const newDs = { id: 'ds-' + Date.now(), name, type: dsType, category, description: desc, scale: scale || '未指定', format: format || '未指定', priceRange: { min: 0, max: 0 }, postedDate: new Date().toISOString().slice(0, 10), postedBy: (AuthManager.currentUser && AuthManager.currentUser.nick) || '匿名用户', tags: [category], faq: _pmFaqItems.slice() }; platformData.datasets.unshift(newDs); MOCK_DATASETS.unshift(newDs); _pmFaqItems = []; showToast('数据集发布成功!', 'success'); hideAddProductForm(); renderCertProducts(); renderDatasets(); } function handleAddOpcFromPM() { const title = document.getElementById('pmOpcTitle').value.trim(); const category = document.getElementById('pmOpcCategory').value; const desc = document.getElementById('pmOpcDesc').value.trim(); const seeking = document.getElementById('pmOpcSeeking').value.trim(); const opcType = document.querySelector('input[name="pmOpcType"]:checked').value; if (!title) { showToast('请输入标题', 'error'); return; } if (!category) { showToast('请选择领域', 'error'); return; } if (!desc) { showToast('请输入详细描述', 'error'); return; } const newOpc = { id: 'opc-' + Date.now(), title, type: opcType, category, description: desc, seeking: seeking || '未指定', postedDate: new Date().toISOString().slice(0, 10), postedBy: (AuthManager.currentUser && AuthManager.currentUser.nick) || '匿名用户', tags: [category], faq: _pmFaqItems.slice() }; platformData.opc.unshift(newOpc); MOCK_OPC_IDEAS.unshift(newOpc); _pmFaqItems = []; showToast('OPC创意/需求发布成功!', 'success'); hideAddProductForm(); renderCertProducts(); renderOpc(); } function handleRemoveDataset(id) { if (!confirm('确定要删除该数据集吗?')) return; platformData.datasets = (platformData.datasets || []).filter(d => d.id !== id); const idx = MOCK_DATASETS.findIndex(d => d.id === id); if (idx >= 0) MOCK_DATASETS.splice(idx, 1); showToast('数据集已删除', 'success'); renderCertProducts(); renderDatasets(); } function handleRemoveOpc(id) { if (!confirm('确定要删除该OPC创意/需求吗?')) return; platformData.opc = (platformData.opc || []).filter(d => d.id !== id); const idx = MOCK_OPC_IDEAS.findIndex(d => d.id === id); if (idx >= 0) MOCK_OPC_IDEAS.splice(idx, 1); showToast('OPC创意/需求已删除', 'success'); renderCertProducts(); renderOpc(); } function hideAddProductForm() { document.getElementById('addProductForm').style.display = 'none'; document.getElementById('addProductForm').innerHTML = ''; } function switchPriceType(type) { window._priceType = type; const wrap = document.getElementById('customPriceWrap'); if (wrap) wrap.style.display = type === 'custom' ? 'block' : 'none'; } function handleAddProduct() { const name = document.getElementById('newProductName').value.trim(); const category = document.getElementById('newProductCategory').value.trim(); const intro = document.getElementById('newProductIntro').value.trim(); const scenario = document.getElementById('newProductScenario').value.trim(); const priceType = window._priceType || 'negotiable'; const price = priceType === 'custom' ? document.getElementById('newProductPrice').value.trim() : ''; if (!name) { showToast('请输入产品名称', 'error'); return; } if (!category) { showToast('请选择产品分类', 'error'); return; } if (!intro) { showToast('请输入产品介绍', 'error'); return; } if (!scenario) { showToast('请输入应用场景', 'error'); return; } if (priceType === 'custom' && !price) { showToast('请输入价格信息', 'error'); return; } const result = AuthManager.addProduct(name, category, intro, scenario, priceType, price); if (result.success) { // 保存FAQ到产品数据 if (window._pmFaqItems && _pmFaqItems.length > 0) { var u = AuthManager.currentUser; var products = (u && u.products) || []; if (products.length > 0) { products[products.length - 1].faq = _pmFaqItems.slice(); } // 同步到platformData if (!platformData.userProducts) platformData.userProducts = []; var lastPm = platformData.userProducts.find(function(p) { return p.name === name; }); if (lastPm) lastPm.faq = _pmFaqItems.slice(); try { localStorage.setItem(PLATFORM_DATA_KEY, JSON.stringify(platformData)); } catch(e) {} } _pmFaqItems = []; showToast('产品发布成功', 'success'); hideAddProductForm(); renderCertProducts(); } else { showToast(result.message, 'error'); } } function handleRemoveProduct(productId) { if (!confirm('确定要删除该产品吗?')) return; const result = AuthManager.removeProduct(productId); if (result.success) { showToast('产品已删除', 'success'); renderCertProducts(); } else { showToast(result.message, 'error'); } } // ============================================================ // 认证中心 - 我的需求 // ============================================================ function renderCertRequirements() { const u = AuthManager.currentUser; if (!u) return; const userName = u.nick || u.name || ''; // 匹配用户发布的需求(通过 postedBy 匹配) const myReqs = MOCK_REQUIREMENTS.filter(r => r.postedBy === userName || r.postedBy === u.name ); let listHtml = ''; if (myReqs.length > 0) { listHtml = myReqs.map(r => { const priorityColor = r.priority === '高' ? 'var(--error)' : r.priority === '中' ? 'var(--warning)' : 'var(--gray-500)'; return `
${r.title} ${r.status === 'open' ? '🟢 进行中' : '⚫ 已关闭'}
${r.category} 预算:¥${(r.budget.min/10000).toFixed(0)}-${(r.budget.max/10000).toFixed(0)}万 周期:${r.timeline} ${r.priority}优先级
${r.description}
${r.tags.map(t => `${t}`).join('')}
`}).join(''); } else { listHtml = `
📋

您还没有发布过需求

在平台首页搜索框下方可以发布需求

`; } document.getElementById('certRequirementsBody').innerHTML = `
我的需求 共 ${myReqs.length} 条
${listHtml} `; } function handleRemoveMyRequirement(reqId) { if (!confirm('确定要删除该需求吗?此操作不可撤销。')) return; const idx = MOCK_REQUIREMENTS.findIndex(r => r.id === reqId); if (idx >= 0) { MOCK_REQUIREMENTS.splice(idx, 1); // 同步删除 platformData 中的数据 var pIdx = platformData.requirements.findIndex(function(r) { return r.id === reqId; }); if (pIdx >= 0) platformData.requirements.splice(pIdx, 1); showToast('需求已删除', 'success'); renderCertRequirements(); } } // ============================================================ // 认证中心 - 我的发布(数据集 + OPC创意 + 产品) // ============================================================ function renderCertPublish() { const u = AuthManager.currentUser; if (!u) return; const userName = u.nick || u.name || ''; // 产品 const myProducts = u.products || []; // 数据集 const myDatasets = MOCK_DATASETS.filter(d => d.postedBy === userName || d.postedBy === u.name ); // OPC创意 const myOpc = MOCK_OPC_IDEAS.filter(d => d.postedBy === userName || d.postedBy === u.name ); const totalItems = myProducts.length + myDatasets.length + myOpc.length; let html = `
我的发布 共 ${totalItems} 项
`; // 产品部分 html += `

📦 产品 (${myProducts.length})

`; if (myProducts.length > 0) { html += myProducts.map(p => `
${p.name} 产品
${p.category || '未分类'} ${p.priceType === 'custom' ? p.price : '面议'} ${new Date(p.createdAt).toLocaleDateString('zh-CN')}
${p.scenario ? `
🎯 ${p.scenario.length > 60 ? p.scenario.slice(0,60)+'...' : p.scenario}
` : ''}
`).join(''); } else { html += `
暂无发布产品
`; } // 数据集部分 html += `

📚 数据集 (${myDatasets.length})

`; if (myDatasets.length > 0) { html += myDatasets.map(d => `
${d.name} ${d.type === 'supply' ? '供给' : '需求'}
${d.category} ${d.scale} ${d.format}
${d.description.length > 60 ? d.description.slice(0,60)+'...' : d.description}
`).join(''); } else { html += `
暂无发布数据集
`; } // OPC创意部分 html += `

🚀 OPC创意/需求 (${myOpc.length})

`; if (myOpc.length > 0) { html += myOpc.map(d => `
${d.title} ${d.type === 'idea' ? '创意' : '需求'}
${d.category} ${d.postedDate}
${d.description.length > 60 ? d.description.slice(0,60)+'...' : d.description}
`).join(''); } else { html += `
暂无发布OPC创意
`; } if (totalItems === 0) { html = `
📦

您还没有任何发布内容

完成企业认证后可发布产品和需求

`; } document.getElementById('certPublishBody').innerHTML = html; } // 点击外部关闭下拉 document.addEventListener('click', function(e) { if (!e.target.closest('#navUserBadge')) { const dd = document.getElementById('userDropdown'); if (dd) dd.classList.remove('show'); } }); function smoothScroll(id) { const el = document.getElementById(id); if (el) el.scrollIntoView({ behavior:'smooth' }); } function scrollToTop() { window.scrollTo({ top:0, behavior:'smooth' }); } // ============================================================ // MODULE 8: AI CHAT WIDGET // ============================================================ function toggleChat() { AppState.chatOpen = !AppState.chatOpen; document.getElementById('chatPanel').classList.toggle('open', AppState.chatOpen); document.getElementById('chatTrigger').classList.toggle('active', AppState.chatOpen); if (AppState.chatOpen) { document.getElementById('chatTrigger').textContent = '✕'; setTimeout(() => { document.getElementById('chatInput').focus(); }, 300); } else { document.getElementById('chatTrigger').textContent = '💬'; } } function sendChatMessage() { const input = document.getElementById('chatInput'); const msg = input.value.trim(); if (!msg) return; const container = document.getElementById('chatMessages'); const userDiv = document.createElement('div'); userDiv.className = 'chat-msg chat-msg--user'; userDiv.textContent = msg; container.appendChild(userDiv); input.value = ''; // AI 响应 setTimeout(() => { const response = AIEngine.getChatResponse(msg); const botDiv = document.createElement('div'); botDiv.className = 'chat-msg chat-msg--bot'; botDiv.innerHTML = response.text.replace(/\n/g, '
'); if (response.suggestions && response.suggestions.length > 0) { const sugDiv = document.createElement('div'); sugDiv.className = 'chat-msg__suggestions'; response.suggestions.forEach((s, i) => { const btn = document.createElement('span'); btn.className = 'chat-msg__suggestion'; btn.textContent = s; btn.onclick = () => { if (response.providerIds && response.providerIds[i]) { showProviderDetail(response.providerIds[i]); } else if (s === '打开需求发布表单') { openPublishModal(); } else if (s === '查看全部服务商' || s === '查看全部') { switchTab('providers'); renderProviders(MOCK_PROVIDERS); document.getElementById('providerMarket').scrollIntoView({ behavior:'smooth' }); } else if (s === '查看行业资讯') { document.getElementById('industryNews').scrollIntoView({ behavior:'smooth' }); } else if (s === '查看项目标讯') { document.getElementById('biddingInfo').scrollIntoView({ behavior:'smooth' }); } else if (s === '查看投融资动态') { document.getElementById('investInfo').scrollIntoView({ behavior:'smooth' }); } else if (s === '查看数据集') { document.getElementById('datasetMarket').scrollIntoView({ behavior:'smooth' }); } else if (s === '查看一人公司') { document.getElementById('opcSolo').scrollIntoView({ behavior:'smooth' }); } else if (s === '查看WAIC展商' || s === '搜索更多展商') { document.getElementById('waicExhibitors').scrollIntoView({ behavior:'smooth' }); } else if (s === 'H1应用与生态馆' || s === 'H3具身智能馆') { document.getElementById('waicExhibitors').scrollIntoView({ behavior:'smooth' }); const hall = s.startsWith('H1') ? 'H1' : 'H3'; setTimeout(() => filterWaicExhibitors(hall), 600); } else if (s === '发布我的创意') { document.getElementById('opcSolo').scrollIntoView({ behavior:'smooth' }); setTimeout(() => openOpcPublish(), 500); } else if (s === '发布需求') { openPublishModal(); } else if (s === '查看推荐服务商') { const query = AIEngine.parseQuery(msg); const providers = AIEngine.matchProviders(query); switchTab('providers'); renderProviders(providers); document.getElementById('providerMarket').scrollIntoView({ behavior:'smooth' }); } else { document.getElementById('chatInput').value = s; sendChatMessage(); } }; sugDiv.appendChild(btn); }); botDiv.appendChild(sugDiv); } container.appendChild(botDiv); container.scrollTop = container.scrollHeight; }, 600); container.scrollTop = container.scrollHeight; } function chatQuickAction(action) { document.getElementById('chatInput').value = action; sendChatMessage(); } // ============================================================ // MODULE 9: TOAST // ============================================================ function showToast(message, type) { const container = document.getElementById('toastContainer'); const toast = document.createElement('div'); const icons = { success:'✅', error:'❌', info:'ℹ️' }; toast.className = `toast ${type ? 'toast--'+type : ''}`; toast.innerHTML = `${icons[type]||'ℹ️'}${message}
`; container.appendChild(toast); setTimeout(() => { toast.style.opacity = '0'; toast.style.transition = 'opacity 0.3s'; }, 2500); setTimeout(() => toast.remove(), 2800); } // ============================================================ // MODULE 10: PARTICLE SYSTEM // ============================================================ function initParticles() { const canvas = document.getElementById('heroParticles'); if (!canvas) return; const ctx = canvas.getContext('2d'); let particles = []; const maxParticles = 60; function resize() { const hero = document.getElementById('hero'); canvas.width = hero.offsetWidth; canvas.height = hero.offsetHeight; } resize(); window.addEventListener('resize', resize); class Particle { constructor() { this.reset(); } reset() { this.x = Math.random() * canvas.width; this.y = Math.random() * canvas.height; this.size = Math.random() * 2 + 0.5; this.speedX = (Math.random() - 0.5) * 0.4; this.speedY = (Math.random() - 0.5) * 0.4; this.opacity = Math.random() * 0.5 + 0.1; } update() { this.x += this.speedX; this.y += this.speedY; if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) this.reset(); } draw() { ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fillStyle = `rgba(147,197,253,${this.opacity})`; ctx.fill(); } } for (let i = 0; i < maxParticles; i++) particles.push(new Particle()); // Draw connections function drawConnections() { for (let i = 0; i < particles.length; i++) { for (let j = i + 1; j < particles.length; j++) { const dx = particles[i].x - particles[j].x; const dy = particles[i].y - particles[j].y; const dist = Math.sqrt(dx*dx + dy*dy); if (dist < 120) { ctx.beginPath(); ctx.moveTo(particles[i].x, particles[i].y); ctx.lineTo(particles[j].x, particles[j].y); ctx.strokeStyle = `rgba(147,197,253,${0.08 * (1 - dist/120)})`; ctx.lineWidth = 0.5; ctx.stroke(); } } } } function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); particles.forEach(p => { p.update(); p.draw(); }); drawConnections(); requestAnimationFrame(animate); } animate(); } // ============================================================ // MODULE 11: AOS - Animate on Scroll // ============================================================ function initAOS() { const cardEls = document.querySelectorAll('.grid-4 > *, .grid-3 > *, .advantage-card, .news-card, .bidding-card, .invest-card, .req-card, .stats__item, .partners__logo, .section__title, .section__subtitle, .section-header-bar'); // 先判断哪些元素已在视口内 const inViewport = new Set(); cardEls.forEach(el => { const rect = el.getBoundingClientRect(); if (rect.top < window.innerHeight + 100 && rect.bottom > -100) { inViewport.add(el); } }); // 对已在视口内的元素:跳过隐藏,直接显示 cardEls.forEach((el, i) => { if (inViewport.has(el)) { el.classList.add('aos-init', 'aos-animate'); } else { el.classList.add('aos-init', 'aos-fade-up'); el.style.transitionDelay = (i % 4) * 0.08 + 's'; } }); // specific animations for non-viewport elements document.querySelectorAll('.advantage-card:nth-child(odd).aos-fade-up').forEach(el => { el.classList.remove('aos-fade-up'); el.classList.add('aos-fade-left'); }); document.querySelectorAll('.advantage-card:nth-child(even).aos-fade-up').forEach(el => { el.classList.remove('aos-fade-up'); el.classList.add('aos-fade-right'); }); document.querySelectorAll('.section-header-bar.aos-fade-up').forEach(el => { el.classList.remove('aos-fade-up'); el.classList.add('aos-zoom-in'); }); // 对不在视口内的元素使用 IntersectionObserver const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('aos-animate'); observer.unobserve(entry.target); } }); }, { threshold: 0, rootMargin: '50px 0px 50px 0px' }); document.querySelectorAll('.aos-init:not(.aos-animate)').forEach(el => { observer.observe(el); }); // 安全回退:确保所有卡片在 1s 后都可见 setTimeout(() => { document.querySelectorAll('.aos-init:not(.aos-animate)').forEach(el => { el.classList.add('aos-animate'); }); }, 1000); } // ============================================================ // MODULE 12: SCROLL PROGRESS // ============================================================ function initScrollProgress() { window.addEventListener('scroll', () => { const winScroll = document.documentElement.scrollTop; const height = document.documentElement.scrollHeight - window.innerHeight; const scrolled = (winScroll / height) * 100; document.getElementById('scrollProgress').style.width = scrolled + '%'; }); } // ============================================================ // MODULE 13: HERO TITLE ANIMATION // ============================================================ function initHeroTitle() { const title = document.querySelector('.hero__title'); if (!title) return; // Wrap each non-space character in const walker = document.createTreeWalker(title, NodeFilter.SHOW_TEXT, null, false); const textNodes = []; while (walker.nextNode()) textNodes.push(walker.currentNode); textNodes.forEach(node => { const frag = document.createDocumentFragment(); node.textContent.split('').forEach((ch, i) => { const span = document.createElement('span'); span.className = 'char'; span.textContent = ch; span.style.animationDelay = (i * 0.03) + 's'; frag.appendChild(span); }); node.replaceWith(frag); }); } // ============================================================ // MODULE 9: 高质量数据集 // ============================================================ let currentDatasetFilter = 'all'; let currentDatasetCatFilter = 'all'; function renderDatasets() { const grid = document.getElementById('datasetGrid'); if (!grid) return; let data = (platformData.datasets && platformData.datasets.length) ? platformData.datasets : MOCK_DATASETS; if (currentDatasetFilter !== 'all') { data = data.filter(d => d.type === currentDatasetFilter); } if (currentDatasetCatFilter !== 'all') { data = data.filter(d => d.category === currentDatasetCatFilter); } // Stats const total = data.length; const supply = data.filter(d => d.type === 'supply').length; const demand = data.filter(d => d.type === 'demand').length; var elT = document.getElementById('datasetTotal'); var elS = document.getElementById('datasetSupply'); var elD = document.getElementById('datasetDemand'); if (elT) elT.textContent = total; if (elS) elS.textContent = supply; if (elD) elD.textContent = demand; grid.innerHTML = data.map(d => { const typeBadge = d.type === 'supply' ? '📤 供给' : '📥 需求'; const priceText = d.priceRange.min && d.priceRange.max ? `¥${(d.priceRange.min/10000).toFixed(1)}万 - ¥${(d.priceRange.max/10000).toFixed(1)}万` : '面议'; return `
${d.name}
${typeBadge}

${d.description.slice(0, 100)}...

${d.tags.map(t => `${t}`).join('')}
📊 ${d.scale} 📁 ${d.format}
💰 ${priceText} 📂 ${d.category}
`; }).join(''); if (data.length === 0) { grid.innerHTML = '
暂无匹配的数据集
'; } } function filterDatasets() { currentDatasetCatFilter = document.getElementById('datasetCategoryFilter').value; renderDatasets(); } function openDatasetPublish() { document.getElementById('datasetPublishOverlay').style.display = 'flex'; // Init category dropdown const sel = document.getElementById('dsCategory'); sel.innerHTML = ''; PRODUCT_CATEGORIES.forEach(c => { sel.innerHTML += ``; }); } function closeDatasetPublish(e) { if (e && e.target !== document.getElementById('datasetPublishOverlay')) return; document.getElementById('datasetPublishOverlay').style.display = 'none'; } function toggleDatasetPriceField() { const type = document.querySelector('input[name="dsPublishType"]:checked').value; document.getElementById('dsPriceGroup').style.display = type === 'supply' ? '' : 'none'; } function submitDataset() { const total = AuthManager.getTotalPublishCount(); if (total >= AuthManager.PUBLISH_TOTAL_LIMIT) { showToast(`发布总数已达上限(${AuthManager.PUBLISH_TOTAL_LIMIT}个),请先删除部分内容再发布`, 'error'); return; } const type = document.querySelector('input[name="dsPublishType"]:checked').value; const name = document.getElementById('dsName').value.trim(); const category = document.getElementById('dsCategory').value; const desc = document.getElementById('dsDesc').value.trim(); const scale = document.getElementById('dsScale').value; const format = document.getElementById('dsFormat').value.trim(); const minPrice = document.getElementById('dsPriceMin').value; const maxPrice = document.getElementById('dsPriceMax').value; if (!name) return showToast('请输入数据集名称', 'error'); if (!category) return showToast('请选择产业分类', 'error'); if (!desc) return showToast('请输入数据描述', 'error'); const newDs = { id: 'ds-' + Date.now(), name, type, category, description: desc, scale: scale || '未指定', format: format || '未指定', priceRange: { min: parseInt(minPrice) || 0, max: parseInt(maxPrice) || 0 }, postedDate: new Date().toISOString().slice(0, 10), postedBy: (AuthManager.currentUser && AuthManager.currentUser.nick) || '匿名用户', tags: [category] }; // 同时写入 platformData 和 MOCK 数据 platformData.datasets.unshift(newDs); MOCK_DATASETS.unshift(newDs); renderDatasets(); showToast('数据集发布成功!', 'success'); // 重置表单,支持连续发布 document.getElementById('dsName').value = ''; document.getElementById('dsDesc').value = ''; document.getElementById('dsScale').value = ''; document.getElementById('dsFormat').value = ''; document.getElementById('dsPriceMin').value = ''; document.getElementById('dsPriceMax').value = ''; document.getElementById('dsCategory').value = ''; // 移除AI填充高亮 ['dsName','dsDesc','dsScale','dsFormat','dsCategory'].forEach(id => { const el = document.getElementById(id); if (el) el.classList.remove('ai-filled'); }); // 清空文件列表 uploadedDatasetFiles = []; renderDatasetFileList(); } // ============================================================ // MODULE 9B: OPC 一人公司 // ============================================================ let currentOpcFilter = 'all'; function renderOpc() { const grid = document.getElementById('opcGrid'); if (!grid) return; let data = (platformData.opc && platformData.opc.length) ? platformData.opc : MOCK_OPC_IDEAS; if (currentOpcFilter !== 'all') { data = data.filter(d => d.type === currentOpcFilter); } // Stats const total = data.length; const ideas = data.filter(d => d.type === 'idea').length; const reqs = data.filter(d => d.type === 'requirement').length; var elT = document.getElementById('opcTotal'); var elI = document.getElementById('opcIdea'); var elR = document.getElementById('opcReq'); if (elT) elT.textContent = total; if (elI) elI.textContent = ideas; if (elR) elR.textContent = reqs; grid.innerHTML = data.map(d => { const typeIcon = d.type === 'idea' ? '💡' : '🛠️'; const typeLabel = d.type === 'idea' ? '创新Idea' : '技术需求'; const typeColor = d.type === 'idea' ? 'var(--indigo-500)' : 'var(--warning)'; return `
${typeIcon} ${d.title}
${typeLabel}

${d.description.slice(0, 120)}...

${d.tags.map(t => `${t}`).join('')}
🤝 ${d.seeking}
📂 ${d.category}
`; }).join(''); if (data.length === 0) { grid.innerHTML = '
暂无匹配的创意/需求
'; } } function filterOpc(filter) { currentOpcFilter = filter; renderOpc(); } function openOpcPublish() { document.getElementById('opcPublishOverlay').style.display = 'flex'; // Init category dropdown const sel = document.getElementById('opcCategory'); sel.innerHTML = ''; PRODUCT_CATEGORIES.forEach(c => { sel.innerHTML += ``; }); } function closeOpcPublish(e) { if (e && e.target !== document.getElementById('opcPublishOverlay')) return; document.getElementById('opcPublishOverlay').style.display = 'none'; } function submitOpc() { const total = AuthManager.getTotalPublishCount(); if (total >= AuthManager.PUBLISH_TOTAL_LIMIT) { showToast(`发布总数已达上限(${AuthManager.PUBLISH_TOTAL_LIMIT}个),请先删除部分内容再发布`, 'error'); return; } const type = document.querySelector('input[name="opcType"]:checked').value; const title = document.getElementById('opcTitle').value.trim(); const category = document.getElementById('opcCategory').value; const desc = document.getElementById('opcDesc').value.trim(); const seeking = document.getElementById('opcSeeking').value.trim(); if (!title) return showToast('请输入标题', 'error'); if (!category) return showToast('请选择所属领域', 'error'); if (!desc) return showToast('请输入详细描述', 'error'); const newOpc = { id: 'opc-' + Date.now(), title, type, category, description: desc, seeking: seeking || '未指定', postedDate: new Date().toISOString().slice(0, 10), postedBy: (AuthManager.currentUser && AuthManager.currentUser.nick) || '匿名用户', tags: [category] }; // 同时写入 platformData(持久化数据优先)和 MOCK_OPC_IDEAS(兜底) platformData.opc.unshift(newOpc); MOCK_OPC_IDEAS.unshift(newOpc); renderOpc(); showToast('发布成功!', 'success'); // 重置表单,支持连续发布 document.getElementById('opcTitle').value = ''; document.getElementById('opcDesc').value = ''; document.getElementById('opcSeeking').value = ''; document.getElementById('opcCategory').value = ''; // 移除AI填充高亮 ['opcTitle','opcDesc','opcSeeking','opcCategory'].forEach(id => { const el = document.getElementById(id); if (el) el.classList.remove('ai-filled'); }); // 清空文件列表 uploadedOpcFiles = []; renderOpcFileList(); } // ============================================================ // MODULE 9C: WAIC 2026 展商名录 // ============================================================ // HTML 转义辅助函数 function escHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } function escAttr(str) { if (!str) return ''; return String(str).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(//g, '>'); } // 人民币小写转大写(简化版) function toChineseAmountSimple(amt) { var units = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿']; var digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; var s = Math.round(amt * 100).toString(); var yuan = s.slice(0, -2) || '0'; var jiao = s.slice(-2, -1); var fen = s.slice(-1); var iYuan = parseInt(yuan) || 0; if (iYuan === 0) return '零元整'; var str = iYuan.toString(); var len = str.length; var result = ''; for (var i = 0; i < len; i++) { var d = parseInt(str[i]); var u = units[len - i - 1]; if (d === 0) { if (result[result.length-1] !== '零' && i < len - 1) result += '零'; } else { result += digits[d] + u; } } result = result.replace(/零+$/, ''); if (jiao === '0' && fen === '0') result += '元整'; else { result += '元'; if (jiao !== '0') result += digits[parseInt(jiao)] + '角'; if (fen !== '0') result += digits[parseInt(fen)] + '分'; } return result; } let waicCurrentFilter = 'all'; function filterWaicExhibitors(hall, btnEl) { if (hall !== undefined) { waicCurrentFilter = hall; document.querySelectorAll('#waicExhibitors .bidding-filter-btn').forEach(b => b.classList.remove('active')); if (btnEl) btnEl.classList.add('active'); } renderWaicExhibitors(); } function renderWaicExhibitors() { const grid = document.getElementById('waicGrid'); if (!grid) return; const empty = document.getElementById('waicEmpty'); const catFilter = document.getElementById('waicCategoryFilter')?.value || 'all'; const search = (document.getElementById('waicSearchInput')?.value || '').toLowerCase(); let data = (platformData.waic && platformData.waic.length) ? platformData.waic : MOCK_WAIC_EXHIBITORS; if (waicCurrentFilter !== 'all') data = data.filter(e => e.hall === waicCurrentFilter); if (catFilter !== 'all') data = data.filter(e => e.category === catFilter); if (search) data = data.filter(e => e.name.toLowerCase().includes(search) || e.description.toLowerCase().includes(search) || e.products.toLowerCase().includes(search) || e.tags.some(t => t.toLowerCase().includes(search))); if (data.length === 0) { grid.innerHTML = ''; if (empty) empty.style.display = 'block'; return; } if (empty) empty.style.display = 'none'; const hallClass = (h) => { if (h === 'H1') return 'waic-card__hall--h1'; if (h === 'H2') return 'waic-card__hall--h2'; if (h === 'H3') return 'waic-card__hall--h3'; if (h === 'Zhangjiang') return 'waic-card__hall--zj'; return 'waic-card__hall--west'; }; const hallLabel = (h) => { if (h === 'H1') return '🖥️ H1'; if (h === 'H2') return '🔬 H2'; if (h === 'H3') return '🤖 H3'; if (h === 'Zhangjiang') return '💎 张江'; return '🌊 西岸'; }; grid.innerHTML = data.map(e => `
${escHtml(e.name)} ${hallLabel(e.hall)}
${escHtml(e.category)}
${escHtml(e.description)}
展品:${escHtml(e.products)}
`).join(''); } // ============================================================ // MODULE 10: INIT // ============================================================ function initApp() { console.log('[Init] === 开始初始化 AI+ 平台 ==='); console.log('[Init] User-Agent:', navigator.userAgent); // 加载平台数据(优先从后台 localStorage 读取) loadPlatformData(); console.log('[Init] 数据来源:', platformDataSource); console.log('[Init] platformData 内容: providers=' + platformData.providers.length + ', requirements=' + platformData.requirements.length + ', news=' + platformData.news.length + ', biddings=' + platformData.biddings.length + ', datasets=' + platformData.datasets.length + ', opc=' + platformData.opc.length + ', waic=' + platformData.waic.length); // 初始化筛选器 var catSelect = document.getElementById('filterCategory'); if (catSelect) { CATEGORIES.forEach(c => { if (c.id !== 'all') { var opt = document.createElement('option'); opt.value = c.id; opt.textContent = c.name; catSelect.appendChild(opt); } }); } var locSelect = document.getElementById('filterLocation'); if (locSelect) { LOCATIONS.forEach(l => { var opt = document.createElement('option'); opt.value = l; opt.textContent = l; locSelect.appendChild(opt); }); } // 初始化需求发布表单分类 var reqCatSelect = document.getElementById('reqCategory'); if (reqCatSelect) { CATEGORIES.filter(function(c) { return c.id !== 'all'; }).forEach(function(c) { var opt = document.createElement('option'); opt.value = c.id; opt.textContent = c.icon + ' ' + c.name; reqCatSelect.appendChild(opt); }); } // 初始化轮播 try { carousel.init(); } catch(e) { console.error('carousel.init error:', e); } // 初始化wizard try { wizard.updateUI(); } catch(e) { console.error('wizard.updateUI error:', e); } // 渲染默认服务商 try { renderProviders(platformData.providers); console.log('[Init] renderProviders 完成'); } catch(e) { console.error('[Init] renderProviders error:', e.message, e.stack); } // 渲染行业资讯 try { renderNews(); console.log('[Init] renderNews 完成'); } catch(e) { console.error('[Init] renderNews error:', e.message, e.stack); } // 渲染标讯 try { renderBiddings(); console.log('[Init] renderBiddings 完成'); } catch(e) { console.error('[Init] renderBiddings error:', e.message, e.stack); } // 渲染投资信息 try { renderInvestments(); console.log('[Init] renderInvestments 完成'); } catch(e) { console.error('[Init] renderInvestments error:', e.message, e.stack); } // 初始化数据集分类筛选 var dsCatFilter = document.getElementById('datasetCategoryFilter'); if (dsCatFilter) { PRODUCT_CATEGORIES.forEach(function(c) { dsCatFilter.innerHTML += ''; }); } // 渲染数据集 try { renderDatasets(); console.log('[Init] renderDatasets 完成'); } catch(e) { console.error('[Init] renderDatasets error:', e.message, e.stack); } // 渲染OPC一人公司 try { renderOpc(); console.log('[Init] renderOpc 完成'); } catch(e) { console.error('[Init] renderOpc error:', e.message, e.stack); } // 渲染WAIC展商名录 try { renderWaicExhibitors(); console.log('[Init] renderWaicExhibitors 完成'); } catch(e) { console.error('[Init] renderWaicExhibitors error:', e.message, e.stack); } // 渲染AI+终端商城 try { renderTerminalProducts(); console.log('[Init] renderTerminalProducts 完成'); } catch(e) { console.error('[Init] renderTerminalProducts error:', e.message, e.stack); } // 更新终端商城统计 try { updateTerminalStats(); } catch(e) { console.error('[Init] updateTerminalStats error:', e.message); } // 数据集筛选按钮 document.querySelectorAll('#datasetFilters .bidding-filter-btn').forEach(btn => { btn.addEventListener('click', function() { document.querySelectorAll('#datasetFilters .bidding-filter-btn').forEach(b => b.classList.remove('active')); this.classList.add('active'); currentDatasetFilter = this.dataset.filter; renderDatasets(); }); }); // OPC筛选按钮 document.querySelectorAll('#opcFilters .bidding-filter-btn').forEach(btn => { btn.addEventListener('click', function() { document.querySelectorAll('#opcFilters .bidding-filter-btn').forEach(b => b.classList.remove('active')); this.classList.add('active'); filterOpc(this.dataset.filter); }); }); // 行业资讯筛选按钮 document.querySelectorAll('.news-filter-btn').forEach(btn => { btn.addEventListener('click', function() { document.querySelectorAll('.news-filter-btn').forEach(b => b.classList.remove('active')); this.classList.add('active'); renderNews(this.dataset.filter); }); }); // 标讯筛选按钮 - 仅在标讯区域绑定 document.querySelectorAll('#biddingFilters .bidding-filter-btn, #biddingInfo .bidding-filter-btn').forEach(btn => { btn.addEventListener('click', function() { document.querySelectorAll('.bidding-filter-btn').forEach(b => b.classList.remove('active')); this.classList.add('active'); renderBiddings(this.dataset.filter, { resetLimit: true }); }); }); // 投资信息筛选按钮 document.querySelectorAll('#investFilters .invest-filter-btn, #investInfo .invest-filter-btn').forEach(btn => { btn.addEventListener('click', function() { document.querySelectorAll('.invest-filter-btn').forEach(b => b.classList.remove('active')); this.classList.add('active'); renderInvestments(this.dataset.filter); }); }); // ============================================================ // 事件委托:服务商卡片 & 需求卡片 点击进入详情 // ============================================================ var providerGrid = document.getElementById('providerGrid'); var requirementGrid = document.getElementById('requirementGrid'); if (providerGrid) { providerGrid.addEventListener('click', function(e) { var card = e.target.closest('[data-provider-id]'); if (card) showProviderDetail(card.getAttribute('data-provider-id')); }); } if (requirementGrid) { requirementGrid.addEventListener('click', function(e) { var card = e.target.closest('[data-req-id]'); if (card) showRequirementDetail(card.getAttribute('data-req-id')); }); } // 导航滚动阴影 window.addEventListener('scroll', () => { document.getElementById('topNav').classList.toggle('scrolled', window.scrollY > 10); }); // 关闭菜单 document.addEventListener('click', (e) => { if (!e.target.closest('.nav__inner')) { document.getElementById('navLinks').classList.remove('open'); } }); // 初始化增强功能 initParticles(); initHeroTitle(); initScrollProgress(); // 初始化认证系统 AuthManager.init(); // 后台从数据库加载用户列表 setTimeout(function () { AuthManager.loadUsersFromApi(); }, 500); // 绑定登录/注册表单提交事件 const loginForm = document.getElementById('loginForm'); const regForm = document.getElementById('registerForm'); if (loginForm) loginForm.addEventListener('submit', handleLogin); if (regForm) regForm.addEventListener('submit', handleRegister); // 输入时实时清除错误提示 const inputErrorMap = { loginAccount: 'loginAccountError', loginPassword: 'loginPasswordError', loginCode: 'loginCodeError', regName: 'regNameError', regNick: 'regNickError', regAccount: 'regAccountError', regCode: 'regCodeError', regPassword: 'regPasswordError', regPassword2: 'regPassword2Error' }; Object.entries(inputErrorMap).forEach(([inputId, errId]) => { const el = document.getElementById(inputId); const errEl = document.getElementById(errId); if (el && errEl) { el.addEventListener('input', () => { el.classList.remove('auth-input-error'); errEl.classList.remove('show'); }); } }); // ESC 关闭弹窗 document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { var authOverlay = document.getElementById('authModalOverlay'); if (authOverlay && authOverlay.style.display === 'flex') closeAuthModal(); var certOverlay = document.getElementById('certModalOverlay'); if (certOverlay && certOverlay.style.display === 'flex') closeCertCenter(); var detailOverlay = document.getElementById('detailModalOverlay'); if (detailOverlay && detailOverlay.style.display === 'flex') closeDetailModal(); var publishOverlay = document.getElementById('publishModalOverlay'); if (publishOverlay && publishOverlay.style.display === 'flex') closePublishModal(); var wechatOverlay = document.getElementById('wechatPayOverlay'); if (wechatOverlay && wechatOverlay.classList.contains('show')) closeWechatPayModal(); } }); // 延迟初始化 AOS(等卡片渲染完成) setTimeout(initAOS, 200); // 安全网:1秒后确认平台状态 setTimeout(function() { try { updateStatusBar('平台就绪 \u2713', '#6366f1'); } catch(e) { console.error('[Safety] 安全网失败:', e.message); } }, 1000); console.log('[Init] ===================================='); console.log('[Init] AI+ 供需对接平台 v2.0 初始化完成'); console.log('[Init] 数据来源: ' + platformDataSource); console.log('[Init] 服务商 ' + platformData.providers.length + ' | 需求 ' + platformData.requirements.length + ' | 资讯 ' + platformData.news.length); console.log('[Init] 标讯 ' + platformData.biddings.length + ' | 立项项目 ' + platformData.projects.length + ' | 投融资 ' + platformData.investments.length + ' | 数据集 ' + platformData.datasets.length); console.log('[Init] OPC ' + platformData.opc.length + ' | WAIC ' + platformData.waic.length); console.log('[Init] ===================================='); updateStatusBar('平台初始化完成 \u2713 ' + platformData.providers.length + ' 服务商 · ' + platformData.requirements.length + ' 需求', '#6366f1'); // 初始化统计数据和页脚 updateStats(); renderFooterContent(); } // ============================================================ // 统计数据动画 + 页脚内容渲染 + 页脚弹窗 // ============================================================ // 默认站点设置(可被管理后台覆盖) const DEFAULT_SITE_SETTINGS = { brandName: '惠捷同城', brandDesc: '惠捷同城 智能供需对接平台 —— 用 AI 连接需求方与服务商,让每一次合作都精准高效。', domain: 'hj0471.com', copyright: '© 2026 惠捷同城 hj0471.com. All rights reserved. 让 AI 连接供需,让合作更高效。', contactPhone: '15024994942', contactEmail: 'service@hj0471.com', contactAddr: '内蒙古呼和浩特市', serviceTime: '8:00-18:00', wechatQr: '', productServices: [ { name: 'AI 智能搜索', url: '#hero' }, { name: '服务商查找', url: '#providers' }, { name: '需求发布', url: '#publishModal' }, { name: '广告投放', url: '#adModal' } ], aboutUs: [ { name: '平台介绍', content: '惠捷同城是专注于AI领域的智能供需对接平台,致力于用人工智能技术连接需求方与服务商。平台汇聚120+城市的1250+认证服务商,覆盖AI算力、软件开发、设计创意等15+领域,为企业和个人提供精准高效的供需匹配服务。' }, { name: '合作生态', content: '我们与华为云、阿里云、腾讯云、百度AI、字节跳动、商汤科技、科大讯飞、智谱AI等头部企业建立深度合作关系,共同构建AI产业生态。通过技术共享、资源互补,为平台用户提供更优质的服务体验。' }, { name: '加入我们', content: '惠捷同城正在快速发展,我们欢迎有志于AI产业的人才加入。岗位包括:AI算法工程师、全栈开发工程师、产品经理、商务拓展等。简历请投递至 service@hj0471.com,邮件标题请注明"应聘+岗位"。' }, { name: '联系我们', content: '联系人:姚杰\n联系电话:15024994942\n电子邮箱:service@hj0471.com\n办公地址:内蒙古呼和浩特市\n服务时间:8:00-18:00' } ], legalInfo: [ { name: '用户协议', content: '欢迎使用惠捷同城智能供需对接平台。使用本平台服务即表示您同意以下条款:\n\n1. 用户应如实填写注册信息,不得冒用他人身份。\n2. 发布的需求、产品、数据集等信息应真实有效,不得包含虚假内容。\n3. 用户不得发布违反法律法规的内容,包括但不限于涉政、涉黄、涉暴内容。\n4. 平台有权对违规内容和账号进行处理,包括警告、下架、封禁等。\n5. 用户应遵守交易规则,通过平台进行供需对接。\n6. 平台不对用户间交易结果承担担保责任。\n7. 本协议解释权归惠捷同城所有。' }, { name: '隐私政策', content: '惠捷同城高度重视用户隐私保护,本政策说明我们如何收集、使用和保护您的信息:\n\n1. 信息收集:我们收集您注册时填写的姓名、公司名称、联系方式等信息。\n2. 信息使用: collected信息仅用于平台供需对接服务,不会用于其他用途。\n3. 信息保护:我们采用加密存储、访问控制等技术手段保护您的信息安全。\n4. 信息共享:未经您同意,我们不会向第三方共享您的个人信息。\n5. Cookie使用:平台使用Cookie来改善用户体验,您可通过浏览器设置管理Cookie。\n6. 用户权利:您有权查看、修改、删除个人信息,如有需要请联系客服。\n7. 政策更新:本政策可能更新,更新后将在平台公示。' }, { name: '服务条款', content: '惠捷同城平台服务条款:\n\n1. 认证服务:企业认证需缴纳保证金¥10000,有效期1年,到期后需重新认证。\n2. 发布额度:认证后可发布10项内容(产品方案/数据集/OPC共享额度)。\n3. 保证金说明:保证金在认证到期且无违规情况下可申请退还。\n4. 广告服务:平台提供首页轮播图、推荐位等广告位,具体价格请联系商务。\n5. 数据使用:平台展示的数据集、标讯等信息仅供参考,用户应自行核实。\n6. 知识产权:平台内容版权归惠捷同城所有,未经授权不得转载。\n7. 免责声明:因不可抗力导致服务中断,平台不承担责任。\n8. 条款修改:平台保留修改服务条款的权利,修改后将在平台公示。' } ] }; function getSiteSettings() { try { const stored = localStorage.getItem('hj_site_settings'); if (stored) return Object.assign({}, DEFAULT_SITE_SETTINGS, JSON.parse(stored)); } catch(e) {} return DEFAULT_SITE_SETTINGS; } function updateStats() { const providers = (platformData.providers || []).length; const requirements = (platformData.requirements || []).length; const biddings = (platformData.biddings || []).length; const datasets = (platformData.datasets || []).length; animateCounter('statsProviders', providers); animateCounter('statsRequirements', requirements); animateCounter('statsBiddings', biddings); animateCounter('statsDatasets', datasets); } function animateCounter(id, target) { const el = document.getElementById(id); if (!el) return; const current = parseInt(el.textContent.replace(/[^0-9]/g, '')) || 0; if (current === target) { el.textContent = target + '+'; return; } const duration = 1200; const steps = 30; const stepValue = (target - current) / steps; let step = 0; const timer = setInterval(() => { step++; if (step >= steps) { el.textContent = target + '+'; clearInterval(timer); } else { el.textContent = Math.round(current + stepValue * step) + '+'; } }, duration / steps); } function renderFooterContent() { const s = getSiteSettings(); // 品牌区 const brandName = document.querySelector('.footer__brand-name'); if (brandName) brandName.textContent = s.brandName; const brandDesc = document.querySelector('.footer__brand-desc'); if (brandDesc) brandDesc.textContent = s.brandDesc; const domainLink = document.querySelector('.footer__domain'); if (domainLink) { domainLink.href = 'https://' + s.domain; domainLink.textContent = '🌐 ' + s.domain; } // 联系信息 const contactItems = document.querySelectorAll('.footer__contact-item'); if (contactItems.length >= 3) { contactItems[0].innerHTML = '📞 ' + (s.contactPhone || ''); contactItems[1].innerHTML = '📧 ' + (s.contactEmail || ''); contactItems[2].innerHTML = '🕐 服务时间 ' + (s.serviceTime || ''); } // 产品服务 const productCol = document.querySelector('#footerProductLinks'); if (productCol) { productCol.innerHTML = (s.productServices || []).map(item => `${item.name}` ).join(''); } // 关于我们 const aboutCol = document.querySelector('#footerAboutLinks'); if (aboutCol) { aboutCol.innerHTML = (s.aboutUs || []).map((item, i) => `${item.name}` ).join(''); } // 法律信息 const legalCol = document.querySelector('#footerLegalLinks'); if (legalCol) { legalCol.innerHTML = (s.legalInfo || []).map((item, i) => `${item.name}` ).join(''); } // 底部版权 const copyright = document.getElementById('footerCopyright'); if (copyright) copyright.textContent = s.copyright; const bottom = document.querySelector('.footer__bottom'); if (bottom && !document.querySelector('.footer__bottom-links')) { // fallback if bottom-links not found bottom.innerHTML = '' + escHtml(s.copyright) + ''; } } function footerLinkClick(name, url) { if (name === '广告投放') { openFooterModal('ad'); } else if (url && url.startsWith('#') && url !== '#') { const target = url.substring(1); if (target === 'publishModal') { openPublishModal(); } else { smoothScroll(target); } } else { smoothScroll('hero'); } } function openFooterModal(type, index) { const s = getSiteSettings(); let title = '', body = '', maxWidth = '640px'; if (type === 'about') { const item = (s.aboutUs || [])[index]; if (!item) return; title = item.name; if (index === 0) { // 平台介绍 maxWidth = '720px'; body = `
🏢
惠捷同城
智能供需对接平台 —— 用 AI 连接需求方与服务商,让每一次合作都精准高效
120+
覆盖城市
1250+
认证服务商
15+
专业领域
98%
客户满意度
🤖
AI 智能匹配
基于大模型的智能搜索引擎,精准匹配供需双方
企业认证体系
严格的企业认证 + 保证金机制,保障交易安全
📊
多维数据服务
产品方案、数据集、OPC创意一站式发布管理
💬
AI 在线咨询
智能对话系统,7×24 小时供需沟通不停歇
${item.content}
`; } else if (index === 1) { // 合作生态 maxWidth = '720px'; body = `
🤝
合作生态
与头部企业共建 AI 产业生态,技术共享、资源互补
${item.content}
🏆 战略合作伙伴
华为云
阿里云
腾讯云
百度AI
字节跳动
商汤科技
科大讯飞
智谱AI
🔧
技术合作
共享 AI 算力、大模型能力、云基础设施
📦
资源互补
数据集共享、服务商互通、渠道协同
🎓
人才培养
联合培训、技术认证、行业峰会
🚀
联合创新
共建行业解决方案、联合实验室
`; } else if (index === 2) { // 加入我们 maxWidth = '720px'; body = `
💼
加入我们
与优秀的人一起,用 AI 改变供需对接的方式
${item.content}
🎯 热招岗位
🧠
AI 算法工程师
负责推荐算法、NLP、大模型应用研发
💻
全栈开发工程师
前端 React/Vue + 后端 Node.js/Python
📋
产品经理
负责平台产品规划、需求设计、项目管理
📢
商务拓展
开拓服务商资源、建立行业合作生态
💎 福利待遇
💰
有竞争力的薪资
🎓
完善的培训体系
🌱
清晰的成长路径
弹性工作制
`; } else if (index === 3) { // 联系我们 maxWidth = '680px'; body = `
📞
联系我们
随时欢迎您与我们取得联系,我们将竭诚为您服务
📱
联系电话
${s.contactPhone || '15024994942'}
📧
电子邮箱
${s.contactEmail || 'service@hj0471.com'}
📍
办公地址
${s.contactAddr || '内蒙古呼和浩特市'}
🕐
服务时间
${s.serviceTime || '8:00-18:00'}
💬
微信客服
公众号
惠捷同城
微信公众号
`; } } else if (type === 'legal') { const item = (s.legalInfo || [])[index]; if (!item) return; title = item.name; maxWidth = '680px'; // 将内容按编号分段 var sections = item.content.split(/\n(?=\d+\.)/).filter(function(s){return s.trim();}); var heroIcons = ['📜', '🔒', '⚙️']; var heroColors = ['fm-hero--blue', 'fm-hero--indigo', 'fm-hero--cyan']; body = `
${heroIcons[index] || '📄'}
${item.name}
最后更新:2026年7月 · 惠捷同城 hj0471.com
'; } else if (type === 'ad') { title = '广告投放'; maxWidth = '720px'; body = `
📢
广告投放
精准触达 AI 供需两端客户,多种广告位任您选择
🖼️
首页轮播图
首页顶部大图轮播展示,全站最高曝光位置
高曝光
推荐服务商位
服务商列表顶部推荐位,精准获客
精准获客
🏷️
频道冠名
标讯/数据集/OPC 频道冠名展示
品牌曝光
📌
悬浮广告位
侧边悬浮广告,全屏跟随展示
持续展示
📞 商务合作请联系:${s.contactPhone || '15024994942'} 📧 ${s.contactEmail || 'service@hj0471.com'}
`; } // 使用已有的详情弹窗 let overlay = document.getElementById('footerModalOverlay'); if (!overlay) { overlay = document.createElement('div'); overlay.id = 'footerModalOverlay'; overlay.className = 'modal-overlay'; overlay.style.cssText = 'display:flex;z-index:10001;'; overlay.onclick = function(e) { if (e.target === overlay) closeFooterModal(); }; overlay.innerHTML = ` `; document.body.appendChild(overlay); } document.getElementById('footerModalInner').style.maxWidth = maxWidth; document.getElementById('footerModalTitle').textContent = title; document.getElementById('footerModalBody').innerHTML = body; overlay.style.display = 'flex'; // 滚动到顶部 document.getElementById('footerModalBody').scrollTop = 0; } function closeFooterModal() { const overlay = document.getElementById('footerModalOverlay'); if (overlay) overlay.style.display = 'none'; } // ============================================================ // AI+终端商城 MODULE - 商品展示 / 发布 / 详情 / 交易 // ============================================================ const TERMINAL_CATEGORY_MAP = { glasses: { icon: '👓', name: 'AI眼镜' }, ring: { icon: '💍', name: '智能戒指' }, watch: { icon: '⌚', name: '智能手表' }, earphone: { icon: '🎧', name: 'AI耳机' }, other: { icon: '📦', name: '其他终端' } }; let terminalFilter = 'all'; let terminalSearchKeyword = ''; function getTerminalProducts() { if (platformData.terminalProducts && platformData.terminalProducts.length) { return platformData.terminalProducts; } return MOCK_TERMINAL_PRODUCTS; } function renderTerminalProducts() { var data = getTerminalProducts(); var grid = document.getElementById('terminalGrid'); var empty = document.getElementById('terminalEmpty'); if (!grid) return; var filtered = data.filter(function(p) { var matchFilter = terminalFilter === 'all' || p.category === terminalFilter; var matchSearch = !terminalSearchKeyword || (p.name && p.name.toLowerCase().indexOf(terminalSearchKeyword) >= 0) || (p.brand && p.brand.toLowerCase().indexOf(terminalSearchKeyword) >= 0); return matchFilter && matchSearch; }); if (filtered.length === 0) { grid.innerHTML = ''; if (empty) empty.style.display = 'block'; return; } if (empty) empty.style.display = 'none'; grid.innerHTML = filtered.map(function(p) { var cat = TERMINAL_CATEGORY_MAP[p.category] || TERMINAL_CATEGORY_MAP.other; var badgeHtml = ''; if (p.badge === 'hot') badgeHtml = '🔥 热销'; else if (p.badge === 'new') badgeHtml = '✨ 新品'; var imgHtml = p.image ? '' + escHtml(p.name) + '' : cat.icon; var specsHtml = (p.specs || '').split('|').filter(function(s){return s.trim();}).slice(0, 3).map(function(s) { return '' + escHtml(s.trim()) + ''; }).join(''); var descPreview = p.description ? (p.description.length > 60 ? p.description.slice(0, 60) + '...' : p.description) : ''; return '
' + '
' + badgeHtml + imgHtml + '
' + '
' + '
' + cat.icon + ' ' + escHtml(p.brand || '未知品牌') + '
' + '
' + escHtml(p.name) + '
' + '
' + escHtml(descPreview) + '
' + '
' + specsHtml + '
' + '' + '
🏪 ' + escHtml(p.seller || p.postedBy || '未知商家') + ' · 已售' + (p.deals || 0) + '件
' + '
' + '
'; }).join(''); } function filterTerminalProducts(filter, btn) { if (filter) terminalFilter = filter; if (btn) { document.querySelectorAll('#terminalFilters .bidding-filter-btn').forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); } var searchInput = document.getElementById('terminalSearchInput'); terminalSearchKeyword = searchInput ? searchInput.value.toLowerCase().trim() : ''; renderTerminalProducts(); } function openTerminalPublish() { // 认证门控检查 if (!AuthManager.currentUser) { showToast('请先登录后再发布商品', 'info'); openAuthModal('login'); return; } var certStatus = AuthManager.getCertStatus(); if (certStatus !== 'approved') { showToast('请先完成企业认证后再发布商品', 'warning'); openCertCenter('cert'); return; } _tpFaqItems = []; renderTpFaqList(); var overlay = document.getElementById('terminalPublishOverlay'); if (overlay) overlay.style.display = 'flex'; } // 终端商城发布 - 图册管理 var _tpGalleryItems = []; var _tpRichBlocks = []; function addTerminalGalleryItem() { var input = document.getElementById('tpGalleryInput'); if (!input || !input.value.trim()) return; _tpGalleryItems.push(input.value.trim()); input.value = ''; renderTpGalleryList(); } function removeTerminalGalleryItem(idx) { _tpGalleryItems.splice(idx, 1); renderTpGalleryList(); } function renderTpGalleryList() { var el = document.getElementById('tpGalleryList'); if (!el) return; el.innerHTML = _tpGalleryItems.map(function(url, i) { return '
' + '' + '' + '
'; }).join(''); } function addTerminalRichBlock() { var titleEl = document.getElementById('tpRichTitle'); var imgEl = document.getElementById('tpRichImg'); var textEl = document.getElementById('tpRichText'); var title = titleEl ? titleEl.value.trim() : ''; var img = imgEl ? imgEl.value.trim() : ''; var text = textEl ? textEl.value.trim() : ''; if (!title && !text) { showToast('请输入段落标题或内容', 'warning'); return; } _tpRichBlocks.push({ title: title, image: img, text: text }); if (titleEl) titleEl.value = ''; if (imgEl) imgEl.value = ''; if (textEl) textEl.value = ''; renderTpRichList(); } function removeTerminalRichBlock(idx) { _tpRichBlocks.splice(idx, 1); renderTpRichList(); } function renderTpRichList() { var el = document.getElementById('tpRichList'); if (!el) return; if (!_tpRichBlocks.length) { el.innerHTML = ''; return; } el.innerHTML = _tpRichBlocks.map(function(b, i) { return '
' + '' + (b.image ? '🖼️' : '📝') + '' + '' + escHtml(b.title || '(无标题)') + '' + '' + '
'; }).join(''); } function closeTerminalPublish(event) { if (event && event.target !== event.currentTarget) return; var overlay = document.getElementById('terminalPublishOverlay'); if (overlay) overlay.style.display = 'none'; // 清空表单 ['tpName','tpBrand','tpPrice','tpImage','tpDesc','tpSpecs','tpStock','tpGalleryInput','tpRichTitle','tpRichImg','tpRichText'].forEach(function(id) { var el = document.getElementById(id); if (el) el.value = ''; }); var catSelect = document.getElementById('tpCategory'); if (catSelect) catSelect.value = ''; var stockInput = document.getElementById('tpStock'); if (stockInput) stockInput.value = '100'; // 清空图册和图文 _tpGalleryItems = []; _tpRichBlocks = []; renderTpGalleryList(); renderTpRichList(); // 清空 AI 区域 var fileList = document.getElementById('terminalFileList'); if (fileList) fileList.innerHTML = ''; var aiProgress = document.getElementById('terminalAiProgress'); if (aiProgress) aiProgress.style.display = 'none'; terminalUploadFiles = []; } function submitTerminalProduct() { var name = document.getElementById('tpName').value.trim(); var category = document.getElementById('tpCategory').value; var brand = document.getElementById('tpBrand').value.trim(); var price = document.getElementById('tpPrice').value.trim(); var image = document.getElementById('tpImage').value.trim(); var desc = document.getElementById('tpDesc').value.trim(); var specs = document.getElementById('tpSpecs').value.trim(); var stock = document.getElementById('tpStock').value.trim() || '100'; if (!name) { showToast('请输入商品名称', 'warning'); return; } if (!category) { showToast('请选择商品分类', 'warning'); return; } if (!price) { showToast('请输入商品价格', 'warning'); return; } if (!desc) { showToast('请输入商品描述', 'warning'); return; } var user = AuthManager.currentUser; var userName = user.nick || user.name || '匿名商家'; var newProduct = { id: 'tp-' + Date.now(), name: name, category: category, brand: brand, price: parseFloat(price), image: image, gallery: _tpGalleryItems.slice(), richContent: _tpRichBlocks.slice(), description: desc, specs: specs, stock: parseInt(stock), seller: userName + '的店铺', sellerPhone: user.phone || user.account || '', postedDate: new Date().toLocaleDateString('zh-CN'), postedBy: userName, badge: 'new', deals: 0, faq: _tpFaqItems.slice() }; // 写入 platformData if (!platformData.terminalProducts) platformData.terminalProducts = []; platformData.terminalProducts.unshift(newProduct); try { localStorage.setItem(PLATFORM_DATA_KEY, JSON.stringify(platformData)); } catch(e) {} closeTerminalPublish(); renderTerminalProducts(); updateTerminalStats(); showToast('商品发布成功!', 'success'); } function showTerminalDetail(id) { var data = getTerminalProducts(); var p = data.find(function(x) { return x.id === id; }); if (!p) return; var cat = TERMINAL_CATEGORY_MAP[p.category] || TERMINAL_CATEGORY_MAP.other; var badgeHtml = ''; if (p.badge === 'hot') badgeHtml = ' 🔥 热销'; else if (p.badge === 'new') badgeHtml = ' ✨ 新品'; // 构建画廊图片列表 var galleryImgs = []; if (p.image) galleryImgs.push(p.image); if (p.gallery && p.gallery.length) { p.gallery.forEach(function(g) { if (galleryImgs.indexOf(g) < 0) galleryImgs.push(g); }); } var hasGallery = galleryImgs.length > 0; _terminalDetailGallery = galleryImgs; _terminalDetailGalleryIndex = 0; // 画廊HTML var galleryHtml = ''; if (hasGallery) { var mainImg = galleryImgs[0]; galleryHtml = ''; } else { galleryHtml = ''; } // 规格参数解析 var specsRows = ''; if (p.specs) { specsRows = p.specs.split('|').filter(function(s){return s.trim();}).map(function(s) { var parts = s.trim().split(':'); var key = parts[0] ? parts[0].trim() : ''; var val = parts[1] ? parts[1].trim() : ''; return '
' + escHtml(key) + '' + escHtml(val) + '
'; }).join(''); } // 图文详情区块 var richHtml = ''; if (p.richContent && p.richContent.length) { richHtml = '
' + '
📖 图文详情
'; p.richContent.forEach(function(block) { richHtml += '
'; if (block.title) richHtml += '
▸ ' + escHtml(block.title) + '
'; if (block.image) richHtml += '
'; if (block.text) richHtml += '
' + escHtml(block.text) + '
'; richHtml += '
'; }); richHtml += '
'; } var body = galleryHtml + '
' + '
' + escHtml(p.name) + badgeHtml + '
' + '
' + cat.icon + ' ' + escHtml(p.brand || '未知品牌') + ' · ' + cat.name + '
' + '
' + '¥' + escHtml(String(p.price || 0)) + '' + '/ 件' + '
' + '
' + '
🏪 商家' + escHtml(p.seller || p.postedBy || '未知') + '
' + '
📦 库存' + escHtml(String(p.stock || 0)) + ' 件
' + '
🔥 已售' + escHtml(String(p.deals || 0)) + ' 件
' + '
📅 发布' + escHtml(p.postedDate || '') + '
' + '
' + '
' + '' + '' + '
' + '
'; // 保障提示 body += '
' + '✅ 平台认证商家' + '🔒 担保交易' + '🚚 全国配送' + '↩️ 7天无理由' + '💚 微信支付' + '
'; if (specsRows) { body += '
' + '
📋 规格参数
' + specsRows + '
'; } body += '
' + '
📝 商品简介
' + '
' + escHtml(p.description || '') + '
' + '
'; body += richHtml; openDetail(p.name, body); } // 画廊切换 var _terminalDetailGallery = []; var _terminalDetailGalleryIndex = 0; function switchTerminalGallery(idx) { _terminalDetailGalleryIndex = idx; var main = document.getElementById('tdGalleryMain'); if (!main || !_terminalDetailGallery[idx]) return; var badge = main.querySelector('.td-gallery__badge'); var img = main.querySelector('img'); if (img) img.src = _terminalDetailGallery[idx]; if (badge) badge.textContent = (idx + 1) + ' / ' + _terminalDetailGallery.length; // 更新缩略图高亮 var thumbs = main.parentNode.querySelectorAll('.td-gallery__thumb'); thumbs.forEach(function(t, i) { t.classList.toggle('td-gallery__thumb--active', i === idx); }); } // 终端商城购买 - 当前选中的支付方式 var _terminalPayMethod = 'wechat'; var _terminalPayTimer = null; var _terminalPayCountdown = null; function buyTerminalProduct(id) { if (!AuthManager.currentUser) { showToast('请先登录后再购买', 'info'); openAuthModal('login'); return; } var data = getTerminalProducts(); var p = data.find(function(x) { return x.id === id; }); if (!p) return; if (p.stock <= 0) { showToast('抱歉,该商品已售罄', 'warning'); return; } _terminalPayMethod = 'wechat'; var cat = TERMINAL_CATEGORY_MAP[p.category] || TERMINAL_CATEGORY_MAP.other; var imgHtml = p.image ? '' : cat.icon; // 确认下单 + 支付方式选择 var body = '
' + // 商品摘要 '
' + '
' + imgHtml + '
' + '
' + '
' + escHtml(p.name) + '
' + '
' + escHtml(p.brand || '') + ' · 库存' + escHtml(String(p.stock)) + '件
' + '
' + '
' + '
¥' + escHtml(String(p.price)) + '
' + '
' + '
' + // 订单信息 '
' + '
📦 订单信息
' + '
' + '商家:' + escHtml(p.seller || p.postedBy || '') + '
' + '配送:全国包邮(预计3-5个工作日)
' + '保障:平台担保交易 · 7天无理由退换
' + '
' + '
' + // 支付方式 '
' + '
💳 选择支付方式
' + '
' + '
' + '
💚
' + '
微信支付
' + '
推荐 · 安全便捷
' + '
' + '
' + '
💙
' + '
支付宝
' + '
快捷支付
' + '
' + '
' + '
' + // 金额 '
' + '实付金额' + '¥' + escHtml(String(p.price)) + '' + '
' + // 按钮 '
' + '' + '' + '
' + '
'; openDetail('确认订单', body); } function selectTerminalPayMethod(method) { _terminalPayMethod = method; var wechat = document.getElementById('payMethodWechat'); var alipay = document.getElementById('payMethodAlipay'); if (wechat) wechat.classList.toggle('wx-pay__method--active', method === 'wechat'); if (alipay) alipay.classList.toggle('wx-pay__method--active', method === 'alipay'); } function confirmTerminalOrder(id) { var data = getTerminalProducts(); var p = data.find(function(x) { return x.id === id; }); if (!p) return; var orderId = 'HJ' + Date.now().toString().slice(-10); var payLabel = _terminalPayMethod === 'wechat' ? '微信支付' : '支付宝'; var payColor = _terminalPayMethod === 'wechat' ? '#07c160' : '#1677ff'; var payIcon = _terminalPayMethod === 'wechat' ? '💚' : '💙'; // 生成模拟二维码(SVG图案) var qrSvg = generateMockQRCode(); var body = '
' + '
' + payIcon + ' ' + payLabel + '
' + '
¥' + escHtml(String(p.price)) + '
' + '
' + escHtml(p.name) + '
' + '
' + '' + '
' + qrSvg + '
' + '
' + '
请打开' + (_terminalPayMethod === 'wechat' ? '微信' : '支付宝') + '扫一扫,扫描二维码完成支付
' + '
' + '⏱️ 支付剩余时间:' + '14:59' + '
' + '
' + '' + '' + '等待支付中...' + '' + '
' + '
' + '' + '' + '
' + '
订单号:' + orderId + '
' + '
'; openDetail(payLabel + '支付', body); // 启动倒计时 var remaining = 14 * 60 + 59; if (_terminalPayCountdown) clearInterval(_terminalPayCountdown); _terminalPayCountdown = setInterval(function() { remaining--; if (remaining <= 0) { clearInterval(_terminalPayCountdown); cancelTerminalPay(true); return; } var m = Math.floor(remaining / 60); var s = remaining % 60; var el = document.getElementById('wxPayCountdownNum'); if (el) el.textContent = (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s; }, 1000); // 模拟自动支付检测(8秒后自动成功) _terminalPayTimer = setTimeout(function() { simulateWechatPaySuccess(p.id, orderId); }, 8000); } // 生成模拟二维码 SVG function generateMockQRCode() { var cells = ''; var size = 21; // 使用确定性图案(基于时间戳) var seed = Date.now(); for (var y = 0; y < size; y++) { for (var x = 0; x < size; x++) { seed = (seed * 9301 + 49297) % 233280; if ((seed / 233280) > 0.5) { cells += ''; } } } // 三个定位角 var corners = [[0,0],[size*9-63,0],[0,size*9-63]]; corners.forEach(function(c) { cells += ''; cells += ''; cells += ''; }); return '' + cells + ''; } function simulateWechatPaySuccess(id, orderId) { if (_terminalPayTimer) { clearTimeout(_terminalPayTimer); _terminalPayTimer = null; } if (_terminalPayCountdown) { clearInterval(_terminalPayCountdown); _terminalPayCountdown = null; } // 支付成功状态 var statusEl = document.getElementById('wxPayStatus'); var countdownEl = document.getElementById('wxPayCountdown'); if (countdownEl) countdownEl.style.display = 'none'; if (statusEl) { statusEl.className = 'wx-pay__status wx-pay__status--success'; statusEl.innerHTML = '✅ 支付成功!正在处理订单...'; } // 1.5秒后显示成功页 setTimeout(function() { finishTerminalOrder(id, orderId); }, 1500); } function cancelTerminalPay(timeout) { if (_terminalPayTimer) { clearTimeout(_terminalPayTimer); _terminalPayTimer = null; } if (_terminalPayCountdown) { clearInterval(_terminalPayCountdown); _terminalPayCountdown = null; } closeDetailModal(); showToast(timeout ? '支付超时,订单已取消' : '支付已取消', 'info'); } function finishTerminalOrder(id, orderId) { var data = getTerminalProducts(); var p = data.find(function(x) { return x.id === id; }); if (!p) return; // 扣减库存、增加销量 p.stock = Math.max(0, p.stock - 1); p.deals = (p.deals || 0) + 1; // 持久化 try { localStorage.setItem(PLATFORM_DATA_KEY, JSON.stringify(platformData)); } catch(e) {} var payLabel = _terminalPayMethod === 'wechat' ? '微信支付' : '支付宝'; var payIcon = _terminalPayMethod === 'wechat' ? '💚' : '💙'; var body = '
' + '
' + '

支付成功!

' + '
订单已支付,商家将尽快为您发货
' + '
' + '
订单编号
' + '
' + orderId + '
' + '
支付方式
' + '
' + payIcon + ' ' + payLabel + '
' + '
支付金额
' + '
¥' + escHtml(String(p.price)) + '
' + '
' + '
商家联系方式:' + escHtml(p.sellerPhone || '请联系平台客服') + '
' + '
' + '' + '' + '
' + '
'; openDetail('交易成功', body); updateTerminalStats(); showToast('支付成功!订单已提交', 'success'); } function contactTerminalSeller(id) { var data = getTerminalProducts(); var p = data.find(function(x) { return x.id === id; }); if (!p) return; closeDetailModal(); var conv = getOrCreateConsultConv(id, 'terminal'); openConsultCenter(); selectConsult(conv.id); } function openTerminalMyProducts() { if (!AuthManager.currentUser) { showToast('请先登录', 'info'); openAuthModal('login'); return; } var user = AuthManager.currentUser; var userName = user.nick || user.name || ''; var data = getTerminalProducts(); var myProducts = data.filter(function(p) { return p.postedBy === userName || p.postedBy === user.name; }); var body = '
' + '
' + '

🛒 我的商品

' + '' + '
' + '
共 ' + myProducts.length + ' 件商品
' + '
'; if (myProducts.length === 0) { body += '
' + '
📦
' + '

暂无商品,点击上方按钮发布您的AI终端产品

' + '
'; } else { body += myProducts.map(function(p) { var cat = TERMINAL_CATEGORY_MAP[p.category] || TERMINAL_CATEGORY_MAP.other; return '
' + '
' + '
' + cat.icon + ' ' + cat.name + '' + escHtml(p.name) + '
' + '
' + escHtml(p.brand || '') + ' · ¥' + escHtml(String(p.price)) + ' · 库存' + escHtml(String(p.stock)) + ' · 已售' + escHtml(String(p.deals || 0)) + '
' + '
' + '
' + '' + '' + '
' + '
'; }).join(''); } openDetail('我的商品', body); } function handleRemoveTerminal(id) { if (!confirm('确定删除该商品?')) return; var data = getTerminalProducts(); var idx = data.findIndex(function(p) { return p.id === id; }); if (idx >= 0) { data.splice(idx, 1); try { localStorage.setItem(PLATFORM_DATA_KEY, JSON.stringify(platformData)); } catch(e) {} renderTerminalProducts(); updateTerminalStats(); // 刷新我的商品列表 openTerminalMyProducts(); showToast('商品已删除', 'success'); } } function updateTerminalStats() { var data = getTerminalProducts(); var totalEl = document.getElementById('terminalTotal'); var merchantsEl = document.getElementById('terminalMerchants'); var dealsEl = document.getElementById('terminalDeals'); if (totalEl) totalEl.textContent = data.length; // 去重商家数 var merchants = {}; data.forEach(function(p) { var seller = p.seller || p.postedBy || 'unknown'; merchants[seller] = true; }); if (merchantsEl) merchantsEl.textContent = Object.keys(merchants).length; // 累计成交量 var totalDeals = data.reduce(function(sum, p) { return sum + (p.deals || 0); }, 0); if (dealsEl) dealsEl.textContent = totalDeals; } // AI 文件上传 + 自动填充 let terminalUploadFiles = []; function handleTerminalFiles(files) { if (!files || files.length === 0) return; terminalUploadFiles = Array.from(files); renderTerminalFileList(); // 模拟 AI 分析 aiFillTerminalForm(); } function renderTerminalFileList() { var container = document.getElementById('terminalFileList'); if (!container) return; container.innerHTML = terminalUploadFiles.map(function(f, i) { return '
' + '📄' + escHtml(f.name) + '' + '' + (f.size / 1024).toFixed(1) + 'KB' + '
'; }).join(''); } function aiFillTerminalForm() { var progressEl = document.getElementById('terminalAiProgress'); var barEl = document.getElementById('terminalAiProgressBar'); var textEl = document.getElementById('terminalAiProgressText'); if (!progressEl) return; progressEl.style.display = 'block'; barEl.style.width = '0%'; textEl.textContent = 'AI 正在分析文档...'; var steps = [ { pct: 12, text: 'AI 正在解析文档内容...', delay: 500 }, { pct: 28, text: '提取商品名称和品牌信息...', delay: 1100 }, { pct: 42, text: '分析价格和规格参数...', delay: 1700 }, { pct: 56, text: '生成商品描述...', delay: 2300 }, { pct: 70, text: '提取产品图片生成图册...', delay: 2900 }, { pct: 85, text: '生成图文详情内容...', delay: 3500 }, { pct: 100, text: '✅ AI 信息补录完成!', delay: 4100 } ]; steps.forEach(function(step, i) { setTimeout(function() { barEl.style.width = step.pct + '%'; textEl.textContent = step.text; if (i === 1) { var nameInput = document.getElementById('tpName'); if (nameInput && !nameInput.value) { nameInput.value = 'AI智能终端产品'; nameInput.classList.add('ai-filled'); } var brandInput = document.getElementById('tpBrand'); if (brandInput && !brandInput.value) { brandInput.value = 'AI品牌'; brandInput.classList.add('ai-filled'); } } if (i === 2) { var priceInput = document.getElementById('tpPrice'); if (priceInput && !priceInput.value) { priceInput.value = '1999'; priceInput.classList.add('ai-filled'); } var catSelect = document.getElementById('tpCategory'); if (catSelect && !catSelect.value) { catSelect.value = 'glasses'; catSelect.classList.add('ai-filled'); } } if (i === 3) { var descInput = document.getElementById('tpDesc'); if (descInput && !descInput.value) { descInput.value = '该产品搭载最新AI芯片,支持智能语音助手、实时翻译、健康监测等多项功能。采用轻量化设计,佩戴舒适,续航持久,是您智能化生活的理想伴侣。'; descInput.classList.add('ai-filled'); } } if (i === 4) { var specsInput = document.getElementById('tpSpecs'); if (specsInput && !specsInput.value) { specsInput.value = '重量:45g | 续航:8h | 连接:蓝牙5.3 | 防水:IP54 | 充电:USB-C'; specsInput.classList.add('ai-filled'); } var stockInput = document.getElementById('tpStock'); if (stockInput && !stockInput.value) { stockInput.value = '100'; stockInput.classList.add('ai-filled'); } var imageInput = document.getElementById('tpImage'); if (imageInput && !imageInput.value) { imageInput.value = 'https://picsum.photos/seed/aifill/600/600'; imageInput.classList.add('ai-filled'); } } if (i === 5) { // AI 填充图册 if (!_tpGalleryItems.length) { _tpGalleryItems = [ 'https://picsum.photos/seed/aifill1/600/600', 'https://picsum.photos/seed/aifill2/600/600', 'https://picsum.photos/seed/aifill3/600/600' ]; renderTpGalleryList(); } } if (i === 6) { // AI 填充图文详情 if (!_tpRichBlocks.length) { _tpRichBlocks = [ { title: '核心功能亮点', image: 'https://picsum.photos/seed/aifill1/800/400', text: '搭载最新AI芯片,支持智能语音助手、实时多语言翻译、健康数据监测等核心功能。轻量化设计,佩戴舒适,全天候陪伴。' }, { title: '产品规格与工艺', image: 'https://picsum.photos/seed/aifill2/800/400', text: '采用航空级材质,重量仅45g。支持蓝牙5.3连接,续航8小时,IP54防水等级。USB-C快充,15分钟充电使用2小时。' }, { title: '应用场景', image: 'https://picsum.photos/seed/aifill3/800/400', text: '适用于商务会议、出国旅行、运动健身、日常健康监测等多种场景。让AI技术融入生活的每一个细节。' } ]; renderTpRichList(); } setTimeout(function() { progressEl.style.display = 'none'; }, 2000); } }, step.delay); }); } // 拖拽上传支持 document.addEventListener('DOMContentLoaded', function() { var zone = document.getElementById('terminalUploadZone'); if (zone) { zone.addEventListener('dragover', function(e) { e.preventDefault(); zone.classList.add('dragover'); }); zone.addEventListener('dragleave', function(e) { zone.classList.remove('dragover'); }); zone.addEventListener('drop', function(e) { e.preventDefault(); zone.classList.remove('dragover'); handleTerminalFiles(e.dataTransfer.files); }); } }); document.addEventListener('DOMContentLoaded', initApp); // 跨标签页数据同步:管理后台更新数据后自动刷新首页 window.addEventListener('storage', function(e) { if (e.key === PLATFORM_DATA_KEY) { loadPlatformData(); try { renderProviders(platformData.providers); } catch(ex) { console.error('[Sync] renderProviders:', ex.message); } try { renderNews(); } catch(ex) { console.error('[Sync] renderNews:', ex.message); } try { renderBiddings(); } catch(ex) { console.error('[Sync] renderBiddings:', ex.message); } try { renderInvestments(); } catch(ex) { console.error('[Sync] renderInvestments:', ex.message); } try { renderDatasets(); } catch(ex) { console.error('[Sync] renderDatasets:', ex.message); } try { renderOpc(); } catch(ex) { console.error('[Sync] renderOpc:', ex.message); } try { renderWaicExhibitors(); } catch(ex) { console.error('[Sync] renderWaicExhibitors:', ex.message); } try { renderTerminalProducts(); } catch(ex) { console.error('[Sync] renderTerminalProducts:', ex.message); } try { updateTerminalStats(); } catch(ex) { console.error('[Sync] updateTerminalStats:', ex.message); } try { updateStats(); } catch(ex) { console.error('[Sync] updateStats:', ex.message); } console.log('[Sync] 数据同步刷新完成'); } if (e.key === 'hj_site_settings') { try { renderFooterContent(); } catch(ex) { console.error('[Sync] renderFooterContent:', ex.message); } } }); // ============================================================ // CONSULTATION MODULE - AI 咨询沟通管理系统 (PC前端) // ============================================================ // 会话存储 let CONSULT_CONVS = []; let consultCurrentId = null; let consultFilter = 'all'; // 初始化默认会话 function initConsultData() { if (CONSULT_CONVS.length > 0) return; const providers = platformData.providers || []; const requirements = platformData.requirements || []; // 创建几个示例会话 if (providers.length > 0) { const p = providers[0]; const conv = createConsultConv(p.id, 'provider', { name: p.name, avatar: p.name.charAt(0), role: 'supply', category: p.category, location: p.location }); conv.messages.push({ type:'system', text:`AI助手已将您的需求与「${p.name}」进行匹配。对方在${p.category}领域有丰富经验,位于${p.location}。`, time: Date.now()-3600000 }); conv.messages.push({ type:'user', text:`您好「${p.name}」团队,我对贵司的服务很感兴趣,想进一步了解。`, time: Date.now()-3500000 }); conv.messages.push({ type:'other', text:`感谢关注!我们正好有相关经验,建议先做个简单的需求对接?`, time: Date.now()-3400000 }); conv.unread = 1; } if (requirements.length > 0) { const r = requirements[0]; const conv2 = createConsultConv(r.id, 'requirement', { name: r.title.length > 12 ? r.title.slice(0,12)+'...' : r.title, avatar: '需', role: 'demand', category: r.category, budget: r.budget, location: r.location }); conv2.messages.push({ type:'system', text:`AI助手已将您的服务能力与「${r.title}」的需求进行匹配。该需求预算约¥${(r.budget?.min||0)/10000}-${(r.budget?.max||0)/10000}万。`, time: Date.now()-7200000 }); conv2.unread = 0; } // 数据集示例会话 const datasets = platformData.datasets || []; if (datasets.length > 0) { const d = datasets[0]; const conv3 = createConsultConv(d.id, 'dataset', { name: d.name.length > 14 ? d.name.slice(0,14)+'...' : d.name, avatar: 'DS', role: d.type === 'supply' ? 'supply' : 'demand', category: d.category, scale: d.scale, format: d.format, priceRange: d.priceRange, postedBy: d.postedBy, sourceLabel: '数据集' }); conv3.messages.push({ type:'system', text:`AI助手已为您连接数据集「${d.name}」的发布方${d.postedBy||''}。\n📊 数据规模:${d.scale}\n📁 数据格式:${d.format}\n📂 分类:${d.category}`, time: Date.now()-10800000 }); conv3.messages.push({ type:'user', text:`您好,对这个数据集很感兴趣,请问可以提供数据样本吗?`, time: Date.now()-10700000 }); conv3.messages.push({ type:'other', text:`您好!当然可以,我们可以提供部分脱敏样本供您评估。请问您的主要使用场景是什么?`, time: Date.now()-10600000 }); conv3.unread = 1; } // OPC示例会话 const opcItems = platformData.opc || []; if (opcItems.length > 0) { const o = opcItems[0]; const conv4 = createConsultConv(o.id, 'opc', { name: o.title.length > 14 ? o.title.slice(0,14)+'...' : o.title, avatar: 'OP', role: o.type === 'idea' ? 'supply' : 'demand', category: o.category, seeking: o.seeking, postedBy: o.postedBy, sourceLabel: o.type === 'idea' ? '创新Idea' : '技术需求' }); conv4.messages.push({ type:'system', text:`AI助手已为您连接OPC${o.type === 'idea' ? '创新Idea' : '技术需求'}「${o.title}」的发布方${o.postedBy||''}。\n📂 领域:${o.category}\n🤝 寻找:${o.seeking}`, time: Date.now()-14400000 }); conv4.unread = 0; } } function createConsultConv(sourceId, sourceType, counterparty) { const conv = { id: 'conv-' + Date.now() + '-' + Math.random().toString(36).slice(2,6), sourceId, sourceType, counterparty, messages: [], unread: 0, createdAt: new Date().toISOString(), updatedAt: Date.now() }; CONSULT_CONVS.unshift(conv); return conv; } function getOrCreateConsultConv(sourceId, sourceType) { let conv = CONSULT_CONVS.find(c => c.sourceId === sourceId && c.sourceType === sourceType); if (conv) return conv; let counterparty; if (sourceType === 'provider') { const p = platformData.providers.find(x => x.id === sourceId); if (!p) return null; counterparty = { name: p.name, avatar: p.name.charAt(0), role: 'supply', category: p.category, location: p.location, rating: p.rating, priceRange: p.priceRange, services: p.services }; } else if (sourceType === 'dataset') { const d = platformData.datasets.find(x => x.id === sourceId); if (!d) return null; counterparty = { name: d.name.length > 14 ? d.name.slice(0,14)+'...' : d.name, avatar: 'DS', role: d.type === 'supply' ? 'supply' : 'demand', category: d.category, scale: d.scale, format: d.format, priceRange: d.priceRange, postedBy: d.postedBy, sourceLabel: '数据集' }; } else if (sourceType === 'opc') { const o = platformData.opc.find(x => x.id === sourceId); if (!o) return null; counterparty = { name: o.title.length > 14 ? o.title.slice(0,14)+'...' : o.title, avatar: 'OP', role: o.type === 'idea' ? 'supply' : 'demand', category: o.category, seeking: o.seeking, postedBy: o.postedBy, sourceLabel: o.type === 'idea' ? '创新Idea' : '技术需求' }; } else if (sourceType === 'terminal') { const tp = getTerminalProducts().find(x => x.id === sourceId); if (!tp) return null; counterparty = { name: tp.name.length > 14 ? tp.name.slice(0,14)+'...' : tp.name, avatar: '🛒', role: 'supply', category: (TERMINAL_CATEGORY_MAP[tp.category] || {}).name || 'AI终端', priceRange: { min: tp.price, max: tp.price }, postedBy: tp.seller || tp.postedBy, sourceLabel: 'AI+终端商品' }; } else if (sourceType === 'requirement') { const r = platformData.requirements.find(x => x.id === sourceId); if (!r) return null; counterparty = { name: r.title.length > 15 ? r.title.slice(0,15)+'...' : r.title, avatar: '📋', role: 'demand', category: r.category, location: r.location, budget: r.budget, timeline: r.timeline, postedBy: r.postedBy, postedDate: r.postedDate, priority: r.priority, description: r.description, tags: r.tags, sourceLabel: '需求方' }; } else { const r = platformData.requirements.find(x => x.id === sourceId); if (!r) return null; counterparty = { name: r.title.length > 12 ? r.title.slice(0,12)+'...' : r.title, avatar: '需', role: 'demand', category: r.category, budget: r.budget, location: r.location }; } conv = createConsultConv(sourceId, sourceType, counterparty); // 添加系统欢迎消息 let welcomeText = ''; if (sourceType === 'provider') { welcomeText = `AI助手已将您的需求与「${counterparty.name}」进行匹配。对方在${counterparty.category||'相关'}领域有丰富经验,位于${counterparty.location||''}。开始沟通吧!`; } else if (sourceType === 'requirement') { var budgetText = counterparty.budget ? '¥' + ((counterparty.budget.min||0)/10000).toFixed(1) + ' - ' + ((counterparty.budget.max||0)/10000).toFixed(1) + '万' : '面议'; var priorityText = counterparty.priority === '高' ? '🔴 高优先级' : counterparty.priority === '中' ? '🟡 中优先级' : '🟢 低优先级'; welcomeText = `AI助手已为您匹配到需求方「${counterparty.name}」发布的采购需求。\n\n📋 需求概要:\n• 分类:${counterparty.category||'未知'}\n• 预算:${budgetText}\n• 周期:${counterparty.timeline||'待确认'}\n• 优先级:${priorityText}\n• 地点:${counterparty.location||'未知'}\n• 发布方:${counterparty.postedBy||'未知'}\n\n💡 建议:仔细了解需求详情后,准备好服务方案和报价,即可开始沟通!`; } else if (sourceType === 'dataset') { const priceText = counterparty.priceRange && counterparty.priceRange.min ? `¥${(counterparty.priceRange.min/10000).toFixed(0)}-${(counterparty.priceRange.max/10000).toFixed(0)}万` : '面议'; welcomeText = `AI助手已为您连接数据集「${counterparty.name}」的发布方${counterparty.postedBy||''}。\n📊 数据规模:${counterparty.scale||'未知'}\n📁 数据格式:${counterparty.format||'未知'}\n💰 价格:${priceText}\n📂 分类:${counterparty.category||'未分类'}\n\n开始沟通数据集详情吧!`; } else if (sourceType === 'opc') { welcomeText = `AI助手已为您连接OPC${counterparty.sourceLabel||'项目'}「${counterparty.name}」的发布方${counterparty.postedBy||''}。\n📂 领域:${counterparty.category||'未分类'}\n🤝 寻找:${counterparty.seeking||'合作'}\n\n开始沟通合作意向吧!`; } else if (sourceType === 'terminal') { welcomeText = `AI助手已为您连接AI+终端商城商品「${counterparty.name}」的商家${counterparty.postedBy||''}。\n🛒 分类:${counterparty.category||'AI终端'}\n💰 价格:¥${counterparty.priceRange?.min||0}\n\n开始咨询商品详情吧!`; } else { welcomeText = `AI助手已将您的服务能力与「${counterparty.name}」的需求进行匹配。该需求预算约¥${((counterparty.budget?.min||0)/10000).toFixed(0)}-${((counterparty.budget?.max||0)/10000).toFixed(0)}万,位于${counterparty.location||''}。开始沟通吧!`; } conv.messages.push({ type: 'system', text: welcomeText, time: Date.now() }); return conv; } function openConsultCenter() { initConsultData(); document.getElementById('consultOverlay').classList.add('show'); renderConsultList(); // Show empty state document.getElementById('consultEmpty').style.display = 'flex'; document.getElementById('consultChatArea').style.display = 'none'; consultCurrentId = null; } function closeConsultCenter(e) { if (e && e.target !== document.getElementById('consultOverlay')) return; document.getElementById('consultOverlay').classList.remove('show'); } function filterConsultList(type, btn) { consultFilter = type; document.querySelectorAll('.consult-filter').forEach(b => b.classList.remove('active')); if (btn) btn.classList.add('active'); renderConsultList(); } function getFilteredConsults() { if (consultFilter === 'all') return CONSULT_CONVS; if (consultFilter === 'unread') return CONSULT_CONVS.filter(c => (c.unread||0) > 0); if (consultFilter === 'supply') return CONSULT_CONVS.filter(c => c.counterparty.role === 'supply'); if (consultFilter === 'demand') return CONSULT_CONVS.filter(c => c.counterparty.role === 'demand'); return CONSULT_CONVS; } function renderConsultList() { const list = getFilteredConsults(); const body = document.getElementById('consultListBody'); if (list.length === 0) { body.innerHTML = '
💬
暂无咨询记录
浏览服务商或需求,点击「立即咨询」即可发起对话
'; return; } body.innerHTML = list.map(c => { const cp = c.counterparty; const lastMsg = c.messages[c.messages.length - 1]; const preview = lastMsg ? (lastMsg.text.length > 30 ? lastMsg.text.slice(0,30)+'...' : lastMsg.text) : '开始对话'; const avatarCls = cp.role === 'supply' ? 'consult-conv-item__avatar--supply' : 'consult-conv-item__avatar--demand'; const timeStr = formatConsultTime(c.updatedAt); return `
${cp.avatar}
${escHtml(cp.name)}
${escHtml(preview.replace(/<[^>]*>/g,''))}
${timeStr} ${(c.unread||0)>0 ? `${c.unread}` : ''}
`; }).join(''); } function formatConsultTime(ts) { if (typeof ts === 'string') ts = new Date(ts).getTime(); const diff = Date.now() - ts; if (diff < 60000) return '刚刚'; if (diff < 3600000) return Math.floor(diff/60000)+'分钟前'; if (diff < 86400000) return Math.floor(diff/3600000)+'小时前'; return new Date(ts).toLocaleDateString('zh-CN', {month:'short',day:'numeric'}); } function selectConsult(id) { consultCurrentId = id; const c = CONSULT_CONVS.find(x => x.id === id); if (!c) return; c.unread = 0; document.getElementById('consultEmpty').style.display = 'none'; document.getElementById('consultChatArea').style.display = 'flex'; // 渲染头部 const cp = c.counterparty; const avatarCls = cp.role === 'supply' ? 'consult-conv-item__avatar--supply' : 'consult-conv-item__avatar--demand'; const statusCls = c.counterparty.role === 'supply' ? 'consult-main__status--active' : 'consult-main__status--pending'; const statusText = c.counterparty.role === 'supply' ? '供方 · 在线' : '需方 · 待跟进'; var subInfo = (cp.category||'') + (cp.location ? ' · ' + cp.location : ''); if (c.sourceType === 'requirement') { var shortBudget = cp.budget ? '¥' + ((cp.budget.min||0)/10000).toFixed(1) + '-' + ((cp.budget.max||0)/10000).toFixed(1) + '万' : ''; subInfo = (cp.sourceLabel||'需求方') + ' · ' + (cp.postedBy||'') + (shortBudget ? ' · ' + shortBudget : '') + ' · ' + (cp.priority ? cp.priority + '优先级' : ''); } document.getElementById('consultChatHeader').innerHTML = `
${cp.avatar}
${escHtml(cp.name)}
${escHtml(subInfo)}
${statusText} `; renderConsultMessages(c); renderConsultList(); } function backToConsultList() { consultCurrentId = null; document.getElementById('consultEmpty').style.display = 'flex'; document.getElementById('consultChatArea').style.display = 'none'; renderConsultList(); } function renderConsultMessages(c) { const el = document.getElementById('consultMessages'); el.innerHTML = c.messages.map(m => { const timeStr = new Date(m.time).toLocaleTimeString('zh-CN', {hour:'2-digit',minute:'2-digit'}); let cls = 'consult-msg--system', label = ''; if (m.type === 'user') cls = 'consult-msg--user'; else if (m.type === 'other') cls = 'consult-msg--other'; else if (m.type === 'ai') { cls = 'consult-msg--ai'; var srcBadge = ''; if (m.source === 'kb') srcBadge = ' 知识库'; else if (m.source === 'ai') srcBadge = ' AI大模型'; else if (m.source === 'human') srcBadge = ' 转人工'; label = '🤖 AI · ' + srcBadge + ' '; } else if (m.type === 'ai_typing') { cls = 'consult-msg--ai'; return '
' + '' + '' + '' + 'AI正在思考...
'; } return `
${label}${m.text.replace(/\n/g,'
')}
${timeStr}
`; }).join(''); setTimeout(() => { el.scrollTop = el.scrollHeight; }, 100); } function sendConsultMsg() { const input = document.getElementById('consultMsgInput'); const msg = input.value.trim(); if (!msg || !consultCurrentId) return; input.value = ''; const c = CONSULT_CONVS.find(x => x.id === consultCurrentId); if (!c) return; c.messages.push({ type: 'user', text: msg, time: Date.now() }); c.updatedAt = Date.now(); renderConsultMessages(c); renderConsultList(); // AI 智能回复 setTimeout(() => { const aiResp = generateConsultAiResponse(msg, c); c.messages.push({ type: 'ai', text: aiResp, time: Date.now() }); c.updatedAt = Date.now(); renderConsultMessages(c); renderConsultList(); }, 1000 + Math.random() * 1500); } function generateConsultAiResponse(msg, c) { const cp = c.counterparty; // 数据集类型回复 if (c.sourceType === 'dataset') { const responses = [ `AI分析:消息已记录并转发给数据集${cp.role === 'supply' ? '供方' : '需方'}。\n📊 数据集匹配评估:\n• 数据规模:${cp.scale||'未知'} ✅\n• 数据格式:${cp.format||'未知'} ✅\n• 沟通进展:正常\n• 建议:可请对方提供数据样本或API文档`, `✅ AI已记录此条沟通。\n\n数据集对接建议:\n• ${cp.role === 'supply' ? '供方可发送数据样本和字段说明' : '需方可明确数据量和格式要求'}\n• 确认数据授权范围和使用期限\n• 约定数据交付方式(API/下载/私有部署)`, `AI辅助建议:\n数据集合作推进步骤:\n1. 确认数据规模、格式和质量标准\n2. 了解数据标注和清洗情况\n3. 明确授权范围(研究/商用)\n4. 约定交付方式和验收标准`, ]; return responses[Math.floor(Math.random() * responses.length)]; } // OPC类型回复 if (c.sourceType === 'opc') { const responses = [ `AI分析:消息已记录并转发给${cp.sourceLabel||'OPC项目'}发布方。\n🚀 合作匹配评估:\n• 领域:${cp.category||'未知'} ✅\n• 合作意向:${cp.seeking||'待确认'}\n• 沟通进展:正常\n• 建议:明确双方在项目中的角色分工`, `✅ AI已记录此条沟通。\n\nOPC合作建议:\n• 明确是技术合作、投资还是联合开发\n• 确认知识产权归属和收益分配\n• 约定里程碑节点和交付物\n• 建议签订合作意向书`, `AI辅助建议:\n一人公司项目合作推进:\n1. 明确各自核心优势和贡献\n2. 确定合作模式(合伙/外包/投资)\n3. 约定项目周期和关键节点\n4. 讨论风险分担和退出机制`, ]; return responses[Math.floor(Math.random() * responses.length)]; } // 终端商城类型回复 if (c.sourceType === 'terminal') { const responses = [ `AI分析:消息已记录并转发给商家${cp.postedBy||''}。\n🛒 商品咨询评估:\n• 商品:${cp.name} ✅\n• 分类:${cp.category||'AI终端'} ✅\n• 价格:¥${cp.priceRange?.min||0}\n• 沟通进展:正常\n• 建议:可询问产品详细参数和售后政策`, `✅ AI已记录此条沟通。\n\n终端商品购买建议:\n• 确认产品型号和规格参数\n• 了解保修政策和售后方式\n• 确认发货时间和物流方式\n• 平台支持担保交易,保障资金安全`, `AI辅助建议:\nAI终端商品选购指南:\n1. 确认产品核心功能和适用场景\n2. 了解续航、重量等关键参数\n3. 询问兼容性和连接方式\n4. 确认库存和发货时间\n5. 了解退换货政策`, ]; return responses[Math.floor(Math.random() * responses.length)]; } // 需求广场类型回复(供方 -> 需方) if (c.sourceType === 'requirement') { var reqBudgetAi = cp.budget ? '¥' + ((cp.budget.min||0)/10000).toFixed(1) + ' - ' + ((cp.budget.max||0)/10000).toFixed(1) + '万' : '面议'; var priorityLabel = cp.priority === '高' ? '高优先级' : cp.priority === '中' ? '中优先级' : '低优先级'; const responses = [ `AI助手提示:您的消息已记录,正在通知需求方「${cp.postedBy||'发布方'}」。\n\n📊 匹配分析:\n• 需求领域:${cp.category||'未知'} ✅\n• 预算范围:${reqBudgetAi}\n• 交付周期:${cp.timeline||'待确认'}\n• 优先级:${priorityLabel}\n\n💡 建议:准备好服务方案和成功案例,提高响应效率。`, `✅ AI已记录并转发此条沟通。\n\n对接建议:\n• 尽快出具针对「${cp.name}」的个性化服务方案\n• 准备2-3个相关成功案例向需方展示\n• 明确自身优势是否符合交付周期要求\n• 建议在1-3个工作日内完成首轮对接`, `AI对接策略建议:\n\n针对此${cp.category||'相关'}需求,建议供方按以下步骤推进:\n\n1️⃣ 首轮沟通:了解需求方核心痛点和决策标准\n2️⃣ 方案展示:基于需求详情出具定制化方案\n3️⃣ 报价协商:结合预算范围给出精准报价\n4️⃣ 约定交付:明确里程碑节点和验收标准\n\n📌 关键提醒:需方的${priorityLabel}需求,尽快响应可提升合作机会。`, `AI协同建议:\n\n📋 基于需求「${cp.name}」的分析,建议供方准备以下材料:\n• 公司/团队资质证明(如有认证更佳)\n• ${cp.category||'相关'}领域的项目案例(2-3个)\n• 针对本需求的初步技术方案\n• 分阶段报价明细\n\n⏰ 目标预算${reqBudgetAi},建议方案在预算范围内合理安排。`, ]; return responses[Math.floor(Math.random() * responses.length)]; } // 默认回复(provider/requirement兼容) const responses = [ `AI分析:消息已记录并转发给${cp.role === 'supply' ? '供方' : '需方'}。\n📊 当前匹配度评估:\n• 领域:${cp.category||'未知'} ✅\n• 沟通进展:正常\n• 建议:尽快约定线上会议确认细节`, `✅ AI已记录此条沟通。\n\n后续建议:\n• ${cp.role === 'supply' ? '供方可发送标准服务方案' : '需方可明确具体需求'}\n• 双方约定1周内完成初步对接\n• 平台将自动跟踪项目进度`, `AI辅助建议:\n根据对话内容,建议参考以下步骤推进:\n1. 明确核心需求和交付标准\n2. 约定沟通时间(建议30分钟线上会议)\n3. 供方提供案例参考\n4. 双方确认合作意向`, ]; return responses[Math.floor(Math.random() * responses.length)]; } function consultQuickReply(type) { if (!consultCurrentId) return; const c = CONSULT_CONVS.find(x => x.id === consultCurrentId); if (!c) return; const cp = c.counterparty; let templates; if (c.sourceType === 'dataset') { templates = { schedule: `您好,关于数据集「${cp.name}」,建议安排一次线上沟通(约30分钟),详细对接数据需求。\n\n请问您本周什么时间方便?`, quote: `您好,关于该数据集:\n\n• 数据规模:${cp.scale||'按需'}\n• 数据格式:${cp.format||'标准格式'}\n• 授权方式:可议(研究/商用)\n• 交付方式:API / 下载 / 私有部署\n\n具体价格可进一步商议,期待合作。`, detail: `为了更好地对接数据集,能否请您明确:\n\n1. 需要的数据量和字段范围?\n2. 数据用途(训练/评测/研究)?\n3. 是否需要标注数据?\n4. 期望的交付时间?\n5. 预算范围?`, case: `我们在${cp.category||'相关'}领域已有多个数据集合作案例:\n\n• 为多家AI团队提供高质量训练数据\n• 数据质量通过多项校验\n• 支持定制化标注和清洗\n\n需要我发送数据样本吗?`, summary: `🤖 AI对话总结:\n\n本次沟通围绕数据集「${cp.name}」展开。\n\n📌 关键信息:\n• 数据规模:${cp.scale||'未知'}\n• 数据格式:${cp.format||'未知'}\n• 分类:${cp.category||'未分类'}\n\n📌 建议下一步:\n1. 索取数据样本和字段说明\n2. 确认授权范围\n3. 约定交付方式`, }; } else if (c.sourceType === 'opc') { templates = { schedule: `您好,关于${cp.sourceLabel||'项目'}「${cp.name}」,建议安排一次线上沟通(约30分钟),详细对接合作事宜。\n\n请问您本周什么时间方便?`, quote: `您好,关于合作方案:\n\n• 合作模式:技术合伙 / 联合开发 / 投资\n• 我方贡献:${cp.seeking||'按需协商'}\n• 知识产权:可协商分配\n• 收益分配:按贡献比例\n\n期待深入探讨合作可能。`, detail: `为了更好地了解合作机会,能否请您明确:\n\n1. 项目当前进展阶段?\n2. 您期望的合作模式?\n3. 核心技术壁垒是什么?\n4. 预期里程碑和时间节点?\n5. 资源需求和预算?`, case: `我们在${cp.category||'相关'}领域有丰富经验:\n\n• 多个一人公司项目成功落地\n• 擅长快速原型和敏捷开发\n• 具备从0到1的完整能力链\n\n需要我分享相关案例吗?`, summary: `🤖 AI对话总结:\n\n本次沟通围绕${cp.sourceLabel||'OPC项目'}「${cp.name}」展开。\n\n📌 关键信息:\n• 领域:${cp.category||'未分类'}\n• 寻找:${cp.seeking||'合作'}\n• 发布方:${cp.postedBy||'未知'}\n\n📌 建议下一步:\n1. 明确合作模式和分工\n2. 约定里程碑节点\n3. 签订合作意向书`, }; } else if (c.sourceType === 'terminal') { templates = { schedule: `您好,关于商品「${cp.name}」,我有几个问题想咨询,请问您现在方便吗?`, quote: `您好,关于该商品:\n\n• 商品名称:${cp.name}\n• 商品分类:${cp.category||'AI终端'}\n• 商品价格:¥${cp.priceRange?.min||0}\n\n请问可以优惠吗?是否支持批量采购?`, detail: `为了更好地了解该产品,能否请您提供:\n\n1. 产品的详细规格参数?\n2. 续航时间和充电方式?\n3. 兼容哪些设备和系统?\n4. 保修期多长?\n5. 发货时间和物流方式?`, case: `我对这款${cp.category||'AI终端'}产品很感兴趣:\n\n• 请问有实物图或演示视频吗?\n• 是否有用户评价或使用反馈?\n• 支持试用或体验吗?\n• 有配套的APP或软件平台吗?`, summary: `🤖 AI对话总结:\n\n本次沟通围绕AI+终端商品「${cp.name}」展开。\n\n📌 关键信息:\n• 分类:${cp.category||'AI终端'}\n• 价格:¥${cp.priceRange?.min||0}\n• 商家:${cp.postedBy||'未知'}\n\n📌 建议下一步:\n1. 确认产品规格和售后政策\n2. 协商价格和发货方式\n3. 通过平台担保交易下单`, }; } else if (c.sourceType === 'requirement') { var reqBudget = cp.budget ? '¥' + ((cp.budget.min||0)/10000).toFixed(1) + ' - ' + ((cp.budget.max||0)/10000).toFixed(1) + '万' : '面议'; templates = { schedule: `您好,看到您在「惠捷同城」发布的「${cp.name}」采购需求,我方非常感兴趣。\n\n建议我们安排一次线上沟通(约30分钟),详细对接需求细节和技术方案。\n\n请问这周什么时间方便?我方可以配合。`, quote: `您好,针对您发布的「${cp.name}」需求,我方提供以下初步报价方案供参考:\n\n📊 需求领域:${cp.category||'待确认'}\n💰 您的预算:${reqBudget}\n⏱ 交付周期:${cp.timeline||'待确认'}\n\n我方方案:\n• 基础方案:满足核心需求,性价比高\n• 进阶方案:增加技术优化和持续运维\n• 定制方案:完全按需深度定制\n\n具体方案和报价需深入沟通后确认,期待进一步交流!`, detail: `为了更好地理解并响应您的需求「${cp.name}」,想和您确认几个关键问题:\n\n1. 项目的核心目标和成功标准是什么?\n2. 是否有技术栈或平台的偏好要求?\n3. 期望的交付时间节点是否灵活可调?\n4. 是否已有详细需求文档或方案构想?\n5. 甲方方的决策流程和项目负责人是?\n\n了解这些后,我们可以提供更精准的方案和报价。`, case: `针对您「${cp.name}」的需求,分享我方在${cp.category||'相关'}领域的项目经验:\n\n🏆 成功案例亮点:\n• 已为多家企业提供${cp.category||'相关'}解决方案\n• 典型交付周期:2-6周\n• 客户满意度:98%+\n• 具备完整的项目管理和售后体系\n\n需要我发送相关的案例文档或客户评价吗?`, summary: `🤖 AI对话总结:\n\n本次沟通围绕需求方发布的采购需求「${cp.name}」展开。\n\n📌 需求关键信息:\n• 领域分类:${cp.category||'未知'}\n• 预算范围:${reqBudget}\n• 交付周期:${cp.timeline||'待确认'}\n• 发布方:${cp.postedBy||'未知'} · ${cp.location||'未知'}\n• 优先级:${cp.priority||'未标记'}\n\n📌 建议下一步:\n1. 供方准备好详细服务方案和报价\n2. 约定线上沟通时间(建议30-60分钟)\n3. 确认技术方案和交付标准`, }; } else { templates = { schedule: `您好,建议我们安排一次线上沟通(约30分钟),详细对接项目需求。\n\n请问您本周什么时间方便?\n我可以配合您的时间安排。`, quote: `您好,根据您的需求,我们可提供以下报价方案:\n\n• 基础版:满足核心功能需求\n• 专业版:包含额外优化和运维服务\n• 定制版:完全按需定制开发\n\n具体价格需进一步确认需求细节后给出,预计在合理预算范围内。`, detail: `为了更好地为您服务,能否请您进一步明确以下几点:\n\n1. 项目的具体功能需求?\n2. 期望的交付时间节点?\n3. 预算范围?\n4. 是否有特殊技术要求?\n\n这样我们可以给出更精准的方案。`, case: `我们在${cp.category||'相关'}领域已有多个成功案例,包括:\n\n• 为${cp.location||'多家'}企业提供${cp.category||'相关'}解决方案\n• 平均交付周期:2-4周\n• 客户满意度:98%+\n\n需要我发送详细的案例文档吗?`, summary: `🤖 AI对话总结:\n\n本次沟通围绕${cp.category||'项目合作'}展开。双方已就核心需求进行了初步交流。\n\n📌 关键信息:\n• 对方:${cp.name}\n• 领域:${cp.category||'未知'}\n• 位置:${cp.location||'未知'}\n\n📌 建议下一步:\n1. 约定详细沟通时间\n2. 明确项目范围和交付标准\n3. 确认合作意向`, }; } const text = templates[type] || ''; if (text) { document.getElementById('consultMsgInput').value = text; sendConsultMsg(); } } function consultAiMatch() { if (!consultCurrentId) return; const c = CONSULT_CONVS.find(x => x.id === consultCurrentId); if (!c) return; const cp = c.counterparty; // 生成匹配评分 const dims = { ability: 75 + Math.floor(Math.random() * 25), budget: 70 + Math.floor(Math.random() * 30), location: 65 + Math.floor(Math.random() * 35), timeline: 80 + Math.floor(Math.random() * 20) }; const overall = Math.round((dims.ability + dims.budget + dims.location + dims.timeline) / 4); var summaryText; if (c.sourceType === 'requirement') { summaryText = '综合评估:' + cp.name + '为需求方发布的' + (cp.priority||'') + '采购需求。供方在「' + (cp.category||'相关') + '」领域具备服务能力,与预算' + (cp.budget ? '¥' + ((cp.budget.min||0)/10000).toFixed(1) + '-' + ((cp.budget.max||0)/10000).toFixed(1) + '万' : '面议') + '匹配度较高。建议供方尽快准备方案并主动沟通对接。'; } else { summaryText = '综合评估:' + cp.name + '在「' + (cp.category||'相关') + '」领域具备较强服务能力,与您的需求匹配度较高。建议尽快推进对接,约定详细沟通时间。'; } const matchHtml = `
🎯 AI智能匹配分析 — 综合匹配度 ${overall}%
能力
${dims.ability}%
预算
${dims.budget}%
地域
${dims.location}%
周期
${dims.timeline}%
${summaryText}
`; c.messages.push({ type: 'ai', text: matchHtml, time: Date.now() }); c.updatedAt = Date.now(); renderConsultMessages(c); renderConsultList(); showToast('AI智能匹配报告已生成', 'success'); } // ============================================================ // 供方发布 AI 信息补录 - 产品 & 数据集 // ============================================================ let uploadedProductFiles = []; // 产品添加表单增强:文件上传 + AI补录 function enhanceProductForm() { // 在添加产品表单中插入文件上传区和AI补录按钮 const form = document.getElementById('addProductForm'); if (!form) return; // Check if already enhanced if (form.querySelector('.ai-upload-zone')) return; // 在表单内容前面插入文件上传区 const formContent = form.querySelector('.cert-add-form'); if (!formContent) return; const uploadHtml = `
📤
点击或拖拽文件上传,AI自动解析填充
支持 PDF / Word / Excel / 图片 / CSV / JSON,最大10MB
`; const aiBtnHtml = `
`; formContent.insertAdjacentHTML('afterbegin', aiBtnHtml + uploadHtml); // 设置拖拽 const zone = document.getElementById('productFileZone'); zone.addEventListener('dragover', e => { e.preventDefault(); zone.classList.add('dragover'); }); zone.addEventListener('dragleave', () => zone.classList.remove('dragover')); zone.addEventListener('drop', e => { e.preventDefault(); zone.classList.remove('dragover'); if (e.dataTransfer.files.length) handleProductFiles(e.dataTransfer.files); }); } function handleProductFileSelect(e) { if (e.target.files.length) handleProductFiles(e.target.files); } function handleProductFiles(fileList) { uploadedProductFiles = []; Array.from(fileList).forEach(file => { if (file.size > 10 * 1024 * 1024) { showToast(`文件 ${file.name} 超过10MB限制`, 'error'); return; } uploadedProductFiles.push({ name: file.name, size: file.size, status: 'processing' }); }); renderProductFileList(); // 模拟AI解析 uploadedProductFiles.forEach((f, i) => { setTimeout(() => { f.status = 'done'; renderProductFileList(); // 所有文件解析完成后触发AI填充 if (uploadedProductFiles.every(x => x.status === 'done')) { setTimeout(() => aiFillProductForm(), 500); } }, 1000 + i * 800 + Math.random() * 1000); }); } function renderProductFileList() { const list = document.getElementById('productFileList'); if (!list) return; list.innerHTML = uploadedProductFiles.map(f => `
${getFileIcon(f.name)}
${f.name}
${formatFileSize(f.size)}
${f.status==='processing'?'⏳':'✅'}
`).join(''); } function getFileIcon(name) { const ext = name.split('.').pop().toLowerCase(); if (['jpg','jpeg','png','gif','bmp'].includes(ext)) return '🖼️'; if (['pdf'].includes(ext)) return '📕'; if (['doc','docx'].includes(ext)) return '📝'; if (['xls','xlsx','csv'].includes(ext)) return '📊'; if (['json'].includes(ext)) return '📋'; if (['txt'].includes(ext)) return '📄'; return '📎'; } function formatFileSize(bytes) { if (bytes < 1024) return bytes + ' B'; if (bytes < 1048576) return (bytes/1024).toFixed(1) + ' KB'; return (bytes/1048576).toFixed(1) + ' MB'; } function aiFillProductForm() { // 根据当前发布类型路由 const pubType = window._publishType || 'product'; if (pubType === 'dataset') { aiFillPmDatasetForm(); return; } if (pubType === 'opc') { aiFillPmOpcForm(); return; } const nameEl = document.getElementById('newProductName'); const catEl = document.getElementById('newProductCategory'); const introEl = document.getElementById('newProductIntro'); const scenarioEl = document.getElementById('newProductScenario'); if (!nameEl) return; const progress = document.getElementById('aiProductProgress'); const fill = document.getElementById('aiProductProgressFill'); const text = document.getElementById('aiProductProgressText'); progress.style.display = 'flex'; const fileKeywords = uploadedProductFiles.map(f => f.name).join(' '); let filledCount = 0; const totalFields = 4; // Step 1: 产品名称 setTimeout(() => { if (!nameEl.value.trim()) { if (uploadedProductFiles.length > 0) { const baseName = uploadedProductFiles[0].name.replace(/\.[^.]+$/,'').replace(/[\d\-_]+/g,' ').trim(); nameEl.value = baseName || 'AI推荐智能产品'; } else { nameEl.value = 'AI推荐智能产品'; } nameEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '25%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 400); // Step 2: 产品分类 setTimeout(() => { if (!catEl.value) { const cats = PRODUCT_CATEGORIES.map(c => c.name); let matched = cats.find(c => fileKeywords.includes(c.replace('AI',''))); catEl.value = matched || 'AI应用开发'; catEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '50%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 800); // Step 3: 产品介绍 setTimeout(() => { if (!introEl.value.trim()) { const baseName = nameEl.value || '产品'; introEl.value = `${baseName} - 基于先进的AI技术,为企业提供高效、智能的解决方案。经过深度研发和大量测试,能够显著提升业务效率,降低运营成本。适用于数字化转型企业。`; introEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '75%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1200); // Step 4: 应用场景 setTimeout(() => { if (!scenarioEl.value.trim()) { scenarioEl.value = '适用于企业数字化转型、智能化升级、降本增效等场景。支持在线部署、API调用、私有化部署等多种交付模式。'; scenarioEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '100%'; text.textContent = `${filledCount}/${totalFields} 已填充`; setTimeout(() => { progress.style.display = 'none'; }, 1500); showToast(`AI已自动补录 ${filledCount} 个字段,请确认后保存`, 'success'); }, 1600); } // ============================================================ // 发布需求表单 AI 增强(文件上传 + AI自动补录) // ============================================================ let uploadedRequirementFiles = []; function enhancePublishModal() { const modal = document.getElementById('publishModal'); if (!modal) return; // 如果已经增强过,先移除旧内容 const oldZone = document.getElementById('reqFileZone'); if (oldZone) oldZone.parentElement.remove(); // 在 wizard-steps 之前插入 AI 区域 const wizardSteps = modal.querySelector('.wizard-steps'); if (!wizardSteps) return; const aiHtml = `
上传文件后AI自动解析填充表单
📤
点击或拖拽文件上传,AI自动解析需求信息
支持 PDF / Word / Excel / 图片 / CSV / JSON,最大10MB
`; wizardSteps.insertAdjacentHTML('beforebegin', aiHtml); // 设置拖拽 const zone = document.getElementById('reqFileZone'); zone.addEventListener('dragover', e => { e.preventDefault(); zone.classList.add('dragover'); }); zone.addEventListener('dragleave', () => zone.classList.remove('dragover')); zone.addEventListener('drop', e => { e.preventDefault(); zone.classList.remove('dragover'); if (e.dataTransfer.files.length) handleRequirementFiles(e.dataTransfer.files); }); uploadedRequirementFiles = []; } function handleRequirementFileSelect(e) { if (e.target.files.length) handleRequirementFiles(e.target.files); } function handleRequirementFiles(fileList) { uploadedRequirementFiles = []; Array.from(fileList).forEach(file => { if (file.size > 10 * 1024 * 1024) { showToast(`文件 ${file.name} 超过10MB限制`, 'error'); return; } uploadedRequirementFiles.push({ name: file.name, size: file.size, status: 'processing' }); }); renderRequirementFileList(); // 模拟AI解析 uploadedRequirementFiles.forEach((f, i) => { setTimeout(() => { f.status = 'done'; renderRequirementFileList(); if (uploadedRequirementFiles.every(x => x.status === 'done')) { setTimeout(() => aiFillRequirementForm(), 500); } }, 1000 + i * 800 + Math.random() * 1000); }); } function renderRequirementFileList() { const list = document.getElementById('reqFileList'); if (!list) return; list.innerHTML = uploadedRequirementFiles.map(f => `
${getFileIcon(f.name)}
${f.name}
${formatFileSize(f.size)}
${f.status==='processing'?'⏳':'✅'}
`).join(''); } function aiFillRequirementForm() { const titleEl = document.getElementById('reqTitle'); const catEl = document.getElementById('reqCategory'); const descEl = document.getElementById('reqDesc'); const budgetMinEl = document.getElementById('reqBudgetMin'); const budgetMaxEl = document.getElementById('reqBudgetMax'); if (!titleEl) return; const progress = document.getElementById('aiReqProgress'); const fill = document.getElementById('aiReqProgressFill'); const text = document.getElementById('aiReqProgressText'); if (progress) progress.style.display = 'flex'; const fileKeywords = uploadedRequirementFiles.map(f => f.name).join(' '); let filledCount = 0; const totalFields = 5; // Step 1: 需求标题 setTimeout(() => { if (!titleEl.value.trim()) { if (uploadedRequirementFiles.length > 0) { const baseName = uploadedRequirementFiles[0].name.replace(/\.[^.]+$/,'').replace(/[\d\-_]+/g,' ').trim(); titleEl.value = baseName ? `需要${baseName}相关的AI解决方案` : 'AI智能化需求'; } else { titleEl.value = 'AI智能化转型需求'; } titleEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '20%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 400); // Step 2: 需求分类 setTimeout(() => { if (!catEl.value) { const cats = CATEGORIES.filter(c => c.id !== 'all'); let matched = cats.find(c => fileKeywords.includes(c.name.replace('AI',''))); if (!matched) { if (/教育|培训|教学|课程/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧教育'); else if (/医疗|健康|医院|药/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧医疗'); else if (/农业|种植|养殖/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧农业'); else if (/交通|物流|运输/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧交通'); else if (/金融|银行|保险/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧金融'); else if (/政务|政府|行政/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧政务'); else if (/工厂|制造|生产/.test(fileKeywords)) matched = cats.find(c => c.name === '智能制造'); else if (/客服|对话|问答/.test(fileKeywords)) matched = cats.find(c => c.name === '智能客服'); else if (/文旅|旅游|景区/.test(fileKeywords)) matched = cats.find(c => c.name === '智慧文旅'); else if (/大模型|LLM|GPT/.test(fileKeywords)) matched = cats.find(c => c.name === '大模型应用'); else if (/算力|GPU|服务器/.test(fileKeywords)) matched = cats.find(c => c.name === '算力服务'); } catEl.value = matched ? matched.id : 'llm-application'; catEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '40%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 800); // Step 3: 需求描述 setTimeout(() => { if (!descEl.value.trim()) { const title = titleEl.value || 'AI智能化需求'; const catName = catEl.options[catEl.selectedIndex] ? catEl.options[catEl.selectedIndex].text : 'AI应用'; descEl.value = `【需求背景】\n我司计划在${catName}领域进行智能化升级,希望通过AI技术提升业务效率。\n\n【功能要求】\n1. 核心系统搭建与集成\n2. 数据采集、处理与分析\n3. 智能决策与自动化流程\n4. 可视化看板与报表\n5. 移动端适配\n\n【技术要求】\n- 基于云原生架构,支持弹性扩展\n- 提供标准API接口,便于第三方系统对接\n- 数据安全合规,支持权限管理\n\n【预期效果】\n提升业务处理效率50%以上,降低人工成本,实现数据驱动决策。`; descEl.classList.add('ai-filled'); filledCount++; } fill.style.width = '60%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1200); // Step 4: 预算范围 setTimeout(() => { if (!budgetMinEl.value) { budgetMinEl.value = '50000'; budgetMinEl.classList.add('ai-filled'); filledCount++; } if (!budgetMaxEl.value) { budgetMaxEl.value = '200000'; budgetMaxEl.classList.add('ai-filled'); } fill.style.width = '80%'; text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1600); // Step 5: 时间要求 setTimeout(() => { const timelineEl = document.getElementById('reqTimeline'); if (timelineEl && !timelineEl.value) { timelineEl.value = '1-3个月'; timelineEl.classList.add('ai-filled'); filledCount++; } // 自动跳到第1步,让用户看到已填充内容 wizard.step = 1; wizard.updateUI(); fill.style.width = '100%'; text.textContent = `${filledCount}/${totalFields} 已填充`; setTimeout(() => { if (progress) progress.style.display = 'none'; }, 1500); showToast(`AI已自动补录 ${filledCount} 个字段,请确认后提交`, 'success'); }, 2000); } // PM页面数据集表单AI填充 function aiFillPmDatasetForm() { const nameEl = document.getElementById('pmDsName'); if (!nameEl) return; const catEl = document.getElementById('pmDsCategory'); const descEl = document.getElementById('pmDsDesc'); const scaleEl = document.getElementById('pmDsScale'); const formatEl = document.getElementById('pmDsFormat'); const progress = document.getElementById('aiProductProgress'); const fill = document.getElementById('aiProductProgressFill'); const text = document.getElementById('aiProductProgressText'); if (progress) progress.style.display = 'flex'; const fileKeywords = uploadedProductFiles.map(f => f.name).join(' '); let filledCount = 0; const totalFields = 5; setTimeout(() => { if (!nameEl.value.trim()) { const baseName = uploadedProductFiles.length > 0 ? uploadedProductFiles[0].name.replace(/\.[^.]+$/,'').replace(/[\d\-_]+/g,' ').trim() : ''; nameEl.value = baseName || 'AI推荐高质量数据集'; nameEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '20%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 400); setTimeout(() => { if (catEl && !catEl.value) { const cats = PRODUCT_CATEGORIES.map(c => c.name); let matched = cats.find(c => fileKeywords.includes(c.replace('AI',''))); if (!matched) { if (/交通|车辆/.test(fileKeywords)) matched = '智慧交通'; else if (/医疗|健康/.test(fileKeywords)) matched = '医疗健康'; else if (/金融|交易/.test(fileKeywords)) matched = '金融科技'; else matched = '智慧交通'; } catEl.value = matched; catEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '40%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 800); setTimeout(() => { if (descEl && !descEl.value.trim()) { descEl.value = `${nameEl.value} - 基于AI分析,涵盖多维度高质量数据。数据经过严格清洗、去重和标注,适用于AI模型训练、评测和研究。`; descEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '60%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1200); setTimeout(() => { if (scaleEl && !scaleEl.value) { let scale = '10-100万条'; if (/海量|百万|千万/.test(fileKeywords)) scale = '100万条+'; else if (/小|样本/.test(fileKeywords.toLowerCase())) scale = '<1万条'; scaleEl.value = scale; scaleEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '80%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1600); setTimeout(() => { if (formatEl && !formatEl.value.trim()) { let fmt = 'JSON'; const ext = uploadedProductFiles.length > 0 ? uploadedProductFiles[0].name.split('.').pop().toLowerCase() : ''; if (['csv'].includes(ext)) fmt = 'CSV'; else if (['xls','xlsx'].includes(ext)) fmt = 'Excel(XLSX)'; else if (['json'].includes(ext)) fmt = 'JSON'; else if (['jpg','jpeg','png'].includes(ext)) fmt = '图像(JPG/PNG)'; formatEl.value = fmt; formatEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '100%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; setTimeout(() => { if (progress) progress.style.display = 'none'; }, 1500); showToast(`AI已自动补录 ${filledCount} 个字段,请确认后保存`, 'success'); }, 2000); } // PM页面OPC表单AI填充 function aiFillPmOpcForm() { const titleEl = document.getElementById('pmOpcTitle'); if (!titleEl) return; const catEl = document.getElementById('pmOpcCategory'); const descEl = document.getElementById('pmOpcDesc'); const seekingEl = document.getElementById('pmOpcSeeking'); const progress = document.getElementById('aiProductProgress'); const fill = document.getElementById('aiProductProgressFill'); const text = document.getElementById('aiProductProgressText'); if (progress) progress.style.display = 'flex'; const fileKeywords = uploadedProductFiles.map(f => f.name).join(' '); let filledCount = 0; const totalFields = 4; const typeRadio = document.querySelector('input[name="pmOpcType"]:checked'); const isIdea = typeRadio ? typeRadio.value === 'idea' : true; setTimeout(() => { if (!titleEl.value.trim()) { const baseName = uploadedProductFiles.length > 0 ? uploadedProductFiles[0].name.replace(/\.[^.]+$/,'').replace(/[\d\-_]+/g,' ').trim() : ''; titleEl.value = isIdea ? (baseName || 'AI赋能创新项目') : (baseName || 'AI技术合作需求'); titleEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '25%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 400); setTimeout(() => { if (catEl && !catEl.value) { const cats = PRODUCT_CATEGORIES.map(c => c.name); let matched = cats.find(c => fileKeywords.includes(c.replace('AI',''))); if (!matched) { if (/交通|车辆/.test(fileKeywords)) matched = '智慧交通'; else if (/医疗|健康/.test(fileKeywords)) matched = '医疗健康'; else matched = 'AI应用开发'; } catEl.value = matched; catEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '50%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 800); setTimeout(() => { if (descEl && !descEl.value.trim()) { const cat = catEl ? catEl.value : 'AI'; descEl.value = isIdea ? `基于${cat}领域的创新理念,旨在通过AI技术解决行业痛点。利用AI技术实现智能化升级,打造差异化竞争优势。` : `我们在${cat}领域有明确的技术需求,寻求专业合作伙伴。需要具备AI算法开发、数据处理和系统集成能力。`; descEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '75%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1200); setTimeout(() => { if (seekingEl && !seekingEl.value.trim()) { seekingEl.value = isIdea ? '技术合伙人、联合开发、种子轮投资' : '技术方案提供商、开发外包、技术咨询'; seekingEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '100%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; setTimeout(() => { if (progress) progress.style.display = 'none'; }, 1500); showToast(`AI已自动补录 ${filledCount} 个字段,请确认后保存`, 'success'); }, 1600); } // ============================================================ // 数据集发布 AI 信息补录 - 文件上传 + 智能提取 // ============================================================ let uploadedDatasetFiles = []; function enhanceDatasetForm() { const modal = document.getElementById('datasetPublishModal'); if (!modal) return; if (modal.querySelector('.ai-upload-zone')) return; // already enhanced const body = modal.querySelector('.modal__body'); if (!body) return; const submitBtn = modal.querySelector('button[onclick="submitDataset()"]'); if (!submitBtn) return; const uploadHtml = `
📤
点击或拖拽文件上传,AI自动解析填充
支持 PDF / Word / Excel / 图片 / CSV / JSON,最大10MB
`; const aiBtnHtml = `
`; body.insertAdjacentHTML('afterbegin', aiBtnHtml + uploadHtml); const zone = document.getElementById('datasetFileZone'); zone.addEventListener('dragover', e => { e.preventDefault(); zone.classList.add('dragover'); }); zone.addEventListener('dragleave', () => zone.classList.remove('dragover')); zone.addEventListener('drop', e => { e.preventDefault(); zone.classList.remove('dragover'); if (e.dataTransfer.files.length) handleDatasetFiles(e.dataTransfer.files); }); } function handleDatasetFileSelect(e) { if (e.target.files.length) handleDatasetFiles(e.target.files); } function handleDatasetFiles(fileList) { uploadedDatasetFiles = []; Array.from(fileList).forEach(file => { if (file.size > 10 * 1024 * 1024) { showToast(`文件 ${file.name} 超过10MB限制`, 'error'); return; } uploadedDatasetFiles.push({ name: file.name, size: file.size, status: 'processing' }); }); renderDatasetFileList(); uploadedDatasetFiles.forEach((f, i) => { setTimeout(() => { f.status = 'done'; renderDatasetFileList(); if (uploadedDatasetFiles.every(x => x.status === 'done')) { setTimeout(() => aiFillDatasetForm(), 500); } }, 1000 + i * 800 + Math.random() * 1000); }); } function renderDatasetFileList() { const list = document.getElementById('datasetFileList'); if (!list) return; list.innerHTML = uploadedDatasetFiles.map(f => `
${getFileIcon(f.name)}
${f.name}
${formatFileSize(f.size)}
${f.status==='processing'?'⏳':'✅'}
`).join(''); } function aiFillDatasetForm() { const nameEl = document.getElementById('dsName'); const catEl = document.getElementById('dsCategory'); const descEl = document.getElementById('dsDesc'); const scaleEl = document.getElementById('dsScale'); const formatEl = document.getElementById('dsFormat'); if (!nameEl) return; const progress = document.getElementById('aiDatasetProgress'); const fill = document.getElementById('aiDatasetProgressFill'); const text = document.getElementById('aiDatasetProgressText'); if (progress) progress.style.display = 'flex'; const fileKeywords = uploadedDatasetFiles.map(f => f.name).join(' '); let filledCount = 0; const totalFields = 5; // Step 1: 数据集名称 setTimeout(() => { if (!nameEl.value.trim()) { if (uploadedDatasetFiles.length > 0) { const baseName = uploadedDatasetFiles[0].name.replace(/\.[^.]+$/,'').replace(/[\d\-_]+/g,' ').trim(); nameEl.value = baseName || 'AI推荐高质量数据集'; } else { nameEl.value = 'AI推荐高质量数据集'; } nameEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '20%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 400); // Step 2: 产业分类 setTimeout(() => { if (!catEl.value) { const cats = PRODUCT_CATEGORIES.map(c => c.name); let matched = cats.find(c => fileKeywords.includes(c.replace('AI',''))); // 文件名关键词匹配 if (!matched) { if (/交通|车辆|路口/.test(fileKeywords)) matched = '智慧交通'; else if (/医疗|健康|病历|医学/.test(fileKeywords)) matched = '医疗健康'; else if (/金融|交易|银行|信贷/.test(fileKeywords)) matched = '金融科技'; else if (/制造|工业|工厂|产线/.test(fileKeywords)) matched = '工业制造'; else if (/农业|种植|养殖/.test(fileKeywords)) matched = '智慧农业'; else if (/零售|商品|消费|电商/.test(fileKeywords)) matched = '新零售'; else matched = '智慧交通'; } catEl.value = matched; catEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '40%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 800); // Step 3: 数据描述 setTimeout(() => { if (!descEl.value.trim()) { const baseName = nameEl.value || '数据集'; const cat = catEl.value || '相关'; descEl.value = `${baseName} - 基于AI分析,涵盖${cat}领域多维度高质量数据。数据经过严格清洗、去重和标注,适用于AI模型训练、评测和研究。支持多种数据格式交付,可根据需求定制数据规模和字段。`; descEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '60%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1200); // Step 4: 数据规模 setTimeout(() => { if (!scaleEl.value) { let scale = '10-100万条'; if (/海量|大规模|百万|千万/.test(fileKeywords)) scale = '100万条+'; else if (/小|样本|少量|demo/.test(fileKeywords.toLowerCase())) scale = '<1万条'; else if (/中等|常规/.test(fileKeywords)) scale = '1-10万条'; scaleEl.value = scale; scaleEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '80%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1600); // Step 5: 数据格式 setTimeout(() => { if (!formatEl.value.trim()) { let fmt = 'JSON'; const ext = uploadedDatasetFiles.length > 0 ? uploadedDatasetFiles[0].name.split('.').pop().toLowerCase() : ''; if (['csv'].includes(ext)) fmt = 'CSV'; else if (['xls','xlsx'].includes(ext)) fmt = 'Excel(XLSX)'; else if (['json'].includes(ext)) fmt = 'JSON'; else if (['jpg','jpeg','png','bmp'].includes(ext)) fmt = '图像(JPG/PNG)'; else if (['wav','mp3'].includes(ext)) fmt = '音频(WAV)'; else if (['txt'].includes(ext)) fmt = 'TXT'; else if (/图像|图片|视觉/.test(fileKeywords)) fmt = '图像(JPG)'; else if (/音频|语音|声/.test(fileKeywords)) fmt = '音频(WAV)'; else if (/视频|影像/.test(fileKeywords)) fmt = '视频(MP4)'; formatEl.value = fmt; formatEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '100%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; setTimeout(() => { if (progress) progress.style.display = 'none'; }, 1500); showToast(`AI已自动补录 ${filledCount} 个字段,请确认后提交`, 'success'); }, 2000); } // ============================================================ // OPC发布 AI 信息补录 - 文件上传 + 智能提取 // ============================================================ let uploadedOpcFiles = []; function enhanceOpcForm() { const modal = document.getElementById('opcPublishModal'); if (!modal) return; if (modal.querySelector('.ai-upload-zone')) return; const body = modal.querySelector('.modal__body'); if (!body) return; const submitBtn = modal.querySelector('button[onclick="submitOpc()"]'); if (!submitBtn) return; const uploadHtml = `
📤
点击或拖拽文件上传,AI自动解析填充
支持 PDF / Word / Excel / 图片 / CSV / JSON,最大10MB
`; const aiBtnHtml = `
`; body.insertAdjacentHTML('afterbegin', aiBtnHtml + uploadHtml); const zone = document.getElementById('opcFileZone'); zone.addEventListener('dragover', e => { e.preventDefault(); zone.classList.add('dragover'); }); zone.addEventListener('dragleave', () => zone.classList.remove('dragover')); zone.addEventListener('drop', e => { e.preventDefault(); zone.classList.remove('dragover'); if (e.dataTransfer.files.length) handleOpcFiles(e.dataTransfer.files); }); } function handleOpcFileSelect(e) { if (e.target.files.length) handleOpcFiles(e.target.files); } function handleOpcFiles(fileList) { uploadedOpcFiles = []; Array.from(fileList).forEach(file => { if (file.size > 10 * 1024 * 1024) { showToast(`文件 ${file.name} 超过10MB限制`, 'error'); return; } uploadedOpcFiles.push({ name: file.name, size: file.size, status: 'processing' }); }); renderOpcFileList(); uploadedOpcFiles.forEach((f, i) => { setTimeout(() => { f.status = 'done'; renderOpcFileList(); if (uploadedOpcFiles.every(x => x.status === 'done')) { setTimeout(() => aiFillOpcForm(), 500); } }, 1000 + i * 800 + Math.random() * 1000); }); } function renderOpcFileList() { const list = document.getElementById('opcFileList'); if (!list) return; list.innerHTML = uploadedOpcFiles.map(f => `
${getFileIcon(f.name)}
${f.name}
${formatFileSize(f.size)}
${f.status==='processing'?'⏳':'✅'}
`).join(''); } function aiFillOpcForm() { const titleEl = document.getElementById('opcTitle'); const catEl = document.getElementById('opcCategory'); const descEl = document.getElementById('opcDesc'); const seekingEl = document.getElementById('opcSeeking'); if (!titleEl) return; const progress = document.getElementById('aiOpcProgress'); const fill = document.getElementById('aiOpcProgressFill'); const text = document.getElementById('aiOpcProgressText'); if (progress) progress.style.display = 'flex'; const fileKeywords = uploadedOpcFiles.map(f => f.name).join(' '); let filledCount = 0; const totalFields = 4; // 获取发布类型 const typeRadio = document.querySelector('input[name="opcType"]:checked'); const isIdea = typeRadio ? typeRadio.value === 'idea' : true; // Step 1: 标题 setTimeout(() => { if (!titleEl.value.trim()) { if (uploadedOpcFiles.length > 0) { const baseName = uploadedOpcFiles[0].name.replace(/\.[^.]+$/,'').replace(/[\d\-_]+/g,' ').trim(); titleEl.value = isIdea ? (baseName || 'AI赋能创新项目') : (baseName || 'AI技术合作需求'); } else { titleEl.value = isIdea ? 'AI赋能创新项目' : 'AI技术合作需求'; } titleEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '25%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 400); // Step 2: 所属领域 setTimeout(() => { if (!catEl.value) { const cats = PRODUCT_CATEGORIES.map(c => c.name); let matched = cats.find(c => fileKeywords.includes(c.replace('AI',''))); if (!matched) { if (/交通|车辆|出行/.test(fileKeywords)) matched = '智慧交通'; else if (/医疗|健康|医学/.test(fileKeywords)) matched = '医疗健康'; else if (/金融|交易|银行/.test(fileKeywords)) matched = '金融科技'; else if (/制造|工业|工厂/.test(fileKeywords)) matched = '工业制造'; else if (/农业|种植|养殖/.test(fileKeywords)) matched = '智慧农业'; else if (/零售|商品|消费/.test(fileKeywords)) matched = '新零售'; else if (/教育|学习|课程/.test(fileKeywords)) matched = '智慧教育'; else matched = 'AI应用开发'; } catEl.value = matched; catEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '50%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 800); // Step 3: 详细描述 setTimeout(() => { if (!descEl.value.trim()) { const baseTitle = titleEl.value || '项目'; const cat = catEl.value || 'AI'; if (isIdea) { descEl.value = `${baseTitle} - 基于${cat}领域的创新理念,旨在通过AI技术解决行业痛点。\n\n背景:当前${cat}领域存在效率低、成本高的问题,传统方案难以满足快速增长的需求。\n\n目标:利用AI技术实现智能化升级,打造差异化竞争优势。\n\n预期效果:显著提升运营效率,降低人力成本,预计可带来30%以上的效率提升。`; } else { descEl.value = `${baseTitle} - 我们在${cat}领域有明确的技术需求,寻求专业合作伙伴。\n\n需求背景:项目正在推进中,在${cat}相关技术环节需要外部支持。\n\n技术要求:需要具备AI算法开发、数据处理和系统集成能力。\n\n预期目标:在约定时间内完成技术对接和系统部署,确保稳定运行。`; } descEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '75%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; }, 1200); // Step 4: 寻求合作 setTimeout(() => { if (!seekingEl.value.trim()) { seekingEl.value = isIdea ? '技术合伙人、联合开发、种子轮投资、市场推广' : '技术方案提供商、开发外包、技术咨询、联合交付'; seekingEl.classList.add('ai-filled'); filledCount++; } if (fill) fill.style.width = '100%'; if (text) text.textContent = `${filledCount}/${totalFields} 已填充`; setTimeout(() => { if (progress) progress.style.display = 'none'; }, 1500); showToast(`AI已自动补录 ${filledCount} 个字段,请确认后提交`, 'success'); }, 1600); } // 增强 showAddProductForm,添加文件上传和AI补录 const _origShowAddProductForm = showAddProductForm; showAddProductForm = function() { const total = AuthManager.getTotalPublishCount(); if (total >= AuthManager.PUBLISH_TOTAL_LIMIT) { showToast(`发布总数已达上限(${AuthManager.PUBLISH_TOTAL_LIMIT}个),请先删除部分内容再发布`, 'error'); return; } _origShowAddProductForm(); uploadedProductFiles = []; enhanceProductForm(); }; // 增强数据集发布弹窗,添加文件上传和AI补录 const _origOpenDatasetPublish = openDatasetPublish; openDatasetPublish = function() { _origOpenDatasetPublish(); uploadedDatasetFiles = []; enhanceDatasetForm(); }; // 增强OPC发布弹窗,添加文件上传和AI补录 const _origOpenOpcPublish = openOpcPublish; openOpcPublish = function() { _origOpenOpcPublish(); uploadedOpcFiles = []; enhanceOpcForm(); }; // ============================================================ // FAQ 知识库管理系统 // ============================================================ // --- 终端商品FAQ --- let _tpFaqItems = []; function addFaqItem(q, a) { _tpFaqItems.push({ q: q || '', a: a || '' }); renderTpFaqList(); } function removeFaqItem(index) { _tpFaqItems.splice(index, 1); renderTpFaqList(); } function renderTpFaqList() { var container = document.getElementById('tpFaqList'); if (!container) return; container.innerHTML = _tpFaqItems.map(function(item, i) { return '
' + '
' + '
' + '
' + '
' + '' + '
'; }).join(''); } function aiGenerateFaq() { var name = document.getElementById('tpName') ? document.getElementById('tpName').value.trim() : ''; var cat = document.getElementById('tpCategory') ? document.getElementById('tpCategory').value : ''; var desc = document.getElementById('tpDesc') ? document.getElementById('tpDesc').value.trim() : ''; var specs = document.getElementById('tpSpecs') ? document.getElementById('tpSpecs').value.trim() : ''; var price = document.getElementById('tpPrice') ? document.getElementById('tpPrice').value.trim() : ''; if (!name) { showToast('请先填写商品名称', 'warning'); return; } var catName = {glasses:'AI眼镜',ring:'智能戒指',watch:'智能手表',earphone:'AI耳机',other:'AI终端'}[cat] || 'AI终端'; var specsText = specs ? '规格参数:' + specs : ''; var generatedFaqs = [ { q: '这个产品的续航时间是多久?', a: '根据产品规格' + (specs || '') + ',续航时间可达8小时以上,支持快充功能,30分钟可充至80%电量。' }, { q: '支持什么设备连接?', a: '支持蓝牙5.3和WiFi双模连接,兼容Android 8.0+和iOS 13+系统,可同时连接2台设备。' }, { q: '产品保修期是多久?', a: '整机保修1年,电池保修6个月。保修期内非人为损坏免费维修或更换。' }, { q: '价格可以优惠吗?支持批量采购吗?', a: '商品标价¥' + (price || '面议') + ',批量采购3件以上享95折,10件以上享9折。可联系商家商议具体价格。' }, { q: '发货时间和物流方式?', a: '下单后24小时内发货,默认顺丰快递,全国包邮。偏远地区可能需要加收运费。' }, { q: '产品有什么核心功能?', a: (desc || catName + '核心功能包括AI智能交互、语音助手、健康监测等。') + '具体功能可查看商品详情页介绍。' }, { q: '可以试用或体验吗?', a: '目前支持7天无理由退换货。如需体验可前往线下体验店,或联系商家预约线上演示。' }, { q: '产品重量和佩戴舒适度如何?', a: (specsText || '产品采用轻量化设计') + ',重量控制在45g以内,长时间佩戴舒适无压迫感。' } ]; _tpFaqItems = generatedFaqs; renderTpFaqList(); showToast('AI已生成' + generatedFaqs.length + '条FAQ问答', 'success'); } // --- 产品管理(PM)统一发布FAQ --- let _pmFaqItems = []; function addPmFaqItem(q, a) { _pmFaqItems.push({ q: q || '', a: a || '' }); renderPmFaqList(); } function removePmFaqItem(index) { _pmFaqItems.splice(index, 1); renderPmFaqList(); } function renderPmFaqList() { var container = document.getElementById('pmFaqList'); if (!container) return; container.innerHTML = _pmFaqItems.map(function(item, i) { return '
' + '
' + '
' + '
' + '
' + '' + '
'; }).join(''); } function aiGeneratePmFaq() { var type = window._publishType || 'product'; var name = '', desc = '', cat = ''; if (type === 'product') { name = val('newProductName'); cat = val('newProductCategory'); desc = val('newProductIntro') + ' ' + val('newProductScenario'); } else if (type === 'dataset') { name = val('pmDsName'); cat = val('pmDsCategory'); desc = val('pmDsDesc'); } else { name = val('pmOpcTitle'); cat = val('pmOpcCategory'); desc = val('pmOpcDesc'); } if (!name) { showToast('请先填写名称', 'warning'); return; } var faqs; if (type === 'dataset') { faqs = [ { q: '数据集的规模有多大?', a: val('pmDsScale') ? '数据规模:' + val('pmDsScale') : '数据规模可根据需求定制,详见数据集描述。' }, { q: '数据格式是什么?', a: val('pmDsFormat') ? '数据格式为' + val('pmDsFormat') + ',可根据需求转换为其他格式。' : '支持JSON/CSV等标准格式,可按需转换。' }, { q: '数据质量和标注情况如何?', a: '数据经过严格清洗和质量校验,标注准确率>95%。可提供数据质量报告。' }, { q: '授权范围和使用期限?', a: '支持研究用途和商用授权,授权期限可协商(1年/3年/永久),具体可进一步沟通。' }, { q: '可以提供数据样本吗?', a: '可以提供部分脱敏样本供评估,确认合作后提供完整数据集。' }, { q: '交付方式有哪些?', a: '支持API接口调用、安全下载链接、私有化部署三种交付方式。' } ]; } else if (type === 'opc') { faqs = [ { q: '项目的核心创新点是什么?', a: desc || '核心创新点详见项目描述,欢迎进一步沟通了解。' }, { q: '目前项目处于什么阶段?', a: '项目已有初步方案和技术验证,正在寻找合适的合作伙伴推进落地。' }, { q: '期望什么样的合作模式?', a: val('pmOpcSeeking') || '支持技术合伙、联合开发、投资等多种合作模式,具体可协商。' }, { q: '知识产权如何分配?', a: '知识产权按贡献比例分配,具体在合作协议中明确约定。' }, { q: '预期的时间节点?', a: '预计3-6个月完成MVP,6-12个月实现产品化落地。' } ]; } else { faqs = [ { q: '产品的核心功能有哪些?', a: desc || '产品核心功能详见产品介绍,包括核心技术和应用场景。' }, { q: '支持哪些行业和场景?', a: val('newProductScenario') || '适用于多个行业场景,可根据客户需求定制。' }, { q: '价格如何?', a: window._priceType === 'negotiable' ? '价格根据具体需求面议,可提供多种方案选择。' : '价格:' + val('newProductPrice') + ',可根据合作规模协商。' }, { q: '交付周期多长?', a: '标准版2-4周交付,定制版根据需求复杂度4-8周。' }, { q: '提供售后服务吗?', a: '提供完整售后支持,包括免费维护期3个月、技术支持、版本升级等。' }, { q: '可以定制开发吗?', a: '支持完全定制开发,可根据您的业务需求进行功能定制和系统集成。' } ]; } _pmFaqItems = faqs; renderPmFaqList(); showToast('AI已生成' + faqs.length + '条FAQ问答', 'success'); function val(id) { var el = document.getElementById(id); return el ? el.value.trim() : ''; } } // ============================================================ // AI对话三层混合架构(知识库 → 大模型 → 人工兜底) // ============================================================ // AI配置(后端地址,留空则使用本地降级模式) const AI_CHAT_CONFIG = { backendUrl: '', // 如 'http://localhost:3000/api/ai-chat',留空则纯本地模式 enableKbMatch: true, enableAiApi: true, enableHumanFallback: true, kbMatchThreshold: 0.35 // 关键词匹配阈值 }; // 从产品数据中提取FAQ知识库 function getProductFaq(conv) { if (!conv || !conv.sourceId) return []; var sourceType = conv.sourceType; var sourceId = conv.sourceId; if (sourceType === 'terminal') { var products = platformData.terminalProducts || []; var p = products.find(function(x) { return x.id === sourceId; }); return (p && p.faq) ? p.faq : []; } if (sourceType === 'provider') { var providers = platformData.providers || []; var sp = providers.find(function(x) { return x.id === sourceId; }); if (sp && sp.faq) return sp.faq; // 生成默认FAQ return [ { q: '服务价格', a: sp ? (sp.priceRange || '价格面议') : '价格面议' }, { q: '服务范围', a: sp ? (sp.services || []).join('、') : '' }, { q: '公司地址', a: sp ? (sp.location || '') : '' } ]; } if (sourceType === 'dataset') { var datasets = platformData.datasets || []; var d = datasets.find(function(x) { return x.id === sourceId; }); if (d && d.faq) return d.faq; return [ { q: '数据规模', a: d ? (d.scale || '') : '' }, { q: '数据格式', a: d ? (d.format || '') : '' }, { q: '数据分类', a: d ? (d.category || '') : '' } ]; } if (sourceType === 'opc') { var opcItems = platformData.opc || []; var o = opcItems.find(function(x) { return x.id === sourceId; }); if (o && o.faq) return o.faq; return [ { q: '合作领域', a: o ? (o.category || '') : '' }, { q: '合作意向', a: o ? (o.seeking || '') : '' } ]; } return []; } // 第一层:知识库关键词匹配 function matchFaqKb(userMsg, faqList) { if (!faqList || faqList.length === 0) return null; var msg = userMsg.toLowerCase(); var bestMatch = null; var bestScore = 0; faqList.forEach(function(faq) { if (!faq.q || !faq.a) return; var q = faq.q.toLowerCase(); var score = 0; // 分词匹配 var keywords = q.split(/[\s,,。??、的了吗呢吧啊是可以有和与及或/]+/).filter(function(w) { return w.length > 1; }); keywords.forEach(function(kw) { if (msg.indexOf(kw) >= 0) score += kw.length * 0.15; }); // 完整问题包含匹配 if (msg.indexOf(q) >= 0 || q.indexOf(msg) >= 0) score += 0.5; // 关键词重叠度 var msgWords = msg.split(/[\s,,。??、的了吗呢吧啊是有和与及或/]+/).filter(function(w) { return w.length > 1; }); var overlap = msgWords.filter(function(w) { return q.indexOf(w) >= 0; }).length; score += overlap * 0.08; if (score > bestScore) { bestScore = score; bestMatch = faq; } }); if (bestScore >= AI_CHAT_CONFIG.kbMatchThreshold) { return { answer: bestMatch.answer, score: bestScore, source: 'kb' }; } return null; } // 第二层:调用后端AI大模型API async function callAiApi(userMsg, conv, history) { if (!AI_CHAT_CONFIG.backendUrl || !AI_CHAT_CONFIG.enableAiApi) { return null; // 没有配置后端,返回null触发降级 } var productContext = buildProductContext(conv); var systemPrompt = '你是一个专业的供需对接平台AI客服助手。以下是产品/服务信息,请基于这些信息回答用户问题。' + '回复要简洁专业,使用中文。如果问题涉及报价、谈判、定制需求等复杂问题,建议用户联系供方。'; var payload = { message: userMsg, context: productContext, history: history.slice(-6).map(function(m) { return { role: m.type === 'user' ? 'user' : 'assistant', content: m.text }; }), systemPrompt: systemPrompt }; try { var resp = await fetch(AI_CHAT_CONFIG.backendUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!resp.ok) throw new Error('API error: ' + resp.status); var data = await resp.json(); return { answer: data.reply || data.content || '', source: 'ai' }; } catch(e) { console.warn('[AI Chat] 后端调用失败,降级到模板模式:', e.message); return null; } } // 构建产品上下文(发给大模型) function buildProductContext(conv) { var cp = conv.counterparty; var ctx = '对话对象:' + (cp.name || '未知') + '\n'; ctx += '类型:' + (conv.sourceType || '') + '\n'; if (conv.sourceType === 'terminal') { var p = (platformData.terminalProducts || []).find(function(x) { return x.id === conv.sourceId; }); if (p) { ctx += '商品名称:' + p.name + '\n'; ctx += '品牌:' + (p.brand || '') + '\n'; ctx += '分类:' + (p.category || '') + '\n'; ctx += '价格:¥' + p.price + '\n'; ctx += '描述:' + (p.description || '') + '\n'; ctx += '规格:' + (p.specs || '') + '\n'; } } else if (conv.sourceType === 'provider') { var sp = (platformData.providers || []).find(function(x) { return x.id === conv.sourceId; }); if (sp) { ctx += '服务商:' + sp.name + '\n'; ctx += '领域:' + (sp.category || '') + '\n'; ctx += '位置:' + (sp.location || '') + '\n'; ctx += '服务:' + (sp.services || []).join('、') + '\n'; ctx += '价格范围:' + (sp.priceRange || '') + '\n'; } } else if (conv.sourceType === 'dataset') { var d = (platformData.datasets || []).find(function(x) { return x.id === conv.sourceId; }); if (d) { ctx += '数据集:' + d.name + '\n'; ctx += '规模:' + (d.scale || '') + '\n'; ctx += '格式:' + (d.format || '') + '\n'; ctx += '描述:' + (d.description || '') + '\n'; } } else if (conv.sourceType === 'opc') { var o = (platformData.opc || []).find(function(x) { return x.id === conv.sourceId; }); if (o) { ctx += '项目:' + o.title + '\n'; ctx += '领域:' + (o.category || '') + '\n'; ctx += '寻找:' + (o.seeking || '') + '\n'; } } // 附带FAQ知识库 var faqs = getProductFaq(conv); if (faqs.length > 0) { ctx += '\n已知FAQ:\n'; faqs.forEach(function(f) { ctx += 'Q: ' + f.q + '\nA: ' + f.a + '\n'; }); } return ctx; } // 判断是否需要转人工 function shouldEscalateToHuman(userMsg) { var keywords = ['报价', '价格', '多少钱', '预算', '谈判', '砍价', '优惠', '折扣', '合同', '签约', '定制', '需求定制', '合作', '投资', '融资', '股权', '退款', '投诉', '纠纷', '售后问题', '发货', '物流', '退换货', '发票', '对接人', '联系方式', '电话', '面谈', '线下']; var msg = userMsg.toLowerCase(); return keywords.some(function(kw) { return msg.indexOf(kw) >= 0; }); } // 第三层:人工兜底 function escalateToHuman(conv) { conv.needHuman = true; conv.humanReason = '用户问题涉及报价/合作/售后等复杂事项'; return { answer: '您的问题已转交供方人工处理。\n\n🔔 已通知「' + (conv.counterparty.name || '供方') + '」尽快回复您。\n\n您也可以直接点击下方"转人工"按钮,供方会收到实时提醒。', source: 'human' }; } // 主函数:三层混合AI对话 async function generateHybridAiResponse(msg, conv) { // 第一层:知识库匹配 if (AI_CHAT_CONFIG.enableKbMatch) { var faqs = getProductFaq(conv); var kbMatch = matchFaqKb(msg, faqs); if (kbMatch) { await sleep(400 + Math.random() * 600); return kbMatch; } } // 判断是否需要转人工(在调大模型之前) if (AI_CHAT_CONFIG.enableHumanFallback && shouldEscalateToHuman(msg)) { await sleep(600 + Math.random() * 800); return escalateToHuman(conv); } // 第二层:调用大模型API var aiResult = await callAiApi(msg, conv, conv.messages); if (aiResult && aiResult.answer) { return aiResult; } // 降级:使用模板回复(当前模式) await sleep(800 + Math.random() * 1200); return { answer: generateTemplateResponse(msg, conv), source: 'template' }; } function sleep(ms) { return new Promise(function(r) { setTimeout(r, ms); }); } // 模板回复(降级模式,保留原有逻辑) function generateTemplateResponse(msg, conv) { // 复用原有的模板逻辑 return _origGenerateConsultAiResponse(msg, conv); } // 保存原始模板函数 const _origGenerateConsultAiResponse = generateConsultAiResponse; generateConsultAiResponse = generateTemplateResponse; // 重写 sendConsultMsg 支持异步AI回复 const _origSendConsultMsg = sendConsultMsg; sendConsultMsg = async function() { var input = document.getElementById('consultMsgInput'); var msg = input.value.trim(); if (!msg || !consultCurrentId) return; input.value = ''; var c = CONSULT_CONVS.find(function(x) { return x.id === consultCurrentId; }); if (!c) return; // 添加用户消息 c.messages.push({ type: 'user', text: msg, time: Date.now() }); c.updatedAt = Date.now(); renderConsultMessages(c); renderConsultList(); // 显示"AI正在输入..." c.messages.push({ type: 'ai_typing', text: '', time: Date.now() }); renderConsultMessages(c); // 调用混合AI回复 try { var result = await generateHybridAiResponse(msg, c); // 移除typing消息 var typingIdx = c.messages.findIndex(function(m) { return m.type === 'ai_typing'; }); if (typingIdx >= 0) c.messages.splice(typingIdx, 1); c.messages.push({ type: 'ai', text: result.answer, time: Date.now(), source: result.source }); c.updatedAt = Date.now(); renderConsultMessages(c); renderConsultList(); } catch(e) { // 移除typing消息 var typingIdx2 = c.messages.findIndex(function(m) { return m.type === 'ai_typing'; }); if (typingIdx2 >= 0) c.messages.splice(typingIdx2, 1); c.messages.push({ type: 'ai', text: '抱歉,回复出现异常,请稍后重试或点击"转人工"联系供方。', time: Date.now(), source: 'error' }); renderConsultMessages(c); } }; // 转人工功能 function consultEscalateToHuman() { if (!consultCurrentId) return; var c = CONSULT_CONVS.find(function(x) { return x.id === consultCurrentId; }); if (!c) return; c.needHuman = true; c.humanRequestedAt = Date.now(); c.messages.push({ type: 'system', text: '🔔 已通知供方「' + (c.counterparty.name || '') + '」人工介入。供方将尽快回复您的问题。', time: Date.now() }); renderConsultMessages(c); renderConsultList(); showToast('已通知供方人工处理', 'success'); }