| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937 |
- // Idea House JavaScript - 处理数据字段选择和Coze API处理
- // 全局变量
- let dataFields = [];
- let filteredDataFields = [];
- let selectedFields = new Map(); // 字段ID -> 描述的映射
- // 筛选状态变量
- let columnFilters = {
- id: '',
- description: '',
- type: '',
- coverage: { min: null, max: null },
- userCount: null,
- alphaCount: null
- };
- let sortColumn = null;
- let sortOrder = 'asc';
- // DOM加载完成后初始化
- document.addEventListener('DOMContentLoaded', function() {
- // 设置事件监听器
- document.getElementById('loadDataFieldsBtn').addEventListener('click', loadDataFields);
- document.getElementById('clearSelectionBtn').addEventListener('click', clearSelection);
- document.getElementById('processFieldsBtn').addEventListener('click', processSelectedFields);
- // 设置API令牌切换按钮
- const toggleBtn = document.getElementById('toggleApiTokenBtn');
- const tokenInput = document.getElementById('cozeApiTokenInput');
- toggleBtn.addEventListener('click', function() {
- if (tokenInput.type === 'password') {
- tokenInput.type = 'text';
- toggleBtn.textContent = '隐藏';
- } else {
- tokenInput.type = 'password';
- toggleBtn.textContent = '显示';
- }
- });
- // 加载保存的配置
- loadSavedCozeConfig();
- // 设置保存配置按钮
- document.getElementById('saveCozeConfigBtn').addEventListener('click', saveCozeConfig);
- // 设置清除配置按钮
- document.getElementById('clearCozeConfigBtn').addEventListener('click', clearCozeConfig);
- // 设置筛选事件监听器
- setupFilterEventListeners();
- });
- // 从BRAIN API加载数据字段
- async function loadDataFields() {
- const region = document.getElementById('regionInput').value;
- const delay = document.getElementById('delayInput').value;
- const universe = document.getElementById('universeInput').value;
- const datasetId = document.getElementById('datasetInput').value;
- // 显示加载状态
- document.getElementById('dataFieldsStats').textContent = '正在加载数据字段...';
- document.getElementById('tableContainer').style.display = 'none';
- try {
- // 从localStorage或cookie获取会话ID
- const sessionId = localStorage.getItem('brain_session_id');
- if (!sessionId) {
- alert('请先从主页面连接到BRAIN');
- return;
- }
- // 调用代理端点
- const params = new URLSearchParams({
- region: region,
- delay: delay,
- universe: universe,
- dataset_id: datasetId
- });
- // 记录API调用
- console.log('🚀 正在调用API获取数据字段和数据集描述');
- console.log('📋 参数:', {
- region: region,
- delay: delay,
- universe: universe,
- dataset_id: datasetId
- });
- // 并行获取数据字段和数据集描述
- const [dataFieldsResponse, descriptionResponse] = await Promise.all([
- fetch(`/idea-house/api/get-datafields-proxy?${params}`, {
- method: 'GET',
- headers: {
- 'Session-ID': sessionId
- }
- }),
- fetch(`/idea-house/api/get-dataset-description?${params}`, {
- method: 'GET',
- headers: {
- 'Session-ID': sessionId
- }
- })
- ]);
- console.log('📥 收到响应:');
- console.log(' 数据字段状态:', dataFieldsResponse.status);
- console.log(' 数据集描述状态:', descriptionResponse.status);
- if (!dataFieldsResponse.ok) {
- const errorData = await dataFieldsResponse.json();
- throw new Error(errorData.error || '获取数据字段失败');
- }
- dataFields = await dataFieldsResponse.json();
- // 获取数据集描述(如果可用)
- let datasetDescription = '';
- if (descriptionResponse.ok) {
- console.log('✅ 数据集描述响应正常,正在解析JSON...');
- const descriptionData = await descriptionResponse.json();
- console.log('📄 描述数据:', descriptionData);
- if (descriptionData.success) {
- datasetDescription = descriptionData.description;
- // 将其存储在全局中供后续使用
- window.currentDatasetDescription = datasetDescription;
- console.log('✅ 数据集描述已存储:', datasetDescription);
- } else {
- console.log('⚠️ 描述响应success=false');
- }
- } else {
- console.log('❌ 数据集描述响应不正常:', descriptionResponse.status);
- try {
- const errorData = await descriptionResponse.json();
- console.log('❌ 错误详情:', errorData);
- } catch (e) {
- console.log('❌ 无法解析错误响应');
- }
- }
- // 更新统计信息
- document.getElementById('dataFieldsStats').textContent = `已加载 ${dataFields.length} 个数据字段`;
- // 使用数据集描述填充表格
- populateDataFieldsTable(datasetDescription);
- // 显示表格
- document.getElementById('tableContainer').style.display = 'block';
- } catch (error) {
- console.error('加载数据字段失败:', error);
- document.getElementById('dataFieldsStats').textContent = `错误: ${error.message}`;
- alert(`加载数据字段失败: ${error.message}`);
- }
- }
- // 使用筛选和排序填充数据字段表格
- function populateDataFieldsTable(datasetDescription) {
- console.log('📊 populateDataFieldsTable 被调用,描述:', datasetDescription);
- const tableBody = document.getElementById('dataFieldsTableBody');
- const highCoverageFilter = document.getElementById('filterHighCoverage')?.checked || false;
- const popularFilter = document.getElementById('filterPopular')?.checked || false;
- const matrixOnlyFilter = document.getElementById('filterMatrixOnly')?.checked || false;
- // 显示数据集描述(如果可用)
- if (datasetDescription) {
- console.log('🎯 显示传入的数据集描述');
- displayDatasetDescription(datasetDescription);
- } else if (window.currentDatasetDescription) {
- console.log('🎯 显示已存储的数据集描述');
- displayDatasetDescription(window.currentDatasetDescription);
- } else {
- console.log('⚠️ 无数据集描述可用');
- }
- // 应用筛选器
- filteredDataFields = dataFields.filter(field => {
- // 列特定筛选器
- // ID筛选器
- if (columnFilters.id && !field.id.toLowerCase().includes(columnFilters.id.toLowerCase())) {
- return false;
- }
- // 描述筛选器
- if (columnFilters.description && !field.description.toLowerCase().includes(columnFilters.description.toLowerCase())) {
- return false;
- }
- // 类型筛选器
- if (columnFilters.type && field.type !== columnFilters.type) {
- return false;
- }
- // 覆盖率范围筛选器
- if (columnFilters.coverage.min !== null && field.coverage * 100 < columnFilters.coverage.min) {
- return false;
- }
- if (columnFilters.coverage.max !== null && field.coverage * 100 > columnFilters.coverage.max) {
- return false;
- }
- // 用户数量筛选器
- if (columnFilters.userCount !== null && field.userCount < columnFilters.userCount) {
- return false;
- }
- // Alpha数量筛选器
- if (columnFilters.alphaCount !== null && field.alphaCount < columnFilters.alphaCount) {
- return false;
- }
- // 高覆盖率筛选器
- if (highCoverageFilter && field.coverage < 0.9) {
- return false;
- }
- // 流行度筛选器
- if (popularFilter && field.userCount < 1000) {
- return false;
- }
- // 矩阵类型筛选器
- if (matrixOnlyFilter && field.type !== 'MATRIX') {
- return false;
- }
- return true;
- });
- // 对筛选后的数据字段排序
- if (sortColumn) {
- filteredDataFields.sort((a, b) => {
- let aVal = a[sortColumn];
- let bVal = b[sortColumn];
- // 处理数值
- if (sortColumn === 'coverage' || sortColumn === 'userCount' || sortColumn === 'alphaCount') {
- aVal = Number(aVal);
- bVal = Number(bVal);
- } else {
- // 字符串比较
- aVal = String(aVal).toLowerCase();
- bVal = String(bVal).toLowerCase();
- }
- if (aVal < bVal) return sortOrder === 'asc' ? -1 : 1;
- if (aVal > bVal) return sortOrder === 'asc' ? 1 : -1;
- return 0;
- });
- }
- // 清空表格
- tableBody.innerHTML = '';
- if (filteredDataFields.length === 0) {
- tableBody.innerHTML = '<tr><td colspan="7" style="text-align: center; color: #666; padding: 40px;">未找到符合筛选条件的数据字段</td></tr>';
- updateDataFieldsStats();
- return;
- }
- // 创建表格行
- filteredDataFields.forEach(field => {
- const row = document.createElement('tr');
- row.dataset.fieldId = field.id;
- row.dataset.fieldDescription = field.description;
- if (selectedFields.has(field.id)) {
- row.classList.add('selected');
- }
- row.innerHTML = `
- <td>
- <input type="checkbox" class="field-checkbox" data-field-id="${field.id}" data-field-description="${field.description}" ${selectedFields.has(field.id) ? 'checked' : ''}>
- </td>
- <td><span class="data-field-id">${field.id}</span></td>
- <td><span class="data-field-description">${field.description}</span></td>
- <td><span class="data-field-type">${field.type || 'N/A'}</span></td>
- <td><span class="data-field-coverage">${field.coverage ? (field.coverage * 100).toFixed(1) + '%' : 'N/A'}</span></td>
- <td><span class="data-field-count">${field.userCount ? field.userCount.toLocaleString() : 'N/A'}</span></td>
- <td><span class="data-field-count">${field.alphaCount ? field.alphaCount.toLocaleString() : 'N/A'}</span></td>
- `;
- // 为行添加点击处理程序
- row.addEventListener('click', function(e) {
- if (e.target.type !== 'checkbox') {
- const checkbox = row.querySelector('.field-checkbox');
- checkbox.checked = !checkbox.checked;
- handleFieldSelection(checkbox);
- }
- });
- // 为复选框添加变更处理程序
- const checkbox = row.querySelector('.field-checkbox');
- checkbox.addEventListener('change', function() {
- handleFieldSelection(this);
- });
- tableBody.appendChild(row);
- });
- // 更新统计信息并填充类型筛选器
- updateDataFieldsStats();
- populateTypeFilter();
- updateSelectAllCheckbox();
- }
- // 处理字段选择
- function handleFieldSelection(checkbox) {
- const fieldId = checkbox.dataset.fieldId;
- const fieldDescription = checkbox.dataset.fieldDescription;
- const row = checkbox.closest('tr');
- if (checkbox.checked) {
- selectedFields.set(fieldId, fieldDescription);
- row.classList.add('selected');
- } else {
- selectedFields.delete(fieldId);
- row.classList.remove('selected');
- }
- updateSelectedFieldsDisplay();
- updateDataFieldsStats();
- updateSelectAllCheckbox();
- }
- // 更新选中字段的显示
- function updateSelectedFieldsDisplay() {
- const selectedFieldsList = document.getElementById('selectedFieldsList');
- const selectedFieldsSection = document.getElementById('selectedFieldsSection');
- if (selectedFields.size === 0) {
- selectedFieldsSection.style.display = 'none';
- return;
- }
- selectedFieldsSection.style.display = 'block';
- selectedFieldsList.innerHTML = '';
- selectedFields.forEach((description, fieldId) => {
- const fieldItem = document.createElement('div');
- fieldItem.className = 'selected-field-item';
- fieldItem.textContent = `${fieldId}: ${description}`;
- selectedFieldsList.appendChild(fieldItem);
- });
- }
- // 清除所有选择
- function clearSelection() {
- selectedFields.clear();
- // 取消选中所有复选框并移除选中类
- document.querySelectorAll('.field-checkbox').forEach(checkbox => {
- checkbox.checked = false;
- checkbox.closest('tr').classList.remove('selected');
- });
- updateSelectedFieldsDisplay();
- updateDataFieldsStats();
- updateSelectAllCheckbox();
- }
- // 使用Coze API处理选中的字段
- async function processSelectedFields() {
- if (selectedFields.size === 0) {
- alert('请至少选择一个字段');
- return;
- }
- // 显示加载覆盖层,包含Coze API特定消息
- const loadingOverlay = document.getElementById('loadingOverlay');
- const loadingContent = loadingOverlay.querySelector('.loading-content');
- loadingContent.innerHTML = `
- <h3>🚀 正在向Coze API发送请求...</h3>
- <p>正在通过Coze工作流处理 ${selectedFields.size} 个选中的字段</p>
- <p style="font-size: 14px; color: #666; margin-top: 10px;">
- 📡 正在连接到Coze API...<br>
- ⚙️ 正在运行工作流分析...<br>
- 📊 正在生成洞察...
- </p>
- `;
- loadingOverlay.style.display = 'flex';
- try {
- // 准备所需格式的数据 {"id":"description"}
- const selectedFieldsObject = {};
- selectedFields.forEach((description, fieldId) => {
- selectedFieldsObject[fieldId] = description;
- });
- // 获取Coze API配置
- const cozeApiToken = document.getElementById('cozeApiTokenInput').value;
- const workflowId = document.getElementById('workflowIdInput').value;
- // 验证输入
- if (!cozeApiToken) {
- alert('请输入Coze API令牌');
- document.getElementById('loadingOverlay').style.display = 'none';
- return;
- }
- if (!workflowId) {
- alert('请输入工作流ID');
- document.getElementById('loadingOverlay').style.display = 'none';
- return;
- }
- // 更新加载消息以显示API调用正在进行
- loadingContent.innerHTML = `
- <h3>📡 Coze API请求进行中...</h3>
- <p>工作流ID: ${workflowId}</p>
- <p>选中的字段: ${Object.keys(selectedFieldsObject).join(', ')}</p>
- <p style="font-size: 14px; color: #4caf50; margin-top: 10px;">
- ✅ API凭据已验证<br>
- 🔄 正在向Coze服务器发送请求...<br>
- ⏳ 请等待响应...
- </p>
- `;
- console.log('🚀 开始Coze API请求...');
- console.log('📋 选中的字段:', selectedFieldsObject);
- console.log('🔑 使用以以下结尾的API令牌:', cozeApiToken.slice(-10));
- console.log('⚙️ 工作流ID:', workflowId);
- // 调用处理端点
- const response = await fetch('/idea-house/api/process-fields', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- selected_fields: selectedFieldsObject,
- coze_api_token: cozeApiToken,
- workflow_id: workflowId,
- dataset_description: window.currentDatasetDescription || ''
- })
- });
- console.log('📡 收到服务器响应');
- const result = await response.json();
- if (!response.ok) {
- console.error('❌ Coze API请求失败:', result.error);
- throw new Error(result.error || '处理字段失败');
- }
- console.log('✅ Coze API请求成功!');
- console.log('📊 结果:', result);
- // 更新加载消息以显示成功
- loadingContent.innerHTML = `
- <h3>✅ 收到Coze API响应!</h3>
- <p style="color: #4caf50;">已成功通过工作流处理</p>
- <p style="font-size: 14px; margin-top: 10px;">
- 📥 收到来自Coze的响应<br>
- 🎉 正在格式化结果...
- </p>
- `;
- // 短暂延迟以显示成功消息
- await new Promise(resolve => setTimeout(resolve, 1000));
- // 显示结果
- displayResults(result);
- } catch (error) {
- console.error('💥 通过Coze API处理字段失败:', error);
- alert(`通过Coze API处理字段失败: ${error.message}`);
- } finally {
- // 隐藏加载覆盖层
- document.getElementById('loadingOverlay').style.display = 'none';
- // 为下次使用重置加载内容
- loadingContent.innerHTML = `
- <h3>处理中...</h3>
- <p>请等待我们分析您选中的字段...</p>
- `;
- }
- }
- // 以markdown格式显示结果
- function displayResults(result) {
- const resultsSection = document.getElementById('resultsSection');
- const resultsContent = document.getElementById('resultsContent');
- // 显示结果部分
- resultsSection.style.display = 'block';
- // 将结果格式化为markdown - 简化版本
- let markdown = '# 分析结果\n\n';
- // 添加选中字段部分
- markdown += '## 选中的字段\n\n';
- Object.entries(result.selected_fields).forEach(([fieldId, description]) => {
- markdown += `- **${fieldId}**: ${description}\n`;
- });
- markdown += '\n';
- // 添加输出部分 - 仅显示实际分析输出
- markdown += '## 分析输出\n\n';
- if (result.output) {
- // 如果输出已经是格式化文本,直接使用
- if (typeof result.output === 'string') {
- markdown += result.output;
- } else {
- // 如果是对象,尝试美观地显示
- markdown += '```json\n';
- markdown += JSON.stringify(result.output, null, 2);
- markdown += '\n```\n';
- }
- } else {
- markdown += '_无输出数据可用_';
- }
- // 将markdown渲染为HTML
- resultsContent.innerHTML = renderMarkdown(markdown);
- // 滚动到结果部分
- resultsSection.scrollIntoView({ behavior: 'smooth' });
- }
- // 辅助函数格式化markdown(可选增强功能)
- function renderMarkdown(markdown) {
- // 这是一个改进的markdown渲染器,能更好地处理列表
- let html = markdown;
- // 首先,转义HTML以防止XSS
- html = html.replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>');
- // 代码块(必须在行内代码之前)
- html = html.replace(/```([\s\S]*?)```/g, function(match, code) {
- return '<pre><code>' + code.trim() + '</code></pre>';
- });
- // 标题
- html = html.replace(/^#### (.*$)/gim, '<h4>$1</h4>');
- html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>');
- html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>');
- html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>');
- // 粗体(必须在斜体之前)
- html = html.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
- // 斜体
- html = html.replace(/\*([^*\n]+)\*/g, '<em>$1</em>');
- // 行内代码
- html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
- // 更仔细地处理列表
- // 为了更好的列表处理,分割成行
- const lines = html.split('\n');
- let inList = false;
- let processedLines = [];
- for (let i = 0; i < lines.length; i++) {
- let line = lines[i];
- // 检查行是否是列表项
- if (line.match(/^[\*\-\+] /)) {
- // 用适当的HTML替换列表标记
- line = line.replace(/^[\*\-\+] (.*)$/, '<li>$1</li>');
- // 如果不在列表中,开始一个列表
- if (!inList) {
- processedLines.push('<ul>');
- inList = true;
- }
- processedLines.push(line);
- } else if (line.match(/^\d+\. /)) {
- // 有序列表
- line = line.replace(/^\d+\. (.*)$/, '<li>$1</li>');
- // 如果不在列表中或前一个是无序列表,开始有序列表
- if (!inList || (i > 0 && lines[i-1].match(/^[\*\-\+] /))) {
- if (inList) processedLines.push('</ul>');
- processedLines.push('<ol>');
- inList = true;
- }
- processedLines.push(line);
- } else {
- // 不是列表项
- if (inList) {
- // 关闭列表
- if (i > 0 && lines[i-1].match(/^\d+\. /)) {
- processedLines.push('</ol>');
- } else {
- processedLines.push('</ul>');
- }
- inList = false;
- }
- processedLines.push(line);
- }
- }
- // 关闭任何剩余的列表
- if (inList) {
- if (lines[lines.length - 1].match(/^\d+\. /)) {
- processedLines.push('</ol>');
- } else {
- processedLines.push('</ul>');
- }
- }
- html = processedLines.join('\n');
- // 换行 - 将双换行符转换为段落
- html = html.replace(/\n\n/g, '</p><p>');
- html = '<p>' + html + '</p>';
- // 清理空段落
- html = html.replace(/<p>\s*<\/p>/g, '');
- html = html.replace(/<p>(<h[1-6]>)/g, '$1');
- html = html.replace(/(<\/h[1-6]>)<\/p>/g, '$1');
- html = html.replace(/<p>(<ul>|<ol>|<pre>)/g, '$1');
- html = html.replace(/(<\/ul>|<\/ol>|<\/pre>)<\/p>/g, '$1');
- // 段落内的单换行符
- html = html.replace(/\n/g, '<br>');
- return html;
- }
- // 将Coze配置保存到localStorage
- function saveCozeConfig() {
- const cozeApiToken = document.getElementById('cozeApiTokenInput').value;
- const workflowId = document.getElementById('workflowIdInput').value;
- // 保存到localStorage
- localStorage.setItem('coze_api_token', cozeApiToken);
- localStorage.setItem('coze_workflow_id', workflowId);
- // 显示成功消息
- const messageElement = document.getElementById('saveConfigMessage');
- messageElement.style.display = 'inline';
- // 3秒后隐藏消息
- setTimeout(() => {
- messageElement.style.display = 'none';
- }, 3000);
- }
- // 从localStorage加载保存的Coze配置
- function loadSavedCozeConfig() {
- const savedToken = localStorage.getItem('coze_api_token');
- const savedWorkflowId = localStorage.getItem('coze_workflow_id');
- if (savedToken) {
- document.getElementById('cozeApiTokenInput').value = savedToken;
- }
- if (savedWorkflowId) {
- document.getElementById('workflowIdInput').value = savedWorkflowId;
- }
- }
- // 清除Coze配置并重置为默认值
- function clearCozeConfig() {
- // 从localStorage移除
- localStorage.removeItem('coze_api_token');
- localStorage.removeItem('coze_workflow_id');
- // 重置为默认值
- document.getElementById('cozeApiTokenInput').value = 'pat_OCxUpnmL7hCvUxEWwcKL5XwUOdoiA3eWLzwY6L8W9sQVN1saJnoMrDNyhFhEn63l';
- document.getElementById('workflowIdInput').value = '7522912027267956786';
- // 显示消息
- const messageElement = document.getElementById('saveConfigMessage');
- messageElement.textContent = '配置已重置为默认值!';
- messageElement.style.color = '#ff9800';
- messageElement.style.display = 'inline';
- // 3秒后隐藏消息
- setTimeout(() => {
- messageElement.style.display = 'none';
- messageElement.textContent = '配置已保存!';
- messageElement.style.color = '#4caf50';
- }, 3000);
- }
- // 设置筛选事件监听器
- function setupFilterEventListeners() {
- // 快速筛选复选框
- const highCoverageFilter = document.getElementById('filterHighCoverage');
- const popularFilter = document.getElementById('filterPopular');
- const matrixOnlyFilter = document.getElementById('filterMatrixOnly');
- // 筛选操作按钮
- const selectAllBtn = document.getElementById('selectAllFiltered');
- const clearAllBtn = document.getElementById('clearAllSelected');
- const selectAllCheckbox = document.getElementById('selectAllCheckbox');
- // 设置快速筛选监听器
- if (highCoverageFilter) highCoverageFilter.onchange = () => populateDataFieldsTable();
- if (popularFilter) popularFilter.onchange = () => populateDataFieldsTable();
- if (matrixOnlyFilter) matrixOnlyFilter.onchange = () => populateDataFieldsTable();
- // 设置操作按钮监听器
- if (selectAllBtn) selectAllBtn.onclick = selectAllFilteredFields;
- if (clearAllBtn) clearAllBtn.onclick = clearAllSelectedFields;
- if (selectAllCheckbox) {
- selectAllCheckbox.onclick = (e) => {
- e.stopPropagation();
- if (selectAllCheckbox.checked) {
- selectAllFilteredFields();
- } else {
- clearAllFilteredFields();
- }
- };
- }
- // 列筛选监听器
- document.querySelectorAll('.column-filter').forEach(filter => {
- filter.addEventListener('input', (e) => {
- const column = e.target.dataset.column;
- const value = e.target.value;
- if (column === 'userCount' || column === 'alphaCount') {
- columnFilters[column] = value ? parseInt(value) : null;
- } else {
- columnFilters[column] = value;
- }
- // 添加/移除活动类
- if (value) {
- e.target.classList.add('active');
- } else {
- e.target.classList.remove('active');
- }
- populateDataFieldsTable();
- });
- });
- // 覆盖率范围筛选器
- document.querySelectorAll('.column-filter-min, .column-filter-max').forEach(filter => {
- filter.addEventListener('input', (e) => {
- const isMin = e.target.classList.contains('column-filter-min');
- const value = e.target.value;
- if (isMin) {
- columnFilters.coverage.min = value ? parseFloat(value) : null;
- } else {
- columnFilters.coverage.max = value ? parseFloat(value) : null;
- }
- // 添加/移除活动类
- const minInput = e.target.parentElement.querySelector('.column-filter-min');
- const maxInput = e.target.parentElement.querySelector('.column-filter-max');
- if (minInput.value || maxInput.value) {
- minInput.classList.add('active');
- maxInput.classList.add('active');
- } else {
- minInput.classList.remove('active');
- maxInput.classList.remove('active');
- }
- populateDataFieldsTable();
- });
- });
- // 排序按钮监听器
- document.querySelectorAll('.sort-btn').forEach(btn => {
- btn.addEventListener('click', (e) => {
- const column = e.target.dataset.column;
- // 重置所有其他排序按钮
- document.querySelectorAll('.sort-btn').forEach(b => {
- if (b !== e.target) {
- b.classList.remove('asc', 'desc');
- b.dataset.order = 'asc';
- }
- });
- // 切换排序顺序
- if (sortColumn === column) {
- sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
- } else {
- sortColumn = column;
- sortOrder = 'asc';
- }
- e.target.dataset.order = sortOrder;
- e.target.classList.remove('asc', 'desc');
- e.target.classList.add(sortOrder);
- populateDataFieldsTable();
- });
- });
- }
- // 更新数据字段统计信息
- function updateDataFieldsStats() {
- const dataFieldsCountEl = document.getElementById('dataFieldsCount');
- const filteredCountEl = document.getElementById('filteredCount');
- const selectedCountEl = document.getElementById('selectedFieldsCount');
- if (dataFieldsCountEl) dataFieldsCountEl.textContent = `已加载 ${dataFields.length} 个字段`;
- if (filteredCountEl) filteredCountEl.textContent = `${filteredDataFields.length} 个已筛选`;
- if (selectedCountEl) selectedCountEl.textContent = `${selectedFields.size} 个已选中`;
- }
- // 填充类型筛选下拉菜单
- function populateTypeFilter() {
- const typeFilter = document.getElementById('typeFilter');
- if (!typeFilter) return;
- // 从当前数据字段获取唯一类型
- const uniqueTypes = [...new Set(dataFields.map(field => field.type))].sort();
- // 清除现有选项,除了"所有类型"
- typeFilter.innerHTML = '<option value="">所有类型</option>';
- uniqueTypes.forEach(type => {
- const option = document.createElement('option');
- option.value = type;
- option.textContent = type;
- typeFilter.appendChild(option);
- });
- // 如果存在选中的值,恢复它
- if (columnFilters.type && uniqueTypes.includes(columnFilters.type)) {
- typeFilter.value = columnFilters.type;
- }
- }
- // 选中所有筛选后的字段
- function selectAllFilteredFields() {
- filteredDataFields.forEach(field => {
- selectedFields.set(field.id, field.description);
- const row = document.querySelector(`tr[data-field-id="${field.id}"]`);
- if (row) {
- const checkbox = row.querySelector('.field-checkbox');
- checkbox.checked = true;
- row.classList.add('selected');
- }
- });
- updateSelectedFieldsDisplay();
- updateDataFieldsStats();
- updateSelectAllCheckbox();
- }
- // 清除所有选中的字段
- function clearAllSelectedFields() {
- selectedFields.clear();
- // 更新所有复选框
- document.querySelectorAll('.field-checkbox').forEach(checkbox => {
- checkbox.checked = false;
- checkbox.closest('tr').classList.remove('selected');
- });
- updateSelectedFieldsDisplay();
- updateDataFieldsStats();
- updateSelectAllCheckbox();
- }
- // 仅清除筛选后的字段
- function clearAllFilteredFields() {
- filteredDataFields.forEach(field => {
- selectedFields.delete(field.id);
- const row = document.querySelector(`tr[data-field-id="${field.id}"]`);
- if (row) {
- const checkbox = row.querySelector('.field-checkbox');
- checkbox.checked = false;
- row.classList.remove('selected');
- }
- });
- updateSelectedFieldsDisplay();
- updateDataFieldsStats();
- updateSelectAllCheckbox();
- }
- // 更新全选复选框状态
- function updateSelectAllCheckbox() {
- const selectAllCheckbox = document.getElementById('selectAllCheckbox');
- if (!selectAllCheckbox) return;
- const allFilteredSelected = filteredDataFields.length > 0 &&
- filteredDataFields.every(field => selectedFields.has(field.id));
- selectAllCheckbox.checked = allFilteredSelected;
- selectAllCheckbox.indeterminate = !allFilteredSelected &&
- filteredDataFields.some(field => selectedFields.has(field.id));
- }
- // 显示数据集描述
- function displayDatasetDescription(description) {
- console.log('🎨 显示数据集描述:', description);
- // 检查数据集描述元素是否已存在
- let descriptionElement = document.getElementById('datasetDescription');
- if (!descriptionElement) {
- console.log('📌 创建新的数据集描述元素');
- // 如果元素不存在则创建它
- const tableContainer = document.getElementById('tableContainer');
- const dataFieldsControls = tableContainer.querySelector('.data-fields-controls');
- // 为数据集描述创建一个新的div
- descriptionElement = document.createElement('div');
- descriptionElement.id = 'datasetDescription';
- descriptionElement.className = 'dataset-description';
- descriptionElement.style.cssText = `
- padding: 15px;
- background: #e8f5e9;
- border: 1px solid #4caf50;
- border-radius: 4px;
- margin-bottom: 15px;
- font-size: 14px;
- line-height: 1.5;
- `;
- // 将其插入到控件之前
- tableContainer.insertBefore(descriptionElement, dataFieldsControls);
- console.log('✅ 数据集描述元素已创建并插入');
- } else {
- console.log('📌 使用现有的数据集描述元素');
- }
- // 更新内容
- descriptionElement.innerHTML = `
- <strong>数据集描述:</strong><br>
- ${description}
- `;
- console.log('✅ 数据集描述内容已更新');
- }
|