add temp ticket

This commit is contained in:
xion 2025-04-03 15:35:24 +08:00
parent 7fb0666612
commit e56eaab69a
8 changed files with 216 additions and 28 deletions

View File

@ -42,6 +42,7 @@
"@types/react-dom": "^19.1.1",
"@vitejs/plugin-basic-ssl": "^2.0.0",
"@vitejs/plugin-react": "^4.3.4",
"commander": "^13.1.0",
"tailwindcss": "^4.1.1",
"typescript": "^5.8.2",
"vite": "^6.2.4"

View File

View File

@ -1,3 +0,0 @@
packages:
- 'submodules/*'
- 'packages/*'

View File

@ -1,5 +1,6 @@
import fs from 'fs';
import path from 'path';
import { program } from 'commander';
export const root = process.cwd();
@ -9,3 +10,11 @@ export const clearWorkspace = () => {
fs.rmSync(path.join(root, file), { recursive: true, force: true });
}
};
// clearWorkspace();
program.option('-c, --clear', 'clear workspace').action((opts) => {
if (opts.clear) {
clearWorkspace();
}
});
program.parse(process.argv);

View File

@ -1,5 +1,87 @@
import { basename } from '../modules/basename';
console.log('basename', basename);
import { useState } from 'react';
import { Box, Button, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, IconButton } from '@mui/material';
import { Edit, Delete } from 'lucide-react';
import { ModalForm } from './ModalForm';
// 定义工单类型
interface Ticket {
id: number;
title: string;
status: string;
priority: string;
createTime: string;
}
export const App = () => {
return <div className='bg-slate-200 w-full h-full border'>123</div>;
const [tickets, setTickets] = useState<Ticket[]>([]);
const [open, setOpen] = useState(false);
const [selectedTicket, setSelectedTicket] = useState<Ticket | null>(null);
const handleCreate = () => {
setSelectedTicket(null);
setOpen(true);
};
const handleEdit = (ticket: Ticket) => {
setSelectedTicket(ticket);
setOpen(true);
};
const handleDelete = (id: number) => {
setTickets(tickets.filter((ticket) => ticket.id !== id));
};
const handleSave = (data: Ticket) => {
if (selectedTicket) {
setTickets(tickets.map((t) => (t.id === selectedTicket.id ? data : t)));
} else {
setTickets([...tickets, { ...data, id: Date.now() }]);
}
setOpen(false);
};
return (
<Box className='p-4'>
<Box className='mb-4 flex justify-between'>
<h1 className='text-2xl font-bold'></h1>
<Button variant='contained' onClick={handleCreate}>
</Button>
</Box>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{tickets.map((ticket) => (
<TableRow key={ticket.id}>
<TableCell>{ticket.title}</TableCell>
<TableCell>{ticket.status}</TableCell>
<TableCell>{ticket.priority}</TableCell>
<TableCell>{ticket.createTime}</TableCell>
<TableCell>
<IconButton onClick={() => handleEdit(ticket)}>
<Edit className='w-4 h-4' />
</IconButton>
<IconButton onClick={() => handleDelete(ticket.id)}>
<Delete className='w-4 h-4' />
</IconButton>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<ModalForm open={open} onClose={() => setOpen(false)} onSave={handleSave} ticket={selectedTicket} />
</Box>
);
};

121
src/pages/ModalForm.tsx Normal file
View File

@ -0,0 +1,121 @@
import { useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
TextField,
MenuItem,
Box
} from '@mui/material';
interface Ticket {
id: number;
title: string;
status: string;
priority: string;
createTime: string;
}
interface ModalFormProps {
open: boolean;
onClose: () => void;
onSave: (data: Ticket) => void;
ticket: Ticket | null;
}
export const ModalForm = ({ open, onClose, onSave, ticket }: ModalFormProps) => {
const { control, handleSubmit, reset } = useForm<Ticket>({
defaultValues: {
title: '',
status: '待处理',
priority: '中',
createTime: new Date().toLocaleString()
}
});
useEffect(() => {
if (ticket) {
reset(ticket);
} else {
reset({
title: '',
status: '待处理',
priority: '中',
createTime: new Date().toLocaleString()
});
}
}, [ticket, reset]);
const onSubmit = (data: Ticket) => {
onSave(data);
};
return (
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
<DialogTitle>{ticket ? '编辑工单' : '创建工单'}</DialogTitle>
<form onSubmit={handleSubmit(onSubmit)}>
<DialogContent>
<Box className="space-y-4">
<Controller
name="title"
control={control}
rules={{ required: '请输入标题' }}
render={({ field, fieldState }) => (
<TextField
{...field}
label="标题"
fullWidth
error={!!fieldState.error}
helperText={fieldState.error?.message}
/>
)}
/>
<Controller
name="status"
control={control}
render={({ field }) => (
<TextField
{...field}
select
label="状态"
fullWidth
>
<MenuItem value="待处理"></MenuItem>
<MenuItem value="处理中"></MenuItem>
<MenuItem value="已完成"></MenuItem>
</TextField>
)}
/>
<Controller
name="priority"
control={control}
render={({ field }) => (
<TextField
{...field}
select
label="优先级"
fullWidth
>
<MenuItem value="高"></MenuItem>
<MenuItem value="中"></MenuItem>
<MenuItem value="低"></MenuItem>
</TextField>
)}
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={onClose}></Button>
<Button type="submit" variant="contained">
</Button>
</DialogActions>
</form>
</Dialog>
);
};

View File

View File

@ -1,22 +0,0 @@
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": [
"^build"
],
"outputs": [
"dist/**"
]
},
"dev:lib": {
"persistent": true,
"cache": true
},
"build:lib": {
"dependsOn": [
"^build:lib"
]
}
}
}