feat: Add Scoreboard and Date Calc pages, update Calculator with scientific mode and new UI

This commit is contained in:
2026-02-05 16:04:09 +08:00
parent c8a67abdd2
commit 10304c4abf
15 changed files with 1390 additions and 80 deletions

View File

@@ -6,15 +6,34 @@ Page({
operator: null as string | null,
firstOperand: null as number | null,
waitingForSecondOperand: false,
isScientific: false
},
onLoad() {
},
vibrate() {
// wx.vibrateShort({ type: 'light' });
},
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,
@@ -28,6 +47,7 @@ Page({
},
onDot() {
this.vibrate();
const { displayValue, waitingForSecondOperand } = this.data;
if (waitingForSecondOperand) {
this.setData({
@@ -42,6 +62,7 @@ Page({
},
onClear() {
this.vibrate();
this.setData({
displayValue: '0',
history: '',
@@ -52,13 +73,94 @@ Page({
},
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: displayValue.length > 1 ? displayValue.slice(0, -1) : '0'
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 // 计算完后,下次输入数字是新数字
});
},
onOperator(e: any) {
this.vibrate();
const nextOperator = e.currentTarget.dataset.op;
const { displayValue, operator, firstOperand } = this.data;
const inputValue = parseFloat(displayValue);
@@ -66,7 +168,8 @@ Page({
if (operator && this.data.waitingForSecondOperand) {
this.setData({
operator: nextOperator,
history: `${firstOperand} ${nextOperator}`
// 更新历史记录中的符号
history: `${firstOperand} ${nextOperator}`
});
return;
}
@@ -79,7 +182,7 @@ Page({
const result = this.performCalculation(operator, firstOperand, inputValue);
newFirstOperand = result;
this.setData({
displayValue: String(result),
displayValue: String(result),
});
}
@@ -92,35 +195,33 @@ Page({
},
onEqual() {
this.vibrate();
const { displayValue, operator, firstOperand } = this.data;
const inputValue = parseFloat(displayValue);
if (operator && firstOperand != null) {
const result = this.performCalculation(operator, firstOperand, inputValue);
this.setData({
displayValue: String(result),
firstOperand: null,
operator: null,
waitingForSecondOperand: true,
history: ''
history: `${firstOperand} ${operator} ${inputValue} =`
});
}
},
performCalculation(operator: string, firstOperand: number, secondOperand: number) {
switch (operator) {
case '+':
return firstOperand + secondOperand;
case '-':
return firstOperand - secondOperand;
case '*':
return firstOperand * secondOperand;
case '/':
return firstOperand / secondOperand;
case '%':
return firstOperand % secondOperand;
default:
return secondOperand;
}
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;
}
});
})

View File

@@ -1,32 +1,68 @@
<!--pages/calculator/calculator.wxml-->
<view class="calculator">
<view class="screen">
<view class="history">{{history}}</view>
<view class="result">{{displayValue}}</view>
<view class="calculator-container">
<!-- 显示区域 -->
<view class="display-area">
<view class="mode-indicator" bindtap="toggleMode">
<text class="{{isScientific ? 'active' : ''}}">⚗️ 科学模式</text>
</view>
<view class="history-text">{{history}}</view>
<view class="current-value {{displayValue.length > 9 ? 'shrink' : ''}} {{displayValue.length > 15 ? 'shrink-more' : ''}}">{{displayValue}}</view>
</view>
<view class="keypad">
<view class="btn operator" bindtap="onClear">C</view>
<view class="btn operator" bindtap="onDelete">DEL</view>
<view class="btn operator" bindtap="onOperator" data-op="%">%</view>
<view class="btn operator" bindtap="onOperator" data-op="/">÷</view>
<!-- 键盘区域 -->
<view class="keypad-area {{isScientific ? 'scientific-pad' : ''}}">
<view class="btn" bindtap="onDigit" data-digit="7">7</view>
<view class="btn" bindtap="onDigit" data-digit="8">8</view>
<view class="btn" bindtap="onDigit" data-digit="9">9</view>
<view class="btn operator" bindtap="onOperator" data-op="*">×</view>
<!-- 科学功能区 (隐藏/显示) -->
<block wx:if="{{isScientific}}">
<view class="row small-row">
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="sin">sin</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="cos">cos</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="tan">tan</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="log">log</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="ln">ln</view>
</view>
<view class="row small-row">
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onConstant" data-const="pi">π</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onConstant" data-const="e">e</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="pow2">x²</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="sqrt">√</view>
<view class="btn sci-btn" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onMathFunc" data-func="percent">%</view>
</view>
</block>
<!-- 基础键盘 -->
<view class="row">
<view class="btn func" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onClear">AC</view>
<view class="btn func" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDelete">⌫</view>
<view class="btn func" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onToggleSign">+/-</view>
<view class="btn operator" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onOperator" data-op="÷">÷</view>
</view>
<view class="btn" bindtap="onDigit" data-digit="4">4</view>
<view class="btn" bindtap="onDigit" data-digit="5">5</view>
<view class="btn" bindtap="onDigit" data-digit="6">6</view>
<view class="btn operator" bindtap="onOperator" data-op="-">-</view>
<view class="row">
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="7">7</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="8">8</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="9">9</view>
<view class="btn operator" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onOperator" data-op="×">×</view>
</view>
<view class="btn" bindtap="onDigit" data-digit="1">1</view>
<view class="btn" bindtap="onDigit" data-digit="2">2</view>
<view class="btn" bindtap="onDigit" data-digit="3">3</view>
<view class="btn operator" bindtap="onOperator" data-op="+">+</view>
<view class="row">
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="4">4</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="5">5</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="6">6</view>
<view class="btn operator" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onOperator" data-op="-"></view>
</view>
<view class="btn zero" bindtap="onDigit" data-digit="0">0</view>
<view class="btn" bindtap="onDot">.</view>
<view class="btn equal" bindtap="onEqual">=</view>
<view class="row">
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="1">1</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="2">2</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="3">3</view>
<view class="btn operator" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onOperator" data-op="+">+</view>
</view>
<view class="row">
<view class="btn digit zero" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDigit" data-digit="0">0</view>
<view class="btn digit" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onDot">.</view>
<view class="btn operator equal" hover-class="btn-hover" hover-start-time="0" hover-stay-time="100" bindtap="onEqual">=</view>
</view>
</view>
</view>

View File

@@ -1,74 +1,188 @@
/* pages/calculator/calculator.wxss */
page {
height: 100%;
background-color: #f5f5f5;
background-color: #000000;
display: flex;
flex-direction: column;
}
.calculator {
.calculator-container {
display: flex;
flex-direction: column;
height: 100%;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.screen {
/* 显示区域 */
.display-area {
flex: 1;
background-color: #333;
color: white;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
padding: 20rpx;
padding: 40rpx;
background-color: #000;
position: relative;
}
.mode-indicator {
position: absolute;
top: 40rpx;
left: 40rpx;
}
.mode-indicator text {
color: #444;
font-size: 24rpx;
border: 1px solid #444;
padding: 10rpx 20rpx;
border-radius: 30rpx;
}
.mode-indicator text.active {
color: #ff9f0a;
border-color: #ff9f0a;
background: rgba(255, 159, 10, 0.1);
}
.history-text {
font-size: 36rpx;
color: #666;
min-height: 50rpx;
margin-bottom: 20rpx;
font-family: monospace;
text-align: right;
width: 100%;
}
.current-value {
font-size: 160rpx;
color: #fff;
line-height: 1;
font-weight: 200;
word-break: break-all;
text-align: right;
width: 100%;
}
.history {
font-size: 40rpx;
color: #aaa;
margin-bottom: 10rpx;
.current-value.shrink {
font-size: 100rpx;
}
.current-value.shrink-more {
font-size: 70rpx;
}
.result {
font-size: 80rpx;
font-weight: bold;
/* 键盘区域 */
.keypad-area {
background-color: #000;
padding: 0 30rpx 30rpx 30rpx;
display: flex;
flex-direction: column;
gap: 30rpx;
}
.keypad {
background-color: #fff;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 1px;
background-color: #ccc; /* Gap color */
/* 科学模式适配 */
.keypad-area.scientific-pad {
gap: 20rpx;
padding-bottom: 20rpx;
}
/* 统一圆形按钮 */
.keypad-area.scientific-pad .btn {
width: 130rpx;
height: 130rpx;
font-size: 50rpx;
border-radius: 50%; /* 保持圆形 */
}
.keypad-area.scientific-pad .zero {
width: 280rpx; /* 适配新的宽度 */
border-radius: 65rpx; /* 圆角为高度一半 */
}
/* 科学功能键行 */
.keypad-area.scientific-pad .sci-btn {
width: 120rpx; /* 稍微大一点,填满宽度 */
height: 120rpx; /* 正圆 */
font-size: 36rpx;
background: #222;
color: #fff;
border-radius: 50%;
}
.small-row {
justify-content: space-around; /* 均匀分布 */
gap: 10rpx;
}
.row {
display: flex;
justify-content: space-between;
gap: 30rpx;
}
.keypad-area.scientific-pad .row {
gap: 20rpx;
}
.btn {
background-color: #fff;
width: 150rpx;
height: 150rpx;
border-radius: 75rpx; /* 圆形按钮 */
display: flex;
justify-content: center;
align-items: center;
font-size: 40rpx;
active-color: #eee;
font-size: 60rpx;
font-weight: 500;
}
.btn:active {
background-color: #eee;
/* 数字键 */
.digit {
background-color: #333333;
color: #fff;
}
/* 功能键 (AC, Del, +/-) */
.func {
background-color: #a5a5a5;
color: #000;
font-size: 50rpx;
font-weight: 600;
}
/* 运算符 */
.operator {
color: #ff9500;
font-weight: bold;
}
.equal {
background-color: #ff9500;
color: white;
}
.equal:active {
background-color: #e08900;
background-color: #ff9f0a;
color: #fff;
font-size: 70rpx;
padding-bottom: 10rpx;
padding: 0;
}
/* 0键特殊处理 */
.zero {
grid-column: span 2;
width: 330rpx;
border-radius: 75rpx;
justify-content: flex-start;
padding-left: 60rpx;
box-sizing: border-box;
}
/* 点击反馈 */
.btn-hover {
opacity: 0.7;
}
/* 平板适配或小屏适配 */
@media (max-width: 360px) {
.btn {
width: 140rpx;
height: 140rpx;
font-size: 50rpx;
}
.zero {
width: 310rpx;
}
}