// pages/calculator/calculator.ts Page({ data: { displayValue: '0', history: '', operator: null as string | null, firstOperand: null as number | null, waitingForSecondOperand: false, isScientific: false, showHistory: false, historyList: [] as Array<{expression: string, result: string}> }, onLoad() { // 从本地存储恢复历史记录 const saved = wx.getStorageSync('CALC_HISTORY'); if (saved && Array.isArray(saved)) { this.setData({ historyList: saved }); } }, vibrate() { wx.vibrateShort({ type: 'light' }).catch(() => {}); }, preventTouchMove() { // 阻止历史面板底层滚动 }, toggleMode() { this.vibrate(); this.setData({ isScientific: !this.data.isScientific }); }, onDigit(e: any) { this.vibrate(); const digit = e.currentTarget.dataset.digit; const { displayValue, waitingForSecondOperand } = this.data; // 科学模式允许更多数字 const limit = 15; if (!waitingForSecondOperand && displayValue.length >= limit) { return; } if (waitingForSecondOperand) { this.setData({ displayValue: digit, waitingForSecondOperand: false }); } else { this.setData({ displayValue: displayValue === '0' ? digit : displayValue + digit }); } }, onDot() { this.vibrate(); const { displayValue, waitingForSecondOperand } = this.data; if (waitingForSecondOperand) { this.setData({ displayValue: '0.', waitingForSecondOperand: false }); } else if (displayValue.indexOf('.') === -1) { this.setData({ displayValue: displayValue + '.' }); } }, onClear() { this.vibrate(); this.setData({ displayValue: '0', history: '', operator: null, firstOperand: null, waitingForSecondOperand: false }); }, onDelete() { this.vibrate(); const { displayValue } = this.data; if (displayValue.length > 1) { this.setData({ displayValue: displayValue.slice(0, -1) }); } else { this.setData({ displayValue: '0' }); } }, onToggleSign() { this.vibrate(); const { displayValue } = this.data; const newValue = parseFloat(displayValue) * -1; this.setData({ displayValue: String(newValue) }); }, onConstant(e: any) { this.vibrate(); const type = e.currentTarget.dataset.const; let val = 0; if (type === 'pi') val = Math.PI; if (type === 'e') val = Math.E; this.setData({ displayValue: String(val).slice(0, 10), waitingForSecondOperand: true // 下次输入将开启新数字,或者作为操作数 }); }, onMathFunc(e: any) { // 单操作数立即计算 this.vibrate(); const func = e.currentTarget.dataset.func; let val = parseFloat(this.data.displayValue); let result = 0; let desc = ''; switch(func) { case 'sin': // 默认转为弧度计算 (度数 * PI / 180) result = Math.sin(val * Math.PI / 180); desc = `sin(${val})`; break; case 'cos': result = Math.cos(val * Math.PI / 180); desc = `cos(${val})`; break; case 'tan': result = Math.tan(val * Math.PI / 180); desc = `tan(${val})`; break; case 'log': result = Math.log10(val); desc = `log(${val})`; break; case 'ln': result = Math.log(val); desc = `ln(${val})`; break; case 'sqrt': result = Math.sqrt(val); desc = `√(${val})`; break; case 'pow2': result = Math.pow(val, 2); desc = `sqr(${val})`; break; case 'percent': result = val / 100; desc = `${val}%`; break; } // 格式化结果 const formatted = parseFloat(result.toPrecision(12)); this.setData({ displayValue: String(formatted), history: desc, waitingForSecondOperand: true // 计算完后,下次输入数字是新数字 }); this.addToHistory(desc, String(formatted)); }, onOperator(e: any) { this.vibrate(); const nextOperator = e.currentTarget.dataset.op; const { displayValue, operator, firstOperand } = this.data; const inputValue = parseFloat(displayValue); if (operator && this.data.waitingForSecondOperand) { this.setData({ operator: nextOperator, // 更新历史记录中的符号 history: `${firstOperand} ${nextOperator}` }); return; } let newFirstOperand = firstOperand; if (firstOperand == null) { newFirstOperand = inputValue; } else if (operator) { const result = this.performCalculation(operator, firstOperand, inputValue); newFirstOperand = result; this.setData({ displayValue: String(result), }); } this.setData({ firstOperand: newFirstOperand, waitingForSecondOperand: true, operator: nextOperator, history: `${newFirstOperand} ${nextOperator}` }); }, onEqual() { this.vibrate(); const { displayValue, operator, firstOperand } = this.data; const inputValue = parseFloat(displayValue); if (operator && firstOperand != null) { const result = this.performCalculation(operator, firstOperand, inputValue); const expression = `${firstOperand} ${operator} ${inputValue}`; this.setData({ displayValue: String(result), firstOperand: null, operator: null, waitingForSecondOperand: true, history: `${firstOperand} ${operator} ${inputValue} =` }); this.addToHistory(expression, String(result)); } }, performCalculation(op: string, first: number, second: number): number { let result = 0; switch(op) { case '+': result = first + second; break; case '-': result = first - second; break; case '×': result = first * second; break; case '÷': result = first / second; break; default: return second; } const precision = 10000000000; return Math.round(result * precision) / precision; }, // 历史记录相关方法 addToHistory(expression: string, result: string) { const list = this.data.historyList.slice(); list.unshift({ expression, result }); // 最多保留50条 if (list.length > 50) list.length = 50; this.setData({ historyList: list }); wx.setStorageSync('CALC_HISTORY', list); }, toggleHistory() { this.setData({ showHistory: !this.data.showHistory }); }, clearHistory() { this.setData({ historyList: [] }); wx.removeStorageSync('CALC_HISTORY'); }, useHistoryResult(e: any) { const result = e.currentTarget.dataset.result; this.setData({ displayValue: String(result), showHistory: false, waitingForSecondOperand: true }); }, copyResult() { wx.setClipboardData({ data: this.data.displayValue, success: () => { wx.showToast({ title: '已复制', icon: 'success', duration: 1000 }); } }); } })