diff --git a/src/components/ChessboardDisplay.vue b/src/components/ChessboardDisplay.vue index 68ad2c7..450ee47 100644 --- a/src/components/ChessboardDisplay.vue +++ b/src/components/ChessboardDisplay.vue @@ -20,12 +20,8 @@ drawPiece, } from '../utils/drawUtils'; import { useChessStore } from '../stores/chess'; - import { storeToRefs } from 'pinia'; - // 解构响应式状态和直接引用方法 const chessStore = useChessStore(); - const { fenCode, bestMove, error } = storeToRefs(chessStore); - const { setFenCode } = chessStore; // 移除 setError const canvasRef = ref(null); const board = ref<(PieceData | null)[][]>([]); @@ -52,13 +48,13 @@ fontLoaded.value = true; }) .catch((err) => { - error.value = `加载字体失败: ${err.message}`; + chessStore.setError(`加载字体失败: ${err.message}`); }); try { - board.value = parseFEN(fenCode.value); + board.value = parseFEN(chessStore.fenCode); } catch (err) { - error.value = `解析 FEN 码失败: ${(err as Error).message}`; + chessStore.setError(`解析 FEN 码失败: ${(err as Error).message}`); } const handleResize = () => { @@ -71,18 +67,18 @@ canvasRef.value?.addEventListener('click', handleCanvasClick); watch( - () => fenCode.value, // 监听 ref 的值变化 + () => chessStore.fenCode, (newFen) => { try { board.value = parseFEN(newFen); } catch (err) { - error.value = `解析 FEN 码失败: ${(err as Error).message}`; + chessStore.setError(`解析 FEN 码失败: ${(err as Error).message}`); } } ); watch( - [board, () => bestMove.value, scale, fontLoaded, selectedPosition], + [board, () => chessStore.bestMove, scale, fontLoaded, selectedPosition], () => { nextTick(() => { if (canvasRef.value) { @@ -121,11 +117,11 @@ const move = `${fromSquare}${toSquare}`; try { - const newFen = updateFEN(fenCode.value, move); - setFenCode(newFen); + const newFen = updateFEN(chessStore.fenCode, move); + chessStore.setFenCode(newFen); selectedPosition.value = null; } catch (err) { - error.value = `更新 FEN 码失败: ${(err as Error).message}`; + chessStore.setError(`更新 FEN 码失败: ${(err as Error).message}`); } } else { selectedPosition.value = [row, col]; @@ -153,8 +149,8 @@ }); }); - if (bestMove.value) { - drawArrow(ctx, bestMove.value); + if (chessStore.bestMove) { + drawArrow(ctx, chessStore.bestMove); } } diff --git a/src/composables/useChessEngine.ts b/src/composables/useChessEngine.ts index 2a94e54..3e7e1e4 100644 --- a/src/composables/useChessEngine.ts +++ b/src/composables/useChessEngine.ts @@ -6,7 +6,7 @@ import { storeToRefs } from 'pinia'; export function useChessEngine() { const isEngineReady = ref(false); const chessStore = useChessStore(); - const { isCalculating, error } = storeToRefs(chessStore); + const { isCalculating } = storeToRefs(chessStore); const engine = new ChessEngine(); @@ -15,7 +15,7 @@ export function useChessEngine() { await engine.initEngine(); isEngineReady.value = true; } catch (err) { - error.value = (err as Error).message; + chessStore.setError(`初始化引擎失败: ${(err as Error).message}`); } }; @@ -23,12 +23,11 @@ export function useChessEngine() { const fetchBestMove = async (fen: string, depth: number) => { isCalculating.value = true; - error.value = null; try { const bestMove = await engine.getBestMove(fen, depth); chessStore.setBestMove(bestMove); } catch (err) { - error.value = (err as Error).message; + chessStore.setError(`获取最佳移动失败: ${(err as Error).message}`); } finally { isCalculating.value = false; } diff --git a/src/composables/useImageProcessing.ts b/src/composables/useImageProcessing.ts index 2ca246e..2b32931 100644 --- a/src/composables/useImageProcessing.ts +++ b/src/composables/useImageProcessing.ts @@ -1,7 +1,6 @@ import { processImage } from '../utils/processImage'; import { generateFenFromPieces } from '../utils/notationUtils'; import { useChessStore } from '../stores/chess'; -import { storeToRefs } from 'pinia'; import cv from '@techstark/opencv-js'; import { ShallowRef } from 'vue'; @@ -9,24 +8,21 @@ export function useImageProcessing( templates: ShallowRef | undefined> ) { const chessStore = useChessStore(); - const { originalImageSize, chessboardRect, overlayImageSrc, error } = - storeToRefs(chessStore); - const { setFenCode } = chessStore; const processUploadedImage = (img: HTMLImageElement) => { if (!templates.value) { - error.value = '模板未加载'; + chessStore.setError('模板未加载'); return; } - originalImageSize.value = { width: img.width, height: img.height }; + chessStore.originalImageSize = { width: img.width, height: img.height }; try { const { adjustedChessboardRect, detectedPieces, overlayCanvas } = processImage(img, templates.value); - chessboardRect.value = adjustedChessboardRect; - overlayImageSrc.value = overlayCanvas.toDataURL(); + chessStore.chessboardRect = adjustedChessboardRect; + chessStore.overlayImageSrc = overlayCanvas.toDataURL(); const pieceLayout: string[][] = Array.from({ length: 10 }, () => Array(9).fill('none') @@ -39,9 +35,9 @@ export function useImageProcessing( }); const initialFenCode = generateFenFromPieces(pieceLayout, 'red'); - setFenCode(initialFenCode); + chessStore.setFenCode(initialFenCode); } catch (err) { - error.value = `处理图像失败: ${(err as Error).message}`; + chessStore.setError(`处理图像失败: ${(err as Error).message}`); } }; diff --git a/src/composables/useOpenCV.ts b/src/composables/useOpenCV.ts index 7581d76..49e6bef 100644 --- a/src/composables/useOpenCV.ts +++ b/src/composables/useOpenCV.ts @@ -3,26 +3,24 @@ import { onMounted, onUnmounted, shallowRef, markRaw } from 'vue'; import { PieceName } from '../types'; import { preprocessAllTemplates } from '../utils/cv/templateMatching'; import { useChessStore } from '../stores/chess'; -import { storeToRefs } from 'pinia'; export function useOpenCV() { const templates = shallowRef | undefined>(); const maxRetries = 10; let retries = 0; const chessStore = useChessStore(); - const { error } = storeToRefs(chessStore); const onOpenCVReady = async () => { console.log('OpenCV.js is ready'); try { const loadedTemplates = await preprocessAllTemplates(); if (Object.keys(loadedTemplates).length === 0) { - error.value = '没有成功加载任何模板'; + chessStore.setError('没有成功加载任何模板'); return; } templates.value = markRaw(loadedTemplates); } catch (err) { - error.value = `加载模板时出错: ${(err as Error).message}`; + chessStore.setError(`加载模板时出错: ${(err as Error).message}`); } }; @@ -32,7 +30,7 @@ export function useOpenCV() { const initialize = async () => { intervalId = window.setInterval(async () => { if (retries >= maxRetries) { - error.value = '在最大重试次数后仍未能加载 OpenCV.js'; + chessStore.setError('在最大重试次数后仍未能加载 OpenCV.js'); clearInterval(intervalId); return; } @@ -40,6 +38,8 @@ export function useOpenCV() { if (!templates.value && typeof cv !== 'undefined') { clearInterval(intervalId); await onOpenCVReady(); + } else if (templates.value) { + clearInterval(intervalId); } }, 500); if (typeof cv !== 'undefined') { diff --git a/src/stores/chess.ts b/src/stores/chess.ts index 3f07da2..b18bf07 100644 --- a/src/stores/chess.ts +++ b/src/stores/chess.ts @@ -19,12 +19,17 @@ export const useChessStore = defineStore('chess', () => { const error = ref(null); const depth = ref(Number(localStorage.getItem('depth')) || 15); + const setError = (errorMessage: string) => { + console.error(errorMessage); + error.value = errorMessage; + }; + const setFenCode = (fen: string) => { try { fenCode.value = fen; fenHistory.value.push(fen); } catch (err) { - error.value = `设置 FEN 码时出错: ${(err as Error).message}`; + setError(`设置 FEN 码时出错: ${(err as Error).message}`); } }; @@ -46,7 +51,7 @@ export const useChessStore = defineStore('chess', () => { moveHistory.value.push(bestMove.value); setBestMove(''); } catch (err) { - error.value = `执行下一步时出错: ${(err as Error).message}`; + setError(`执行下一步时出错: ${(err as Error).message}`); } }; @@ -85,6 +90,7 @@ export const useChessStore = defineStore('chess', () => { isCalculating, error, depth, + setError, setFenCode, setBestMove, handleNextMove,