产品思维操作系统
汇聚 15 位顶级产品大师的 92 个思维模型。搜索、浏览,或直接向专家提问——让他们从不同角度质询你的决策。
思维模型库
加载中…
没有匹配的模型。试试清除筛选或调整搜索关键词。
让专家追问你
基于上面的模型,10 位专家会从不同角度质询你——不给答案,只逼你想清楚。
汇聚 15 位顶级产品大师的 92 个思维模型。搜索、浏览,或直接向专家提问——让他们从不同角度质询你的决策。
加载中…
没有匹配的模型。试试清除筛选或调整搜索关键词。
基于上面的模型,10 位专家会从不同角度质询你——不给答案,只逼你想清楚。
🤔 ' + escapeHtml(content) + '
'; var optWrap = document.createElement('div'); optWrap.className = 'flex flex-wrap gap-2 mt-2'; if (options && options.length) { options.forEach(function(opt) { var optBtn = document.createElement('button'); optBtn.textContent = opt; optBtn.className = 'clarify-option text-xs px-3 py-1.5 rounded-full transition-colors'; optBtn.style.cssText = 'border:1px solid #fbbf2480; color:#fbbf24; background:transparent; cursor:pointer;'; optBtn.addEventListener('click', function() { input.value = opt; autoGrow(); // 标记为澄清回答,触发发送时 payload 会带上 isClarAnswer = true; triggerAsk(); }); optBtn.addEventListener('mouseenter', function() { optBtn.style.background = '#fbbf2420'; }); optBtn.addEventListener('mouseleave', function() { optBtn.style.background = 'transparent'; }); optWrap.appendChild(optBtn); }); } bubble.appendChild(optWrap); } else { // 普通消息:带角色标签 var label = document.createElement('div'); label.style.cssText = 'font-size:10px; margin-bottom:4px;'; if (role === 'user') { label.textContent = '你'; label.style.color = 'var(--color-text-dim)'; } else { label.textContent = '专家追问'; label.style.color = 'var(--color-accent)'; } bubble.appendChild(label); var body = document.createElement('div'); body.style.cssText = 'color: var(--color-text); line-height:1.7;'; body.innerHTML = role === 'user' ? escapeHtml(content) : formatAnswer(content); bubble.appendChild(body); } wrapper.appendChild(avatar); wrapper.appendChild(bubble); resultContent.appendChild(wrapper); // 滚动到底部 resultContent.scrollTop = resultContent.scrollHeight; } // ============== v2 增强 triggerAsk ============== function triggerAsk() { var question = input.value.trim(); if (!question) { input.focus(); return; } // 检查每日限流 var today = new Date().toISOString().slice(0, 10); var usageKey = 'pm_usage_' + today; var usage = parseInt(localStorage.getItem(usageKey) || '0'); if (usage >= 30) { resultPanel.classList.remove('hidden'); loading.classList.add('hidden'); resultContent.classList.remove('hidden'); statusIcon.textContent = '⚠️'; statusText.textContent = '今日额度已用完'; resultContent.innerHTML = '今日追问次数已达上限(30次),明天再来吧!
'; return; } // 显示结果面板 resultPanel.classList.remove('hidden'); // v2 多轮:如果已有 session,直接追加而不是清空 if (sessionId) { // 追加模式:不清空已有内容 appendMessage('user', question); // 加一个加载指示器 var loadMsg = document.createElement('div'); loadMsg.className = 'chat-msg chat-msg-assistant'; loadMsg.id = 'chat-loading-msg'; loadMsg.innerHTML = '⚔' + escapeHtml(data.error) + '
'; return; } // v2: 保存 session_id if (data.session_id) { sessionId = data.session_id; } // v2.1: 处理澄清请求 if (data.needs_clarification) { clarificationPending = true; pendingClarifyTerm = data.term; appendMessage('clarify', data.message, data.options); input.value = ''; input.focus(); } else { clarificationPending = false; pendingClarifyTerm = null; resultContent.classList.remove('hidden'); if (resultContent.querySelector('.chat-msg')) { // 多轮模式:追加回答到聊天区 appendMessage('assistant', data.answer); statusIcon.textContent = '⚔'; statusText.textContent = '专家追问'; } else { // 首轮:显示完整回答 + 匹配模型链接 statusIcon.textContent = '⚔'; statusText.textContent = '专家追问'; appendMessage('user', question); appendMessage('assistant', data.answer); } // 匹配模型标签(始终显示) if (firstModels.length > 0 && !document.getElementById('model-tags')) { var tagDiv = document.createElement('div'); tagDiv.id = 'model-tags'; tagDiv.className = 'mt-3 pt-3 flex flex-wrap gap-2'; tagDiv.style.borderTop = '1px solid var(--color-border)'; for (var i = 0; i < firstModels.length; i++) { var m = firstModels[i].model; tagDiv.innerHTML += '' + m.expert + '·' + m.name + ''; } resultContent.appendChild(tagDiv); } } // 清空输入框,准备下一轮 input.value = ''; input.style.height = 'auto'; // 记录使用 localStorage.setItem(usageKey, String(usage + 1)); saveToLog(question); }) .catch(function(err) { clearTimeout(fetchTimeoutId); clearTimeout(slowHintTimerId); var loadMsg = document.getElementById('chat-loading-msg'); if (loadMsg) loadMsg.remove(); var isTimeout = abortController && abortController._isTimeout; if (err && err.name === 'AbortError' && !isTimeout) return; abortController = null; stopThinkingAnimation(); loading.classList.add('hidden'); setLoadingState(false); resultContent.classList.remove('hidden'); if (isTimeout) { showError(504, 'GLM 响应超时(75秒)', question, matchedModels); } else { showError(0, (err && err.message) || '网络请求失败', question, matchedModels); } saveToLog(question); }); } function showError(status, errMsg, question, matchedModels) { statusIcon.textContent = status === 429 ? '⏳' : '⚠️'; statusText.textContent = status === 429 ? '请求过于频繁' : status >= 500 ? 'GLM 服务暂时异常' : '出了点问题'; if (status === 429) { resultContent.innerHTML = '' + escapeHtml(errMsg) + '
'; } else if (status >= 500 || status === 0 || (status === 200 && errMsg)) { resultContent.innerHTML = '' + escapeHtml(errMsg) + '
' + renderLocalResult(question, matchedModels); } } function setLoadingState(loading) { isLoading = loading; input.disabled = false; if (loading) { btnLabel.classList.add('hidden'); btnSpinner.classList.remove('hidden'); btnSpinner.classList.add('inline-flex'); } else { btnLabel.classList.remove('hidden'); btnSpinner.classList.add('hidden'); btnSpinner.classList.remove('inline-flex'); } } function cancelAsk() { if (abortController) { abortController.abort(); abortController = null; } stopThinkingAnimation(); loading.classList.add('hidden'); resultContent.classList.remove('hidden'); setLoadingState(false); var loadMsg = document.getElementById('chat-loading-msg'); if (loadMsg) loadMsg.remove(); statusIcon.textContent = '⏸'; statusText.textContent = '已取消'; } function startThinkingAnimation(matchedExperts) { var steps = ['正在匹配相关专家…']; if (matchedExperts && matchedExperts.length > 0) { var names = matchedExperts.slice(0, 3).map(function(m){ return m.expert; }).join('、'); steps.push('召唤 ' + names + ' 进入思考…'); steps.push(names.split('、')[0] + '正在调取心智模型…'); steps.push('多视角对撞中,寻找冲突核心…'); steps.push('组织追问语言中…'); } else { steps.push('召唤专家进入思考…'); steps.push('多视角对撞中…'); steps.push('组织追问语言中…'); } var i = 0; thinkingStep.textContent = steps[0]; if (thinkingTimer) clearInterval(thinkingTimer); thinkingTimer = setInterval(function() { i = (i + 1) % steps.length; thinkingStep.style.opacity = '0'; setTimeout(function(){ thinkingStep.textContent = steps[i]; thinkingStep.style.opacity = '1'; }, 200); }, 1800); } function stopThinkingAnimation() { if (thinkingTimer) { clearInterval(thinkingTimer); thinkingTimer = null; } } // ============== 渲染工具函数 ============== function escapeHtml(s) { return String(s).replace(/[&<>"']/g, function(c){ return { '&':'&','<':'<','>':'>','"':'"',"'":''' }[c]; }); } function formatAnswer(text) { return text .replace(/\*\*(.+?)\*\*/g, '$1') .replace(/⚔/g, '⚔') .replace(/💬/g, '💬') .replace(/```markdown\n?/g, '') .replace(/\n```/g, '') .replace(/```/g, '') .replace(/\n\n/g, '')
.replace(/\n- /g, '
• ')
.replace(/\n/g, '
');
}
function getTopModels(q, count) {
var modelData = JSON.parse(document.getElementById('model-triggers-data').textContent);
var matches = [];
for (var i = 0; i < modelData.length; i++) {
var m = modelData[i];
var score = 0;
var triggers = m.triggers || [];
for (var j = 0; j < triggers.length; j++) {
if (q.includes(triggers[j].substring(0, 4)) || triggers[j].includes(q.substring(0, 4))) {
score += 2;
}
}
var domains = m.domains || [];
for (var k = 0; k < domains.length; k++) {
if (q.includes(domains[k])) score += 3;
}
if (q.includes(m.name) || m.name.includes(q.substring(0, 3))) score += 1;
var keywords = ['增长', '克制', '砍', '减法', '招人', '人才', '成本', '速度', '决策', '定价', '付费', '功能', '产品', '用户', '创业', '融资', '竞争', '迭代', '简化', '聚焦', '垂直', '整合', '社区', '社交', '设计', '体验'];
for (var w = 0; w < keywords.length; w++) {
if (q.includes(keywords[w])) {
for (var t = 0; t < triggers.length; t++) {
if (triggers[t].includes(keywords[w])) score += 2;
}
for (var d = 0; d < domains.length; d++) {
if (domains[d].includes(keywords[w])) score += 1;
}
}
}
if (score > 0) matches.push({ model: m, score: score });
}
matches.sort(function(a, b) { return b.score - a.score; });
if (matches.length === 0) {
var shuffled = modelData.sort(function() { return 0.5 - Math.random(); });
matches = shuffled.slice(0, count).map(function(m) { return { model: m, score: 1 }; });
}
return matches.slice(0, count);
}
function renderLocalResult(q, matchedModels) {
var html = '
(AI 暂时不可用,以下为相关模型推荐)
'; for (var idx = 0; idx < matchedModels.length; idx++) { var item = matchedModels[idx].model; var bgColor = item.color || '#7a7a90'; html += ''; } return html; } // ============== 投票(保存到 localStorage) ============== document.addEventListener('click', function(e) { if (e.target.classList.contains('vote-btn')) { var expert = e.target.textContent; var votes = JSON.parse(localStorage.getItem('pm_votes') || '{}'); votes[expert] = (votes[expert] || 0) + 1; localStorage.setItem('pm_votes', JSON.stringify(votes)); e.target.style.background = e.target.style.borderColor; e.target.style.color = '#09090f'; e.target.textContent = '✓ ' + expert; } }); // ============== 决策日志 ============== function saveToLog(question) { var log = JSON.parse(localStorage.getItem('pm_decision_log') || '[]'); log.unshift({ q: question, time: new Date().toISOString() }); if (log.length > 50) log = log.slice(0, 50); localStorage.setItem('pm_decision_log', JSON.stringify(log)); } // ======== 冲突浏览器:筛选 + 加载更多 ======== var allConflictsEl = document.getElementById('all-conflicts-data'); if (allConflictsEl) { var allConflicts = JSON.parse(allConflictsEl.textContent); var conflictListEl = document.getElementById('conflict-list'); var loadMoreBtn = document.getElementById('conflict-load-more'); var remainingEl = document.getElementById('conflict-remaining'); var filterBtns = document.querySelectorAll('.conflict-filter-btn'); var currentDomain = 'all'; var currentLimit = 12; function renderConflicts() { var filtered = currentDomain === 'all' ? allConflicts : allConflicts.filter(function(c) { return (c.domains || []).indexOf(currentDomain) !== -1; }); var visible = filtered.slice(0, currentLimit); var html = visible.map(function(c) { return '