import { config } from '../../config'; // 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, showHelp: false, showSettingsMenu: false, historyList: [] as Array<{expression: string, result: string}> }, onShareAppMessage() { return config.share; }, onShareTimeline() { return config.share; }, toggleHelp() { this.setData({ showHelp: !this.data.showHelp, showSettingsMenu: false }); }, toggleSettings() { this.vibrate(); this.setData({ showSettingsMenu: !this.data.showSettingsMenu }); }, closeSettings() { if (this.data.showSettingsMenu) { this.setData({ showSettingsMenu: false }); } }, onLoad() { // 开启分享菜单 wx.showShareMenu({ withShareTicket: false, menus: ['shareAppMessage', 'shareTimeline'] }); // 从本地存储恢复历史记录 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 }); }, switchMode(e: any) { const mode = e.currentTarget.dataset.mode; const isSci = (mode === 'scientific'); if (this.data.isScientific !== isSci) { this.vibrate(); this.setData({ isScientific: isSci }); } }, 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.vibrate(); this.setData({ showHistory: !this.data.showHistory, showSettingsMenu: false }); }, clearHistory() { this.vibrate(); wx.removeStorageSync('CALC_HISTORY'); this.setData({ historyList: [] }); }, useHistoryResult(e: any) { this.vibrate(); const result = e.currentTarget.dataset.result; this.setData({ displayValue: result, waitingForSecondOperand: false, // Treat as a fresh input that can be operated on showHistory: false }); }, copyResult() { this.vibrate(); const { displayValue } = this.data; wx.setClipboardData({ data: displayValue, success: () => { // wx.hideToast(); // 隐藏系统默认的"内容已复制"提示 // wx.showToast({ // title: '复制成功', // icon: 'success' // }); }, fail: (err) => { console.error('复制失败:', err); // 隐私协议未声明或用户拒绝会导致复制失败 (errno 112) if (err.errno === 112 || (err.errMsg && err.errMsg.indexOf('privacy') > -1)) { wx.showModal({ title: '提示', content: '无法自动复制,请长按显示区域手动复制', showCancel: false, confirmText: '知道了' }); } } }); } });