script.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. document.addEventListener('DOMContentLoaded', function () {
  2. // 获取DOM元素 - 计算器模块
  3. const calculateBtn = document.getElementById('calculate-btn');
  4. const solutionsContainer = document.getElementById('solutions');
  5. const statsContainer = document.getElementById('stats');
  6. // 获取DOM元素 - 一星数据模块
  7. const flag1MinInput = document.getElementById('flag1-min');
  8. const flag1SearchBtn = document.getElementById('flag1-search-btn');
  9. const flag1Table = document.getElementById('flag1-table');
  10. // 获取DOM元素 - 二星数据模块
  11. const flag2MinInput = document.getElementById('flag2-min');
  12. const flag2SearchBtn = document.getElementById('flag2-search-btn');
  13. const flag2Table = document.getElementById('flag2-table');
  14. // 获取DOM元素 - 历史记录模块
  15. const historyTypeSelect = document.getElementById('history-type');
  16. const historyStartDateInput = document.getElementById('history-start-date');
  17. const historyEndDateInput = document.getElementById('history-end-date');
  18. const historySearchBtn = document.getElementById('history-search-btn');
  19. const historyContainer = document.getElementById('history-container');
  20. const historyLoadMoreBtn = document.getElementById('history-load-more');
  21. // 获取DOM元素 - 出题模块
  22. const problemContent = document.getElementById('problem-content');
  23. const problemAnswer = document.getElementById('problem-answer');
  24. const showAnswerBtn = document.getElementById('show-answer-btn');
  25. // 数字输入框
  26. const num1Input = document.getElementById('num1');
  27. const num2Input = document.getElementById('num2');
  28. const num3Input = document.getElementById('num3');
  29. const num4Input = document.getElementById('num4');
  30. // 限制输入范围为1-13
  31. [num1Input, num2Input, num3Input, num4Input].forEach(input => {
  32. input.addEventListener('input', function () {
  33. const value = parseInt(this.value);
  34. if (value < 1) this.value = 1;
  35. if (value > 13) this.value = 13;
  36. });
  37. });
  38. // 存储当前解法和问题数据
  39. let currentSolutions = [];
  40. let currentProblem = null;
  41. // 获取问题类型选择框和出题按钮
  42. const problemTypeSelect = document.getElementById('problem-type-select');
  43. const generateProblemBtn = document.getElementById('generate-problem-btn');
  44. // 为出题按钮添加点击事件
  45. generateProblemBtn.addEventListener('click', function () {
  46. const selectedType = problemTypeSelect.value;
  47. if (selectedType) {
  48. // 根据选择的类型生成题目
  49. generateProblem(selectedType);
  50. } else {
  51. // 如果没有选择类型,提示用户
  52. problemContent.innerHTML = '<p class="error">请先选择题目类型</p>';
  53. }
  54. });
  55. // 为显示答案按钮添加点击事件
  56. showAnswerBtn.addEventListener('click', function () {
  57. if (currentProblem && currentProblem.answers) {
  58. console.log('currentProblem:', currentProblem.answers)
  59. if (problemAnswer.style.display === 'block') {
  60. problemAnswer.style.display = 'none';
  61. showAnswerBtn.textContent = '显示答案';
  62. } else {
  63. problemAnswer.style.display = 'block';
  64. renderProblemAnswers(currentProblem.answers);
  65. showAnswerBtn.textContent = '隐藏答案';
  66. }
  67. }
  68. });
  69. // 为计算按钮添加点击事件
  70. calculateBtn.addEventListener('click', fetchSolutions);
  71. // 为历史记录查询按钮添加点击事件
  72. historySearchBtn.addEventListener('click', ()=>{fetchHistory(false)});
  73. // 根据题型生成题目
  74. let answerTimer = null;
  75. let timerInterval = null;
  76. let timerSeconds = 0;
  77. let timerDisplay;
  78. async function generateProblem(type) {
  79. if (answerTimer) clearTimeout(answerTimer);
  80. if (timerInterval) clearInterval(timerInterval);
  81. // 重置问题和答案区域
  82. problemContent.innerHTML = '<p class="placeholder">正在生成题目,请稍候...</p>';
  83. problemAnswer.innerHTML = '';
  84. problemAnswer.style.display = 'none';
  85. showAnswerBtn.style.display = 'none';
  86. currentProblem = null;
  87. // 重置计时器
  88. timerSeconds = 0;
  89. try {
  90. // 调用API获取问题
  91. const response = await fetch(`/api/questions?t=${type}`);
  92. const data = await response.json();
  93. if (response.ok && data.question) {
  94. // 保存当前问题数据
  95. currentProblem = data;
  96. // 显示问题内容
  97. problemContent.innerHTML = `<div class="problem-text">
  98. <div class="timer-container">
  99. <span id="timer-display" class="timer-display">00:00</span>
  100. </div>
  101. ${data.question}</div>`;
  102. // 如果有数字,显示数字
  103. if (data.numbers) {
  104. const numbersHTML = `
  105. <div class="problem-numbers">
  106. ${data.numbers.map(num => `<span class="problem-number">${num === null ? '?' : num}</span>`).join('')}
  107. </div>
  108. `;
  109. problemContent.innerHTML += numbersHTML;
  110. }
  111. timerDisplay = document.getElementById('timer-display');
  112. // 开始计时
  113. startTimer();
  114. // 显示答案按钮
  115. answerTimer = setTimeout(() => {
  116. showAnswerBtn.textContent = '显示答案';
  117. showAnswerBtn.style.display = 'block';
  118. }, 10 * 1000);
  119. } else {
  120. problemContent.innerHTML = `<p class="error">${data.detail || '获取题目失败'}</p>`;
  121. }
  122. } catch (error) {
  123. console.error('Error:', error);
  124. problemContent.innerHTML = '<p class="error">请求失败,请检查网络连接</p>';
  125. }
  126. // 开始计时器
  127. function startTimer() {
  128. // 清除之前的计时器
  129. if (timerInterval) {
  130. clearInterval(timerInterval);
  131. }
  132. // 重置计时
  133. timerSeconds = 0;
  134. updateTimerDisplay();
  135. // 启动新的计时器
  136. timerInterval = setInterval(() => {
  137. timerSeconds++;
  138. if (timerSeconds > 130) {
  139. clearInterval(timerInterval);
  140. }
  141. updateTimerDisplay();
  142. }, 1000);
  143. }
  144. // 更新计时器显示
  145. function updateTimerDisplay() {
  146. if (timerDisplay) {
  147. if (timerSeconds >= 120) {
  148. timerDisplay.textContent = "时间到";
  149. timerDisplay.classList.add('time-up');
  150. } else {
  151. const minutes = Math.floor(timerSeconds / 60);
  152. const seconds = timerSeconds % 60;
  153. timerDisplay.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
  154. timerDisplay.classList.remove('time-up');
  155. }
  156. }
  157. }
  158. }
  159. // 渲染问题答案
  160. function renderProblemAnswers(answers) {
  161. if (!answers || answers.length === 0) {
  162. problemAnswer.innerHTML = '<p class="placeholder">没有找到答案</p>';
  163. return;
  164. }
  165. // 根据答案类型渲染不同的内容
  166. if (Array.isArray(answers)) {
  167. // 如果是数组,渲染为列表
  168. const answersHTML = answers.map(answer => {
  169. if (typeof answer === 'object' && answer.expression) {
  170. // 如果是解法对象
  171. return `
  172. <div class="solution-item flag-${answer.flag || 0}">
  173. <div class="solution-expression">${answer.expression}</div>
  174. <div class="solution-flag flag-${answer.flag || 0}">
  175. ${answer.flag === 1 ? '★' : answer.flag === 2 ? '★★' : ''}
  176. </div>
  177. </div>
  178. `;
  179. } else {
  180. // 如果是普通文本
  181. return `<div class="answer-item">${answer}</div>`;
  182. }
  183. }).join('');
  184. problemAnswer.innerHTML = `
  185. <h3>答案</h3>
  186. <div class="answers-container">
  187. ${answersHTML}
  188. </div>
  189. `;
  190. } else if (typeof answers === 'object') {
  191. // 如果是单个对象
  192. const answerKeys = Object.keys(answers);
  193. const answersHTML = answerKeys.map(key => {
  194. return `
  195. <div class="answer-group">
  196. <div class="answer-key">${key}:</div>
  197. <div class="answer-value">${answers[key]}</div>
  198. </div>
  199. `;
  200. }).join('');
  201. problemAnswer.innerHTML = `
  202. <h3>答案</h3>
  203. <div class="answers-container">
  204. ${answersHTML}
  205. </div>
  206. `;
  207. } else {
  208. // 如果是单个值
  209. problemAnswer.innerHTML = `
  210. <h3>答案</h3>
  211. <div class="answers-container">
  212. <div class="answer-item">${answers}</div>
  213. </div>
  214. `;
  215. }
  216. }
  217. // 获取解法
  218. async function fetchSolutions() {
  219. // 获取输入值
  220. const num1 = parseInt(num1Input.value) || 1;
  221. const num2 = parseInt(num2Input.value) || 1;
  222. const num3 = parseInt(num3Input.value) || 1;
  223. const num4 = parseInt(num4Input.value) || 1;
  224. // 显示加载状态
  225. solutionsContainer.innerHTML = '<p class="placeholder">正在计算解法,请稍候...</p>';
  226. statsContainer.textContent = '';
  227. try {
  228. // 调用API
  229. const response = await fetch(`/api/solutions?num1=${num1}&num2=${num2}&num3=${num3}&num4=${num4}`);
  230. const data = await response.json();
  231. if (response.ok) {
  232. // 保存解法
  233. currentSolutions = data.solutions || [];
  234. // 显示统计信息
  235. if (currentSolutions.length > 0) {
  236. statsContainer.textContent = `共 ${data.count} 种解法(一星: ${data.flag1_count}, 二星: ${data.flag2_count})`;
  237. } else {
  238. statsContainer.textContent = '没有找到任何解法';
  239. }
  240. // 渲染解法
  241. renderSolutions();
  242. } else {
  243. // 显示错误信息
  244. solutionsContainer.innerHTML = `<p class="error">${data.detail || '没有找到解法'}</p>`;
  245. statsContainer.textContent = '';
  246. }
  247. } catch (error) {
  248. console.error('Error:', error);
  249. solutionsContainer.innerHTML = '<p class="error">请求失败,请检查网络连接</p>';
  250. statsContainer.textContent = '';
  251. }
  252. }
  253. // 渲染解法
  254. function renderSolutions() {
  255. // 如果没有解法
  256. if (!currentSolutions || currentSolutions.length === 0) {
  257. solutionsContainer.innerHTML = '<p class="placeholder">没有找到匹配的解法,请尝试其他数字组合</p>';
  258. return;
  259. }
  260. // 直接使用所有解法
  261. const filteredSolutions = currentSolutions;
  262. // 渲染解法列表
  263. const solutionsHTML = filteredSolutions.map(solution => {
  264. return `
  265. <div class="solution-item flag-${solution.flag}">
  266. <div class="solution-expression">${solution.expression}</div>
  267. <div class="solution-flag flag-${solution.flag}">
  268. ${solution.flag === 1 ? '★' : solution.flag === 2 ? '★★' : ''}
  269. </div>
  270. </div>
  271. `;
  272. }).join('');
  273. solutionsContainer.innerHTML = solutionsHTML;
  274. }
  275. // 为一星数据查询按钮添加点击事件
  276. flag1SearchBtn.addEventListener('click', async function () {
  277. const min = flag1MinInput.value || 1;
  278. await fetchFlagData(1, min, flag1Table);
  279. });
  280. // 为二星数据查询按钮添加点击事件
  281. flag2SearchBtn.addEventListener('click', async function () {
  282. const min = flag2MinInput.value || 1;
  283. await fetchFlagData(2, min, flag2Table);
  284. });
  285. // 获取一星/二星数据
  286. async function fetchFlagData(flag, min, tableElement) {
  287. // 显示加载状态
  288. tableElement.querySelector('tbody').innerHTML = '<tr><td colspan="2" class="placeholder">正在加载数据,请稍候...</td></tr>';
  289. try {
  290. // 调用API获取数据
  291. const response = await fetch(`/api/flag?flag=${flag}&min_num=${min}&max_num=`);
  292. const data = await response.json();
  293. if (response.ok && data.length > 0) {
  294. // 处理数据并按数字组合分组
  295. const groupedData = {};
  296. data.forEach(item => {
  297. // 创建数字组合的键
  298. const numbersKey = [item.n1, item.n2, item.n3, item.n4].sort((a, b) => a - b).join(',');
  299. // 如果这个数字组合不存在,创建一个新数组
  300. if (!groupedData[numbersKey]) {
  301. groupedData[numbersKey] = [];
  302. }
  303. // 添加解法到对应的数字组合
  304. item.s.forEach(solution => {
  305. groupedData[numbersKey].push({
  306. expression: solution.c,
  307. flag: solution.f
  308. });
  309. });
  310. });
  311. console.log(groupedData);
  312. // 渲染表格
  313. renderFlagTable(groupedData, tableElement, flag);
  314. } else {
  315. // 显示无数据信息
  316. tableElement.querySelector('tbody').innerHTML = '<tr><td colspan="2" class="placeholder">没有找到匹配的数据</td></tr>';
  317. }
  318. } catch (error) {
  319. console.error('Error:', error);
  320. tableElement.querySelector('tbody').innerHTML = '<tr><td colspan="2" class="error">请求失败,请检查网络连接</td></tr>';
  321. }
  322. }
  323. // 渲染一星/二星数据表格
  324. function renderFlagTable(groupedData, tableElement, currentFlag) {
  325. const tbody = tableElement.querySelector('tbody');
  326. tbody.innerHTML = '';
  327. // 遍历分组数据
  328. Object.entries(groupedData).forEach(([numbersKey, solutions]) => {
  329. const tr = document.createElement('tr');
  330. // 数字单元格
  331. const tdNumbers = document.createElement('td');
  332. tdNumbers.className = 'number-cell';
  333. tdNumbers.textContent = numbersKey;
  334. tr.appendChild(tdNumbers);
  335. // 表达式单元格
  336. const tdExpressions = document.createElement('td');
  337. tdExpressions.className = 'expressions-cell';
  338. const container = document.createElement('div');
  339. container.className = 'expression-container hidden';
  340. // 创建显示按钮
  341. const toggleBtn = document.createElement('button');
  342. toggleBtn.className = 'toggle-btn';
  343. toggleBtn.textContent = '查看答案';
  344. // 添加每个表达式
  345. solutions.forEach(solution => {
  346. // const expressionDiv = document.createElement('div');
  347. // expressionDiv.className = `expression-item flag-${solution.flag}`;
  348. // expressionDiv.textContent = solution.expression;
  349. const expressionDiv = document.createElement('div');
  350. expressionDiv.className = `expression-item flag-${solution.flag} `;
  351. expressionDiv.textContent = solution.expression;
  352. container.appendChild(expressionDiv);
  353. });
  354. tdExpressions.appendChild(container);
  355. // 按钮点击事件
  356. toggleBtn.addEventListener('click', () => {
  357. container.classList.remove('hidden');
  358. toggleBtn.remove();
  359. });
  360. tdExpressions.appendChild(toggleBtn);
  361. tr.appendChild(tdExpressions);
  362. tbody.appendChild(tr);
  363. });
  364. // 如果没有数据
  365. if (tbody.children.length === 0) {
  366. tbody.innerHTML = '<tr><td colspan="2" class="placeholder">没有找到匹配的数据</td></tr>';
  367. }
  368. }
  369. // 添加模块切换事件监听
  370. const moduleSelect = document.getElementById('module-select');
  371. moduleSelect.addEventListener('change', function () {
  372. document.querySelectorAll('.module-container').forEach(module => {
  373. module.style.display = 'none';
  374. });
  375. document.querySelector(`.module-` + this.value).style.display = 'block';
  376. // 切换到计算器模块时重置输入框
  377. if (this.value === '2') {
  378. [num1Input, num2Input, num3Input, num4Input].forEach(input => input.value = 1);
  379. solutionsContainer.innerHTML = '<p class="placeholder">请输入4个数字并点击"计算解法"按钮</p>';
  380. }
  381. // 切换到一星数据模块时加载数据
  382. if (this.value === '3' && flag1Table.querySelector('tbody tr td.placeholder')) {
  383. fetchFlagData(1, flag1MinInput.value, flag1Table);
  384. }
  385. // 切换到二星数据模块时加载数据
  386. if (this.value === '4' && flag2Table.querySelector('tbody tr td.placeholder')) {
  387. fetchFlagData(2, flag2MinInput.value, flag2Table);
  388. }
  389. // 切换到历史记录模块时加载数据
  390. if (this.value === '5' && historyContainer) {
  391. fetchHistory(false);
  392. }
  393. });
  394. // 初始化默认显示模块
  395. document.querySelectorAll('.module-container').forEach(module => {
  396. module.style.display = module.classList.contains('module-1') ? 'block' : 'none';
  397. });
  398. // 历史记录相关变量
  399. let currentHistoryPage = 1;
  400. let isLoadingHistory = false;
  401. let hasMoreHistory = true;
  402. // 获取历史记录数据
  403. async function fetchHistory(loadMore = false) {
  404. if (isLoadingHistory) return;
  405. isLoadingHistory = true;
  406. // 如果不是加载更多,则重置状态
  407. if (!loadMore) {
  408. currentHistoryPage = 1;
  409. hasMoreHistory = true;
  410. historyContainer.innerHTML = '<div class="placeholder">正在加载历史记录...</div>';
  411. historyLoadMoreBtn.style.display = 'none';
  412. } else {
  413. // 显示加载中状态
  414. historyLoadMoreBtn.textContent = '加载中...';
  415. historyLoadMoreBtn.disabled = true;
  416. }
  417. try {
  418. // 构建查询参数
  419. const params = new URLSearchParams();
  420. if (historyTypeSelect.value) {
  421. params.append('game_type', historyTypeSelect.value);
  422. }
  423. if (historyStartDateInput.value) {
  424. params.append('start_date', historyStartDateInput.value);
  425. }
  426. if (historyEndDateInput.value) {
  427. params.append('end_date', historyEndDateInput.value);
  428. }
  429. params.append('page', currentHistoryPage.toString());
  430. params.append('page_size', '10');
  431. // 调用API获取历史记录
  432. const response = await fetch(`/api/history?${params.toString()}`);
  433. const data = await response.json();
  434. if (response.ok && data.history) {
  435. renderHistoryData(data.history, loadMore);
  436. // 更新分页状态
  437. hasMoreHistory = currentHistoryPage < data.total_pages;
  438. historyLoadMoreBtn.style.display = hasMoreHistory ? 'block' : 'none';
  439. // 如果成功加载,增加页码
  440. currentHistoryPage++;
  441. } else {
  442. throw new Error(data.detail || '获取历史记录失败');
  443. }
  444. } catch (error) {
  445. if (!loadMore) {
  446. historyContainer.innerHTML = `<div class="error">${error.message}</div>`;
  447. } else {
  448. // 显示加载失败消息
  449. alert('加载更多历史记录失败: ' + error.message);
  450. }
  451. } finally {
  452. isLoadingHistory = false;
  453. if (loadMore) {
  454. historyLoadMoreBtn.textContent = '加载更多';
  455. historyLoadMoreBtn.disabled = false;
  456. }
  457. }
  458. }
  459. // 渲染历史记录数据
  460. function renderHistoryData(historyItems, append = false) {
  461. if (!historyItems || historyItems.length === 0) {
  462. if (!append) {
  463. historyContainer.innerHTML = '<div class="placeholder">没有找到历史记录</div>';
  464. }
  465. return;
  466. }
  467. // 构建卡片内容
  468. let cardsHTML = '';
  469. historyItems.forEach(item => {
  470. // 格式化日期时间
  471. const date = new Date(item.created_at);
  472. const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
  473. // 获取操作类型的中文名称
  474. const type_names = {
  475. "A": "推理未知数",
  476. "B": "一题多解1",
  477. "C": "一题多解2",
  478. "D": "一星题目",
  479. "E": "二星题目"
  480. };
  481. let typeText = type_names[item.game_type] || item.game_type || '未知类型';
  482. let typeClass = `type-${(item.game_type || '').toLowerCase()}`;
  483. if (!type_names[item.game_type]) {
  484. typeClass = 'type-unknown';
  485. }
  486. // 解析答案数据
  487. let answersContent = '';
  488. let answers = null;
  489. try {
  490. // 尝试解析JSON字符串
  491. if (item.answers && typeof item.answers === 'string') {
  492. answers = JSON.parse(item.answers);
  493. } else if (item.answers) {
  494. answers = item.answers;
  495. }
  496. } catch (e) {
  497. // 如果解析失败,直接使用原始字符串
  498. answers = item.answers;
  499. }
  500. // 构建卡片HTML
  501. cardsHTML += `
  502. <div class="history-card ${typeClass}">
  503. <div class="history-card-header">
  504. <span class="history-card-type">${typeText}</span>
  505. <button class="secondary-btn show-history-answer-btn">显示答案</button>
  506. <span class="history-card-time">${formattedDate}</span>
  507. </div>
  508. <div class="history-card-content">
  509. <div class="problem-text">${item.question || ''}</div>
  510. ${item.numbers ? `<div class="problem-numbers">
  511. ${item.numbers.split(',').map(num => `<span class="problem-number">${num.trim()==='None'?"?":num.trim()}</span>`).join('')}
  512. </div>` : ''}
  513. </div>
  514. <div class="history-card-answers" style="display: none;"></div>
  515. </div>
  516. `;
  517. });
  518. // 如果是追加模式,则添加到现有内容后面
  519. if (append) {
  520. historyContainer.innerHTML += cardsHTML;
  521. } else {
  522. historyContainer.innerHTML = cardsHTML;
  523. }
  524. // 为所有显示答案按钮添加点击事件
  525. document.querySelectorAll('.show-history-answer-btn').forEach((btn, index) => {
  526. btn.addEventListener('click', function () {
  527. const card = this.closest('.history-card');
  528. const answersContainer = card.querySelector('.history-card-answers');
  529. if (answersContainer.style.display === 'block') {
  530. // 隐藏答案
  531. answersContainer.style.display = 'none';
  532. this.textContent = '显示答案';
  533. } else {
  534. // 显示答案
  535. answersContainer.style.display = 'block';
  536. this.textContent = '隐藏答案';
  537. // 如果答案容器为空,则渲染答案内容
  538. if (!answersContainer.innerHTML.trim()) {
  539. const historyItem = historyItems[index];
  540. let answers = null;
  541. try {
  542. // 尝试解析JSON字符串
  543. if (historyItem.answers && typeof historyItem.answers === 'string') {
  544. const jsonString = historyItem.answers.replace(/'/g, '"');
  545. answers = JSON.parse(jsonString);
  546. } else if (historyItem.answers) {
  547. answers = historyItem.answers;
  548. }
  549. } catch (e) {
  550. console.error('解析答案失败:', e);
  551. answers = historyItem.answers;
  552. }
  553. renderHistoryAnswers(answers, answersContainer);
  554. }
  555. }
  556. });
  557. });
  558. }
  559. function renderHistoryAnswers(answers, container) {
  560. if (!answers || answers.length === 0) {
  561. container.innerHTML = '<p class="placeholder">没有找到答案</p>';
  562. return;
  563. }
  564. // 根据答案类型渲染不同的内容
  565. if (Array.isArray(answers)) {
  566. // 如果是数组,渲染为列表
  567. const answersHTML = answers.map(answer => {
  568. if (typeof answer === 'object' && answer.expression) {
  569. // 如果是解法对象
  570. return `
  571. <div class="solution-item flag-${answer.flag || 0}">
  572. <div class="solution-expression">${answer.expression}</div>
  573. <div class="solution-flag flag-${answer.flag || 0}">
  574. ${answer.flag === 1 ? '★' : answer.flag === 2 ? '★★' : ''}
  575. </div>
  576. </div>
  577. `;
  578. } else {
  579. // 如果是普通文本
  580. return `<div class="answer-item">${answer}</div>`;
  581. }
  582. }).join('');
  583. container.innerHTML = `
  584. <div class="answers-container">
  585. ${answersHTML}
  586. </div>
  587. `;
  588. } else if (typeof answers === 'object') {
  589. // 如果是单个对象
  590. const answerKeys = Object.keys(answers);
  591. const answersHTML = answerKeys.map(key => {
  592. return `
  593. <div class="answer-group">
  594. <div class="answer-key">${key}:</div>
  595. <div class="answer-value">${answers[key]}</div>
  596. </div>
  597. `;
  598. }).join('');
  599. container.innerHTML = `
  600. <h3>答案</h3>
  601. <div class="answers-container">
  602. ${answersHTML}
  603. </div>
  604. `;
  605. } else {
  606. // 如果是单个值
  607. container.innerHTML = `
  608. <h3>答案</h3>
  609. <div class="answers-container">
  610. <div class="answer-item">${answers}</div>
  611. </div>
  612. `;
  613. }
  614. }
  615. // 为加载更多按钮添加事件监听
  616. if (historyLoadMoreBtn) {
  617. historyLoadMoreBtn.addEventListener('click', () => {
  618. if (!isLoadingHistory && hasMoreHistory) {
  619. fetchHistory(true);
  620. }
  621. });
  622. }
  623. // 设置日期输入框的默认值为当前日期
  624. const today = new Date();
  625. historyStartDateInput.value = today.toISOString().split('T')[0];
  626. historyEndDateInput.value = today.toISOString().split('T')[0];
  627. });