fix: 前端构建修复+后端静态托管+Docker部署
This commit is contained in:
@@ -10,7 +10,6 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Select,
|
Select,
|
||||||
DatePicker,
|
DatePicker,
|
||||||
InputNumber,
|
|
||||||
Typography,
|
Typography,
|
||||||
Segmented,
|
Segmented,
|
||||||
Table,
|
Table,
|
||||||
@@ -30,7 +29,6 @@ import {
|
|||||||
import { taskApi, projectApi, workerApi } from '@/api';
|
import { taskApi, projectApi, workerApi } from '@/api';
|
||||||
import type { Task, TaskCreate, TaskStatus, Project, Worker } from '@/types';
|
import type { Task, TaskCreate, TaskStatus, Project, Worker } from '@/types';
|
||||||
import { TaskStatusTag, PriorityTag, taskStatusConfig, taskStatusList } from '@/components/constants';
|
import { TaskStatusTag, PriorityTag, taskStatusConfig, taskStatusList } from '@/components/constants';
|
||||||
import TaskDetailModal from '@/pages/TaskDetail';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
@@ -49,14 +47,13 @@ export default function Tasks() {
|
|||||||
const [workers, setWorkers] = useState<Worker[]>([]);
|
const [workers, setWorkers] = useState<Worker[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [viewMode, setViewMode] = useState<string>('kanban');
|
const [viewMode, setViewMode] = useState<string>('kanban');
|
||||||
const [filterProject, setFilterProject] = useState<string | undefined>();
|
const [filterProject, setFilterProject] = useState<number | undefined>();
|
||||||
const [filterStatus, setFilterStatus] = useState<TaskStatus | undefined>();
|
const [filterStatus, setFilterStatus] = useState<TaskStatus | undefined>();
|
||||||
|
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
const [editing, setEditing] = useState<Task | null>(null);
|
const [editing, setEditing] = useState<Task | null>(null);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
const [detailTask, setDetailTask] = useState<Task | null>(null);
|
|
||||||
|
|
||||||
const loadData = useCallback(() => {
|
const loadData = useCallback(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -81,7 +78,7 @@ export default function Tasks() {
|
|||||||
const openCreate = () => {
|
const openCreate = () => {
|
||||||
setEditing(null);
|
setEditing(null);
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.setFieldsValue({ priority: 'medium', max_retries: 3 });
|
form.setFieldsValue({ priority: 'medium' });
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +88,6 @@ export default function Tasks() {
|
|||||||
title: task.title,
|
title: task.title,
|
||||||
description: task.description,
|
description: task.description,
|
||||||
priority: task.priority,
|
priority: task.priority,
|
||||||
max_retries: task.max_retries,
|
|
||||||
});
|
});
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
};
|
};
|
||||||
@@ -105,7 +101,6 @@ export default function Tasks() {
|
|||||||
title: values.title,
|
title: values.title,
|
||||||
description: values.description,
|
description: values.description,
|
||||||
priority: values.priority,
|
priority: values.priority,
|
||||||
max_retries: values.max_retries,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (values.due_date) {
|
if (values.due_date) {
|
||||||
@@ -114,7 +109,8 @@ export default function Tasks() {
|
|||||||
|
|
||||||
if (values.input_data) {
|
if (values.input_data) {
|
||||||
try {
|
try {
|
||||||
payload.input_data = JSON.parse(values.input_data);
|
JSON.parse(values.input_data); // validate JSON format
|
||||||
|
payload.input_data = values.input_data;
|
||||||
} catch {
|
} catch {
|
||||||
message.error('输入数据 JSON 格式错误');
|
message.error('输入数据 JSON 格式错误');
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
@@ -144,7 +140,7 @@ export default function Tasks() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (id: string) => {
|
const handleDelete = async (id: number) => {
|
||||||
try {
|
try {
|
||||||
await taskApi.delete(id);
|
await taskApi.delete(id);
|
||||||
message.success('删除成功');
|
message.success('删除成功');
|
||||||
@@ -206,7 +202,6 @@ export default function Tasks() {
|
|||||||
key={task.id}
|
key={task.id}
|
||||||
size="small"
|
size="small"
|
||||||
className="kanban-card"
|
className="kanban-card"
|
||||||
onClick={() => setDetailTask(task)}
|
|
||||||
style={{ marginBottom: 8 }}
|
style={{ marginBottom: 8 }}
|
||||||
>
|
>
|
||||||
<div style={{ fontWeight: 600, marginBottom: 4 }}>
|
<div style={{ fontWeight: 600, marginBottom: 4 }}>
|
||||||
@@ -214,9 +209,6 @@ export default function Tasks() {
|
|||||||
</div>
|
</div>
|
||||||
<Space size={4}>
|
<Space size={4}>
|
||||||
<PriorityTag priority={task.priority} />
|
<PriorityTag priority={task.priority} />
|
||||||
{task.cost > 0 && (
|
|
||||||
<Tag color="orange">¥{task.cost.toFixed(2)}</Tag>
|
|
||||||
)}
|
|
||||||
</Space>
|
</Space>
|
||||||
{task.description && (
|
{task.description && (
|
||||||
<div
|
<div
|
||||||
@@ -249,9 +241,7 @@ export default function Tasks() {
|
|||||||
title: '任务名称',
|
title: '任务名称',
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
key: 'title',
|
key: 'title',
|
||||||
render: (text: string, record: Task) => (
|
render: (text: string) => text,
|
||||||
<a onClick={() => setDetailTask(record)}>{text}</a>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
@@ -265,12 +255,6 @@ export default function Tasks() {
|
|||||||
key: 'priority',
|
key: 'priority',
|
||||||
render: (p: Task['priority']) => <PriorityTag priority={p} />,
|
render: (p: Task['priority']) => <PriorityTag priority={p} />,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '花费',
|
|
||||||
dataIndex: 'cost',
|
|
||||||
key: 'cost',
|
|
||||||
render: (v: number) => (v > 0 ? `¥${v.toFixed(2)}` : '-'),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
@@ -283,13 +267,6 @@ export default function Tasks() {
|
|||||||
width: 280,
|
width: 280,
|
||||||
render: (_: unknown, record: Task) => (
|
render: (_: unknown, record: Task) => (
|
||||||
<Space>
|
<Space>
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
onClick={() => setDetailTask(record)}
|
|
||||||
>
|
|
||||||
详情
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -434,9 +411,6 @@ export default function Tasks() {
|
|||||||
<Form.Item name="priority" label="优先级">
|
<Form.Item name="priority" label="优先级">
|
||||||
<Select options={priorities} />
|
<Select options={priorities} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="max_retries" label="最大重试次数">
|
|
||||||
<InputNumber min={0} max={10} style={{ width: '100%' }} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name="due_date" label="截止时间">
|
<Form.Item name="due_date" label="截止时间">
|
||||||
<DatePicker style={{ width: '100%' }} />
|
<DatePicker style={{ width: '100%' }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -449,16 +423,6 @@ export default function Tasks() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
{/* Detail Modal */}
|
|
||||||
<TaskDetailModal
|
|
||||||
task={detailTask}
|
|
||||||
workers={workers}
|
|
||||||
onClose={() => setDetailTask(null)}
|
|
||||||
onUpdated={() => {
|
|
||||||
loadData();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user