好的,我们可以在计算器中添加数字按钮,并使用 UnoCSS 来美化界面。以下是修改后的代码:
- 首先,安装必要的依赖:
bun add @unocss/core unocss @unocss/preset-uno @elysiajs/html- 修改
server.ts:
import { Elysia } from 'elysia'
import { staticPlugin } from '@elysiajs/static'
import { html } from '@elysiajs/html'
import React from 'react'
import { renderToString } from 'react-dom/server'
import { Calculator } from './components/Calculator'
import { createGenerator } from '@unocss/core'
import presetUno from '@unocss/preset-uno'
const uno = createGenerator({
presets: [presetUno()],
})
const app = new Elysia()
.use(staticPlugin())
.use(html())
app.get('/', async ({ html }) => {
const calculatorHtml = renderToString(React.createElement(Calculator))
const { css } = await uno.generate(calculatorHtml)
return html(
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Complex Calculator</title>
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<style>${css}</style>
</head>
<body>
<div id="root">${calculatorHtml}</div>
<script type="text/babel" src="/static/client.js"></script>
</body>
</html>`
)
})
// ... 保留原有的 /calculate 路由和其他代码 ...
app.listen(3000)
console.log('Server is running on http://localhost:3000')- 修改
components/Calculator.tsx:
import React, { useState } from 'react'
const themes = {
light: 'bg-white text-black',
dark: 'bg-gray-800 text-white',
colorful: 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500 text-white',
}
export const Calculator: React.FC = () => {
const [operation, setOperation] = useState('')
const [values, setValues] = useState('')
const [result, setResult] = useState<number | null>(null)
const [theme, setTheme] = useState('light')
const [layout, setLayout] = useState('vertical')
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
const response = await fetch('/calculate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ operation, values: values.split(',').map(Number) }),
})
const data = await response.json()
setResult(data.result)
}
const handleNumberClick = (num: number) => {
setValues(prev => prev + (prev ? ',' : '') + num)
}
const handleClear = () => {
setValues('')
setResult(null)
}
return (
<div className={`p-4 ${themes[theme as keyof typeof themes]} ${layout === 'vertical' ? 'flex flex-col' : 'flex flex-row'}`}>
<div className="flex-1">
<h1 className="text-2xl font-bold mb-4">Complex Calculator</h1>
<form onSubmit={handleSubmit} className="mb-4">
<select
value={operation}
onChange={(e) => setOperation(e.target.value)}
className="w-full p-2 mb-2 border rounded"
>
<option value="">Select operation</option>
<option value="sin">Sin</option>
<option value="cos">Cos</option>
<option value="tan">Tan</option>
<option value="mean">Mean</option>
<option value="median">Median</option>
</select>
<input
type="text"
value={values}
onChange={(e) => setValues(e.target.value)}
placeholder="Enter values (comma-separated)"
className="w-full p-2 mb-2 border rounded"
/>
<button type="submit" className="w-full p-2 bg-blue-500 text-white rounded hover:bg-blue-600">Calculate</button>
</form>
{result !== null && <p className="text-xl">Result: {result}</p>}
<div className="grid grid-cols-3 gap-2 mt-4">
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].map((num) => (
<button
key={num}
onClick={() => handleNumberClick(num)}
className="p-2 bg-gray-200 rounded hover:bg-gray-300"
>
{num}
</button>
))}
<button
onClick={handleClear}
className="p-2 bg-red-500 text-white rounded hover:bg-red-600 col-span-3"
>
Clear
</button>
</div>
</div>
<div className={`${layout === 'vertical' ? 'mt-4' : 'ml-4'}`}>
<h2 className="text-xl font-bold mb-2">Customize</h2>
<select
value={theme}
onChange={(e) => setTheme(e.target.value)}
className="w-full p-2 mb-2 border rounded"
>
<option value="light">Light Theme</option>
<option value="dark">Dark Theme</option>
<option value="colorful">Colorful Theme</option>
</select>
<select
value={layout}
onChange={(e) => setLayout(e.target.value)}
className="w-full p-2 mb-2 border rounded"
>
<option value="vertical">Vertical Layout</option>
<option value="horizontal">Horizontal Layout</option>
</select>
</div>
</div>
)
}- 修改
static/client.js:
ReactDOM.hydrate(
React.createElement(Calculator),
document.getElementById('root')
)这些修改添加了以下功能:
- 数字按钮:用户现在可以点击数字按钮来输入值,而不仅仅是手动输入。
- 清除按钮:允许用户快速清除输入和结果。
- UnoCSS 样式:使用 UnoCSS 的工具类来美化界面,包括响应式布局、颜色主题等。
- 主题切换:现在使用 UnoCSS 的类来切换主题,而不是内联样式。
注意,我们不再需要单独的 styles.css 文件,因为所有的样式都通过 UnoCSS 的工具类来实现。
要运行这个增强版的计算器应用,确保你已经安装了所有必要的依赖,然后使用 bun start 命令启动服务器。
这个版本的计算器不仅功能更加完善,而且界面也更加美观和响应式。你可以根据需要进一步调整样式和布局。