|
9 | 9 |
|
10 | 10 | import { useAppContext } from '../../../store/AppContext' |
11 | 11 | import { createAIService } from '../../../services/aiService' |
12 | | -import { PROMPT_TEMPLATES, extractJsonContent } from './CrosstabUtils' |
| 12 | +import { PROMPT_TEMPLATES, extractJsonContent, generateAxisCombinations, generateDimensionPath } from './CrosstabUtils' |
13 | 13 | import { AITask } from '../../../types' |
14 | 14 | import { v4 as uuidv4 } from 'uuid' |
15 | 15 | import StepFlow from './StepFlow' |
@@ -84,8 +84,123 @@ export default function CrosstabChat({ chatId }: CrosstabChatProps) { |
84 | 84 |
|
85 | 85 | // 生成该列的所有单元格数据 |
86 | 86 | try { |
87 | | - // 这里可以调用新的多维度单元格生成逻辑 |
88 | | - // 暂时显示成功消息 |
| 87 | + // 使用已经导入的函数 |
| 88 | + const verticalCombinations = generateAxisCombinations(chat.crosstabData.metadata.verticalDimensions) |
| 89 | + const aiService = createAIService(llmConfig) |
| 90 | + |
| 91 | + const updatedTableData = { ...chat.crosstabData.tableData } |
| 92 | + |
| 93 | + // 为该列的每个单元格生成数据 |
| 94 | + for (const vCombination of verticalCombinations) { |
| 95 | + const rowPath = generateDimensionPath(vCombination) |
| 96 | + const cellKey = `${columnPath}|${rowPath}` |
| 97 | + |
| 98 | + const taskId = uuidv4() |
| 99 | + const task: AITask = { |
| 100 | + id: taskId, |
| 101 | + requestId: aiService.id, |
| 102 | + type: 'crosstab_cell', |
| 103 | + status: 'running', |
| 104 | + title: '生成单元格数据', |
| 105 | + description: `生成单元格 ${columnPath} × ${rowPath} 的数据`, |
| 106 | + chatId, |
| 107 | + modelId: llmConfig.id, |
| 108 | + startTime: Date.now() |
| 109 | + } |
| 110 | + |
| 111 | + dispatch({ |
| 112 | + type: 'ADD_AI_TASK', |
| 113 | + payload: { task } |
| 114 | + }) |
| 115 | + |
| 116 | + try { |
| 117 | + const prompt = PROMPT_TEMPLATES.cell_values |
| 118 | + .replace('[METADATA_JSON]', JSON.stringify(chat.crosstabData.metadata, null, 2)) |
| 119 | + .replace('[HORIZONTAL_PATH]', columnPath) |
| 120 | + .replace('[VERTICAL_PATH]', rowPath) |
| 121 | + .replace('[VALUE_DIMENSIONS]', JSON.stringify(chat.crosstabData.metadata.valueDimensions, null, 2)) |
| 122 | + |
| 123 | + const response = await new Promise<string>((resolve, reject) => { |
| 124 | + aiService.sendMessage( |
| 125 | + [{ id: 'temp', role: 'user', content: prompt, timestamp: Date.now() }], |
| 126 | + { |
| 127 | + onChunk: () => {}, |
| 128 | + onComplete: (response) => resolve(response), |
| 129 | + onError: (error) => reject(error) |
| 130 | + } |
| 131 | + ) |
| 132 | + }) |
| 133 | + |
| 134 | + const jsonContent = extractJsonContent(response) |
| 135 | + const cellValues = JSON.parse(jsonContent) |
| 136 | + |
| 137 | + // 处理AI生成的数据格式 |
| 138 | + const processedCellValues: { [key: string]: string } = {} |
| 139 | + if (chat.crosstabData.metadata.valueDimensions.length > 0) { |
| 140 | + const valueDimensions = chat.crosstabData.metadata.valueDimensions |
| 141 | + |
| 142 | + const keys = Object.keys(cellValues) |
| 143 | + const hasGenericKeys = keys.some(key => key.match(/^value\d+$/)) |
| 144 | + |
| 145 | + if (hasGenericKeys) { |
| 146 | + valueDimensions.forEach((dimension, index) => { |
| 147 | + const genericKey = `value${index + 1}` |
| 148 | + if (cellValues[genericKey]) { |
| 149 | + processedCellValues[dimension.id] = cellValues[genericKey] |
| 150 | + } |
| 151 | + }) |
| 152 | + } else { |
| 153 | + valueDimensions.forEach(dimension => { |
| 154 | + if (cellValues[dimension.id]) { |
| 155 | + processedCellValues[dimension.id] = cellValues[dimension.id] |
| 156 | + } |
| 157 | + }) |
| 158 | + } |
| 159 | + |
| 160 | + if (Object.keys(processedCellValues).length === 0 && Object.keys(cellValues).length > 0) { |
| 161 | + const firstDimension = valueDimensions[0] |
| 162 | + const firstValue = Object.values(cellValues)[0] |
| 163 | + processedCellValues[firstDimension.id] = firstValue as string |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + updatedTableData[cellKey] = processedCellValues |
| 168 | + |
| 169 | + dispatch({ |
| 170 | + type: 'UPDATE_AI_TASK', |
| 171 | + payload: { |
| 172 | + taskId, |
| 173 | + updates: { |
| 174 | + status: 'completed', |
| 175 | + endTime: Date.now() |
| 176 | + } |
| 177 | + } |
| 178 | + }) |
| 179 | + } catch (error) { |
| 180 | + dispatch({ |
| 181 | + type: 'UPDATE_AI_TASK', |
| 182 | + payload: { |
| 183 | + taskId, |
| 184 | + updates: { |
| 185 | + status: 'failed', |
| 186 | + endTime: Date.now(), |
| 187 | + error: error instanceof Error ? error.message : 'Unknown error' |
| 188 | + } |
| 189 | + } |
| 190 | + }) |
| 191 | + console.error(`单元格 ${cellKey} 生成失败:`, error) |
| 192 | + } |
| 193 | + } |
| 194 | + |
| 195 | + // 批量更新表格数据 |
| 196 | + dispatch({ |
| 197 | + type: 'UPDATE_CROSSTAB_DATA', |
| 198 | + payload: { |
| 199 | + chatId, |
| 200 | + data: { tableData: updatedTableData } |
| 201 | + } |
| 202 | + }) |
| 203 | + |
89 | 204 | message.success(`列 "${columnPath}" 数据生成完成`) |
90 | 205 | } catch (error) { |
91 | 206 | console.error('列数据生成失败:', error) |
@@ -124,8 +239,123 @@ export default function CrosstabChat({ chatId }: CrosstabChatProps) { |
124 | 239 |
|
125 | 240 | // 生成该行的所有单元格数据 |
126 | 241 | try { |
127 | | - // 这里可以调用新的多维度单元格生成逻辑 |
128 | | - // 暂时显示成功消息 |
| 242 | + // 使用已经导入的函数 |
| 243 | + const horizontalCombinations = generateAxisCombinations(chat.crosstabData.metadata.horizontalDimensions) |
| 244 | + const aiService = createAIService(llmConfig) |
| 245 | + |
| 246 | + const updatedTableData = { ...chat.crosstabData.tableData } |
| 247 | + |
| 248 | + // 为该行的每个单元格生成数据 |
| 249 | + for (const hCombination of horizontalCombinations) { |
| 250 | + const columnPath = generateDimensionPath(hCombination) |
| 251 | + const cellKey = `${columnPath}|${rowPath}` |
| 252 | + |
| 253 | + const taskId = uuidv4() |
| 254 | + const task: AITask = { |
| 255 | + id: taskId, |
| 256 | + requestId: aiService.id, |
| 257 | + type: 'crosstab_cell', |
| 258 | + status: 'running', |
| 259 | + title: '生成单元格数据', |
| 260 | + description: `生成单元格 ${columnPath} × ${rowPath} 的数据`, |
| 261 | + chatId, |
| 262 | + modelId: llmConfig.id, |
| 263 | + startTime: Date.now() |
| 264 | + } |
| 265 | + |
| 266 | + dispatch({ |
| 267 | + type: 'ADD_AI_TASK', |
| 268 | + payload: { task } |
| 269 | + }) |
| 270 | + |
| 271 | + try { |
| 272 | + const prompt = PROMPT_TEMPLATES.cell_values |
| 273 | + .replace('[METADATA_JSON]', JSON.stringify(chat.crosstabData.metadata, null, 2)) |
| 274 | + .replace('[HORIZONTAL_PATH]', columnPath) |
| 275 | + .replace('[VERTICAL_PATH]', rowPath) |
| 276 | + .replace('[VALUE_DIMENSIONS]', JSON.stringify(chat.crosstabData.metadata.valueDimensions, null, 2)) |
| 277 | + |
| 278 | + const response = await new Promise<string>((resolve, reject) => { |
| 279 | + aiService.sendMessage( |
| 280 | + [{ id: 'temp', role: 'user', content: prompt, timestamp: Date.now() }], |
| 281 | + { |
| 282 | + onChunk: () => {}, |
| 283 | + onComplete: (response) => resolve(response), |
| 284 | + onError: (error) => reject(error) |
| 285 | + } |
| 286 | + ) |
| 287 | + }) |
| 288 | + |
| 289 | + const jsonContent = extractJsonContent(response) |
| 290 | + const cellValues = JSON.parse(jsonContent) |
| 291 | + |
| 292 | + // 处理AI生成的数据格式 |
| 293 | + const processedCellValues: { [key: string]: string } = {} |
| 294 | + if (chat.crosstabData.metadata.valueDimensions.length > 0) { |
| 295 | + const valueDimensions = chat.crosstabData.metadata.valueDimensions |
| 296 | + |
| 297 | + const keys = Object.keys(cellValues) |
| 298 | + const hasGenericKeys = keys.some(key => key.match(/^value\d+$/)) |
| 299 | + |
| 300 | + if (hasGenericKeys) { |
| 301 | + valueDimensions.forEach((dimension, index) => { |
| 302 | + const genericKey = `value${index + 1}` |
| 303 | + if (cellValues[genericKey]) { |
| 304 | + processedCellValues[dimension.id] = cellValues[genericKey] |
| 305 | + } |
| 306 | + }) |
| 307 | + } else { |
| 308 | + valueDimensions.forEach(dimension => { |
| 309 | + if (cellValues[dimension.id]) { |
| 310 | + processedCellValues[dimension.id] = cellValues[dimension.id] |
| 311 | + } |
| 312 | + }) |
| 313 | + } |
| 314 | + |
| 315 | + if (Object.keys(processedCellValues).length === 0 && Object.keys(cellValues).length > 0) { |
| 316 | + const firstDimension = valueDimensions[0] |
| 317 | + const firstValue = Object.values(cellValues)[0] |
| 318 | + processedCellValues[firstDimension.id] = firstValue as string |
| 319 | + } |
| 320 | + } |
| 321 | + |
| 322 | + updatedTableData[cellKey] = processedCellValues |
| 323 | + |
| 324 | + dispatch({ |
| 325 | + type: 'UPDATE_AI_TASK', |
| 326 | + payload: { |
| 327 | + taskId, |
| 328 | + updates: { |
| 329 | + status: 'completed', |
| 330 | + endTime: Date.now() |
| 331 | + } |
| 332 | + } |
| 333 | + }) |
| 334 | + } catch (error) { |
| 335 | + dispatch({ |
| 336 | + type: 'UPDATE_AI_TASK', |
| 337 | + payload: { |
| 338 | + taskId, |
| 339 | + updates: { |
| 340 | + status: 'failed', |
| 341 | + endTime: Date.now(), |
| 342 | + error: error instanceof Error ? error.message : 'Unknown error' |
| 343 | + } |
| 344 | + } |
| 345 | + }) |
| 346 | + console.error(`单元格 ${cellKey} 生成失败:`, error) |
| 347 | + } |
| 348 | + } |
| 349 | + |
| 350 | + // 批量更新表格数据 |
| 351 | + dispatch({ |
| 352 | + type: 'UPDATE_CROSSTAB_DATA', |
| 353 | + payload: { |
| 354 | + chatId, |
| 355 | + data: { tableData: updatedTableData } |
| 356 | + } |
| 357 | + }) |
| 358 | + |
129 | 359 | message.success(`行 "${rowPath}" 数据生成完成`) |
130 | 360 | } catch (error) { |
131 | 361 | console.error('行数据生成失败:', error) |
|
0 commit comments