删除不再使用的常量、工具函数和样式文件

This commit is contained in:
Zhuym 2025-01-28 16:10:02 +08:00
parent 1a471bc07e
commit 569b30e921
7 changed files with 103 additions and 512 deletions

BIN
._src

Binary file not shown.

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>API调试工具</title>
<title>TsumugiBoshi|纺星</title>
<!-- Material Icons -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
@ -25,8 +25,16 @@
}
#root {
flex: 1;
display: flex;
flex-direction: column;
}
pre {
background: #f5f5f5;
padding: 10px;
border-radius: 4px;
font-size: 14px;
overflow-x: auto;
}
pre { background: #f5f5f5; padding: 10px; border-radius: 4px; }
.api-description {
margin: 8px 0 16px !important;
color: #666;
@ -36,6 +44,7 @@
padding: 12px;
border-radius: 4px;
border-left: 4px solid #1976d2;
font-size: 0.9rem;
}
.selected-backend { font-weight: bold; color: #1976d2; }
.scrollable-tabs {
@ -63,13 +72,37 @@
font-size: 0.875rem;
color: #666;
}
.backend-selector {
margin-top: 2rem;
padding: 1.5rem;
background-color: #f8f9fa;
border-radius: 4px;
}
@media (max-width: 600px) {
.MuiContainer-root {
padding: 12px !important;
padding: 8px !important;
}
.MuiPaper-root {
padding: 12px !important;
}
.MuiTypography-h4 {
font-size: 1.5rem !important;
}
.MuiTypography-h6 {
font-size: 1.1rem !important;
}
.MuiTab-root {
min-height: 48px !important;
padding: 6px 12px !important;
font-size: 0.8rem !important;
}
.MuiInputBase-input {
font-size: 0.9rem !important;
}
.backend-selector {
margin-top: 1rem;
padding: 1rem;
}
h4.MuiTypography-root {
font-size: 1.5rem;
}
@ -87,7 +120,7 @@
<div id="root"></div>
<footer>
<Typography variant="body2" color="textSecondary">
© 2023 Tsumugiboshi. All rights reserved.
© 2025 Tsumugiboshi. All rights reserved.
<br />
</Typography>
</footer>
@ -367,97 +400,14 @@
return (
<ThemeProvider theme={theme}>
<Container maxWidth="md" style={{ marginTop: '1rem', marginBottom: '2rem' }}>
{/* 后端地址选择器 */}
<FormControl fullWidth style={{ marginBottom: '2rem' }}>
<InputLabel>选择后端地址</InputLabel>
<Select
value={apiBase}
onChange={handleApiBaseChange}
label="选择后端地址"
>
{/* 默认后端 */}
{PRESET_BACKENDS.map((backend) => (
<MenuItem key={backend.value} value={backend.value}>
{backend.label} - {backend.value}
</MenuItem>
))}
{/* 分割线 */}
{backends.some(b => !PRESET_BACKENDS.some(preset => preset.value === b.value)) && (
<MenuItem disabled>
<hr style={{ width: '100%', margin: '4px 0' }} />
</MenuItem>
)}
{/* 自定义后端 */}
{backends
.filter(b => !PRESET_BACKENDS.some(preset => preset.value === b.value))
.map((backend) => (
<MenuItem key={backend.value} value={backend.value}>
<Box display="flex" justifyContent="space-between" width="100%">
<span>{backend.label} - {backend.value}</span>
<Button
size="small"
color="error"
onClick={(e) => {
e.stopPropagation();
handleDeleteBackend(backend.value);
}}
>
删除
</Button>
</Box>
</MenuItem>
))}
</Select>
<Button
variant="outlined"
color="primary"
style={{ marginTop: '1rem' }}
onClick={handleAddBackend}
>
添加自定义后端
</Button>
</FormControl>
{/* 添加自定义后端对话框 */}
<Dialog open={isDialogOpen} onClose={handleDialogClose}>
<DialogTitle>添加自定义后端</DialogTitle>
<DialogContent>
<TextField
fullWidth
label="后端名称"
value={newBackend.label}
onChange={(e) => setNewBackend({ ...newBackend, label: e.target.value })}
style={{ marginBottom: '1rem' }}
/>
<TextField
fullWidth
label="后端地址"
value={newBackend.value}
onChange={(e) => setNewBackend({ ...newBackend, value: e.target.value })}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleDialogClose}>取消</Button>
<Button onClick={handleSaveBackend} color="primary">保存</Button>
</DialogActions>
</Dialog>
{/* Snackbar 提示 */}
<Snackbar
open={snackbarOpen}
autoHideDuration={3000}
onClose={handleSnackbarClose}
>
<Alert onClose={handleSnackbarClose} severity="success">
{snackbarMessage}
</Alert>
</Snackbar>
<Typography variant="h4" gutterBottom>
API调试工具
💫TsumugiBoshi
</Typography>
<Typography variant="subtitle1" gutterBottom>
神秘API调试工具
</Typography>
{/* API表单部分 */}
<Paper elevation={3} style={{ padding: '1rem', marginBottom: '1rem' }}>
<div className="tabs-container">
<Box className="scrollable-tabs">
@ -523,19 +473,78 @@
</Paper>
{response && (
<Paper elevation={3} style={{ padding: '1rem' }}>
<Paper elevation={3} style={{ padding: '1rem', marginBottom: '1rem' }}>
<Typography variant="h6" gutterBottom>响应结果:</Typography>
<pre style={{
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
backgroundColor: '#f5f5f5',
padding: '1rem',
borderRadius: '4px'
borderRadius: '4px',
fontSize: '0.9rem'
}}>
{response}
</pre>
</Paper>
)}
{/* 移动后端选择器到底部 */}
<Paper elevation={3} className="backend-selector">
<Typography variant="h6" gutterBottom>
后端设置
</Typography>
<FormControl fullWidth>
<InputLabel>选择后端地址</InputLabel>
<Select
value={apiBase}
onChange={handleApiBaseChange}
label="选择后端地址"
>
{/* 默认后端 */}
{PRESET_BACKENDS.map((backend) => (
<MenuItem key={backend.value} value={backend.value}>
{backend.label} - {backend.value}
</MenuItem>
))}
{/* 分割线 */}
{backends.some(b => !PRESET_BACKENDS.some(preset => preset.value === b.value)) && (
<MenuItem disabled>
<hr style={{ width: '100%', margin: '4px 0' }} />
</MenuItem>
)}
{/* 自定义后端 */}
{backends
.filter(b => !PRESET_BACKENDS.some(preset => preset.value === b.value))
.map((backend) => (
<MenuItem key={backend.value} value={backend.value}>
<Box display="flex" justifyContent="space-between" width="100%">
<span>{backend.label} - {backend.value}</span>
<Button
size="small"
color="error"
onClick={(e) => {
e.stopPropagation();
handleDeleteBackend(backend.value);
}}
>
删除
</Button>
</Box>
</MenuItem>
))}
</Select>
<Button
variant="outlined"
color="primary"
style={{ marginTop: '1rem' }}
onClick={handleAddBackend}
>
添加自定义后端
</Button>
</FormControl>
</Paper>
</Container>
</ThemeProvider>
);

View File

@ -1,228 +0,0 @@
import React from 'react';
import {
Tabs,
Tab,
TextField,
Button,
Paper,
Typography,
Grid,
Box,
Select,
MenuItem,
InputLabel,
FormControl,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Snackbar,
Alert,
Radio,
RadioGroup,
FormControlLabel
} from '@mui/material';
import { setCookie } from '../utils/cookies';
function ApiTabs({
tabValue,
setTabValue,
qrInput,
setQrInput,
userId,
setUserId,
response,
setResponse,
musicData,
setMusicData,
apiBase,
setApiBase,
backends,
setBackends,
isDialogOpen,
setIsDialogOpen,
newBackend,
setNewBackend,
snackbarOpen,
setSnackbarOpen,
snackbarMessage,
setSnackbarMessage
}) {
const handleTabChange = (event, newValue) => {
setTabValue(newValue);
};
const handleUserIdChange = (event) => {
const value = event.target.value;
setUserId(value);
setCookie('userId', value);
setMusicData(prev => ({ ...prev, userId: parseInt(value) || 0 }));
};
const handleBackendChange = (event) => {
const value = event.target.value;
setApiBase(value);
localStorage.setItem('apiBase', value);
};
const handleAddBackend = () => {
if (!newBackend.label || !newBackend.value) {
setSnackbarMessage('请填写完整的后端信息');
setSnackbarOpen(true);
return;
}
const updatedBackends = [...backends, newBackend];
setBackends(updatedBackends);
localStorage.setItem('customBackends', JSON.stringify(
updatedBackends.slice(PRESET_BACKENDS.length)
));
setIsDialogOpen(false);
setNewBackend({ label: '', value: '' });
};
return (
<>
<Paper elevation={3} sx={{ p: 3, mb: 4 }}>
<Typography variant="h4" gutterBottom>
API调试工具
</Typography>
<div className="tabs-container">
<div className="scrollable-tabs">
<Tabs
value={tabValue}
onChange={handleTabChange}
variant="scrollable"
scrollButtons="auto"
>
<Tab label="二维码解析" />
<Tab label="音乐数据" />
</Tabs>
</div>
</div>
<Box sx={{ mt: 3 }}>
<Grid container spacing={3}>
<Grid item xs={12} md={6}>
<TextField
fullWidth
label="用户ID"
value={userId}
onChange={handleUserIdChange}
variant="outlined"
/>
</Grid>
<Grid item xs={12} md={6}>
<FormControl fullWidth>
<InputLabel>后端环境</InputLabel>
<Select
value={apiBase}
onChange={handleBackendChange}
label="后端环境"
>
{backends.map((backend, index) => (
<MenuItem key={index} value={backend.value}>
{backend.label}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
{tabValue === 0 && (
<Box sx={{ mt: 3 }}>
<TextField
fullWidth
multiline
rows={4}
label="二维码内容"
value={qrInput}
onChange={(e) => setQrInput(e.target.value)}
variant="outlined"
/>
</Box>
)}
{tabValue === 1 && (
<Box sx={{ mt: 3 }}>
<Grid container spacing={2}>
{Object.entries(musicData.music).map(([key, value]) => (
<Grid item xs={12} sm={6} md={4} key={key}>
<TextField
fullWidth
label={key}
type="number"
value={value}
onChange={(e) => {
const newValue = parseInt(e.target.value) || 0;
setMusicData(prev => ({
...prev,
music: {
...prev.music,
[key]: newValue
}
}));
}}
variant="outlined"
/>
</Grid>
))}
</Grid>
</Box>
)}
{response && (
<Box sx={{ mt: 3 }}>
<Typography variant="h6" gutterBottom>
响应结果
</Typography>
<pre>{JSON.stringify(response, null, 2)}</pre>
</Box>
)}
</Box>
</Paper>
<Dialog open={isDialogOpen} onClose={() => setIsDialogOpen(false)}>
<DialogTitle>添加自定义后端</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
label="名称"
fullWidth
value={newBackend.label}
onChange={(e) => setNewBackend(prev => ({ ...prev, label: e.target.value }))}
/>
<TextField
margin="dense"
label="地址"
fullWidth
value={newBackend.value}
onChange={(e) => setNewBackend(prev => ({ ...prev, value: e.target.value }))}
/>
</DialogContent>
<DialogActions>
<Button onClick={() => setIsDialogOpen(false)}>取消</Button>
<Button onClick={handleAddBackend}>添加</Button>
</DialogActions>
</Dialog>
<Snackbar
open={snackbarOpen}
autoHideDuration={6000}
onClose={() => setSnackbarOpen(false)}
>
<Alert
onClose={() => setSnackbarOpen(false)}
severity="error"
sx={{ width: '100%' }}
>
{snackbarMessage}
</Alert>
</Snackbar>
</>
);
}
export default ApiTabs;

View File

@ -1,79 +0,0 @@
import React, { useState } from 'react';
import { Container, Typography } from '@mui/material';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import ApiTabs from './ApiTabs';
import { PRESET_BACKENDS } from '../constants';
import { getCookie, setCookie } from '../utils/cookies';
const theme = createTheme();
function App() {
const [tabValue, setTabValue] = useState(0);
const [qrInput, setQrInput] = useState('');
const [userId, setUserId] = useState(getCookie('userId') || '');
const [response, setResponse] = useState('');
const [musicData, setMusicData] = useState({
userId: parseInt(userId) || 0,
music: {
musicId: 0,
level: 0,
achievement: 0,
playCount: 0,
comboStatus: 0,
syncStatus: 0,
deluxscoreMax: 0,
scoreRank: 0
}
});
const [apiBase, setApiBase] = useState(
localStorage.getItem('apiBase') || PRESET_BACKENDS[0].value
);
const [backends, setBackends] = useState([
...PRESET_BACKENDS,
...JSON.parse(localStorage.getItem('customBackends') || '[]')
]);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [newBackend, setNewBackend] = useState({ label: '', value: '' });
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState('');
return (
<ThemeProvider theme={theme}>
<div id="root">
<Container maxWidth="md" sx={{ mt: 4, mb: 4 }}>
<ApiTabs
tabValue={tabValue}
setTabValue={setTabValue}
qrInput={qrInput}
setQrInput={setQrInput}
userId={userId}
setUserId={setUserId}
response={response}
setResponse={setResponse}
musicData={musicData}
setMusicData={setMusicData}
apiBase={apiBase}
setApiBase={setApiBase}
backends={backends}
setBackends={setBackends}
isDialogOpen={isDialogOpen}
setIsDialogOpen={setIsDialogOpen}
newBackend={newBackend}
setNewBackend={setNewBackend}
snackbarOpen={snackbarOpen}
setSnackbarOpen={setSnackbarOpen}
snackbarMessage={snackbarMessage}
setSnackbarMessage={setSnackbarMessage}
/>
</Container>
</div>
<footer>
<Typography variant="body2" color="textSecondary">
© 2023 Tsumugiboshi. All rights reserved.
</Typography>
</footer>
</ThemeProvider>
);
}
export default App;

View File

@ -1,5 +0,0 @@
export const PRESET_BACKENDS = [
{ label: "开发环境", value: "http://dev-api.example.com" },
{ label: "测试环境", value: "http://test-api.example.com" },
{ label: "生产环境", value: "http://api.example.com" }
];

View File

@ -1,85 +0,0 @@
body {
margin: 0;
font-family: Arial, sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
}
#root {
flex: 1;
}
pre {
background: #f5f5f5;
padding: 10px;
border-radius: 4px;
}
.api-description {
margin: 8px 0 16px !important;
color: #666;
white-space: pre-line;
line-height: 1.5;
background-color: #f8f9fa;
padding: 12px;
border-radius: 4px;
border-left: 4px solid #1976d2;
}
.selected-backend {
font-weight: bold;
color: #1976d2;
}
.scrollable-tabs {
max-width: calc(100% - 48px);
overflow-x: auto;
overflow-y: hidden;
}
.tabs-container {
display: flex;
align-items: center;
position: relative;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
.menu-button {
position: absolute !important;
right: 0;
top: 50%;
transform: translateY(-50%);
}
footer {
margin-top: auto;
padding: 16px;
background-color: #f5f5f5;
text-align: center;
font-size: 0.875rem;
color: #666;
}
@media (max-width: 600px) {
.MuiContainer-root {
padding: 12px !important;
}
.MuiPaper-root {
padding: 12px !important;
}
h4.MuiTypography-root {
font-size: 1.5rem;
}
.scrollable-tabs::-webkit-scrollbar {
display: none;
}
.api-description {
font-size: 0.875rem;
padding: 8px;
}
}

View File

@ -1,21 +0,0 @@
export function setCookie(name, value, days = 30) {
const d = new Date();
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = `expires=${d.toUTCString()}`;
document.cookie = `${name}=${value};${expires};path=/`;
}
export function getCookie(name) {
const nameEQ = `${name}=`;
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
export function deleteCookie(name) {
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/`;
}