316 lines
8.0 KiB
JavaScript
316 lines
8.0 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// 模块名称(首字母大写)
|
|
const moduleName = process.argv[2];
|
|
if (!moduleName) {
|
|
console.error('请提供模块名称');
|
|
process.exit(1);
|
|
}
|
|
|
|
// 模块路径
|
|
const modulePath = path.join(__dirname, '../src/pages/System', moduleName);
|
|
|
|
// 创建目录结构
|
|
const directories = [
|
|
'',
|
|
'components',
|
|
'types'
|
|
];
|
|
|
|
// 创建目录
|
|
directories.forEach(dir => {
|
|
const dirPath = path.join(modulePath, dir);
|
|
if (!fs.existsSync(dirPath)) {
|
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
}
|
|
});
|
|
|
|
// 创建基础文件
|
|
const files = {
|
|
// 类型定义
|
|
'types/index.ts': `import type { BaseResponse } from '@/types/base/response';
|
|
import type { BaseQuery } from '@/types/base/query';
|
|
|
|
// 查询参数
|
|
export interface ${moduleName}Query extends BaseQuery {
|
|
// TODO: 添加查询参数
|
|
}
|
|
|
|
// 请求参数
|
|
export interface ${moduleName}Request {
|
|
// TODO: 添加请求参数
|
|
}
|
|
|
|
// 响应类型
|
|
export interface ${moduleName}Response extends BaseResponse {
|
|
// TODO: 添加响应字段
|
|
}
|
|
`,
|
|
|
|
// API 服务
|
|
'service.ts': `import request from '@/utils/request';
|
|
import type { ${moduleName}Response, ${moduleName}Request, ${moduleName}Query } from './types';
|
|
|
|
// 获取列表
|
|
export const getList = (params?: ${moduleName}Query) =>
|
|
request.get<${moduleName}Response[]>('/api/v1/${moduleName.toLowerCase()}s', { params });
|
|
|
|
// 创建
|
|
export const create = (data: ${moduleName}Request) =>
|
|
request.post<${moduleName}Response>('/api/v1/${moduleName.toLowerCase()}s', data);
|
|
|
|
// 更新
|
|
export const update = (id: number, data: ${moduleName}Request) =>
|
|
request.put<${moduleName}Response>(\`/api/v1/${moduleName.toLowerCase()}s/\${id}\`, data);
|
|
|
|
// 删除
|
|
export const remove = (id: number) =>
|
|
request.delete(\`/api/v1/${moduleName.toLowerCase()}s/\${id}\`);
|
|
|
|
// 批量删除
|
|
export const batchRemove = (ids: number[]) =>
|
|
request.post('/api/v1/${moduleName.toLowerCase()}s/batch-delete', { ids });
|
|
|
|
// 导出
|
|
export const exportData = (params?: ${moduleName}Query) =>
|
|
request.get('/api/v1/${moduleName.toLowerCase()}s/export', {
|
|
params,
|
|
responseType: 'blob'
|
|
});
|
|
`,
|
|
|
|
// 主页面组件
|
|
'index.tsx': `import React, { useState } from 'react';
|
|
import { Card, message } from 'antd';
|
|
import type { ${moduleName}Response } from './types';
|
|
import * as service from './service';
|
|
import ${moduleName}Table from './components/${moduleName}Table';
|
|
import ${moduleName}Form from './components/${moduleName}Form';
|
|
|
|
const ${moduleName}: React.FC = () => {
|
|
const [loading, setLoading] = useState(false);
|
|
const [list, setList] = useState<${moduleName}Response[]>([]);
|
|
const [selectedRows, setSelectedRows] = useState<${moduleName}Response[]>([]);
|
|
|
|
const loadData = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const data = await service.getList();
|
|
setList(data);
|
|
} catch (error) {
|
|
console.error('加载数据失败:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleCreate = async (values: ${moduleName}Request) => {
|
|
try {
|
|
await service.create(values);
|
|
message.success('创建成功');
|
|
loadData();
|
|
} catch (error) {
|
|
console.error('创建失败:', error);
|
|
}
|
|
};
|
|
|
|
const handleUpdate = async (id: number, values: ${moduleName}Request) => {
|
|
try {
|
|
await service.update(id, values);
|
|
message.success('更新成功');
|
|
loadData();
|
|
} catch (error) {
|
|
console.error('更新失败:', error);
|
|
}
|
|
};
|
|
|
|
const handleDelete = async (id: number) => {
|
|
try {
|
|
await service.remove(id);
|
|
message.success('删除成功');
|
|
loadData();
|
|
} catch (error) {
|
|
console.error('删除失败:', error);
|
|
}
|
|
};
|
|
|
|
const handleBatchDelete = async () => {
|
|
try {
|
|
await service.batchRemove(selectedRows.map(row => row.id));
|
|
message.success('批量删除成功');
|
|
loadData();
|
|
} catch (error) {
|
|
console.error('批量删除失败:', error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Card title="${moduleName} 管理">
|
|
<${moduleName}Form onSubmit={handleCreate} />
|
|
<${moduleName}Table
|
|
loading={loading}
|
|
dataSource={list}
|
|
selectedRows={selectedRows}
|
|
onDelete={handleDelete}
|
|
onBatchDelete={handleBatchDelete}
|
|
onUpdate={handleUpdate}
|
|
onSelectionChange={setSelectedRows}
|
|
/>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
export default ${moduleName};
|
|
`,
|
|
|
|
// 表格组件
|
|
'components/${moduleName}Table.tsx': `import React from 'react';
|
|
import { Table, Space, Button, Popconfirm } from 'antd';
|
|
import type { ${moduleName}Response } from '../types';
|
|
|
|
interface ${moduleName}TableProps {
|
|
loading: boolean;
|
|
dataSource: ${moduleName}Response[];
|
|
selectedRows: ${moduleName}Response[];
|
|
onDelete: (id: number) => Promise<void>;
|
|
onBatchDelete: () => Promise<void>;
|
|
onUpdate: (id: number, data: ${moduleName}Response) => Promise<void>;
|
|
onSelectionChange: (rows: ${moduleName}Response[]) => void;
|
|
}
|
|
|
|
const ${moduleName}Table: React.FC<${moduleName}TableProps> = ({
|
|
loading,
|
|
dataSource,
|
|
selectedRows,
|
|
onDelete,
|
|
onBatchDelete,
|
|
onUpdate,
|
|
onSelectionChange
|
|
}) => {
|
|
const columns = [
|
|
// TODO: 添加列定义
|
|
{
|
|
title: '操作',
|
|
key: 'action',
|
|
render: (_, record: ${moduleName}Response) => (
|
|
<Space size="middle">
|
|
<Button type="link" onClick={() => onUpdate(record.id, record)}>
|
|
编辑
|
|
</Button>
|
|
<Popconfirm
|
|
title="确定要删除吗?"
|
|
onConfirm={() => onDelete(record.id)}
|
|
>
|
|
<Button type="link" danger>
|
|
删除
|
|
</Button>
|
|
</Popconfirm>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<>
|
|
{selectedRows.length > 0 && (
|
|
<div style={{ marginBottom: 16 }}>
|
|
<Popconfirm
|
|
title="确定要删除选中的项目吗?"
|
|
onConfirm={onBatchDelete}
|
|
>
|
|
<Button type="primary" danger>
|
|
批量删除
|
|
</Button>
|
|
</Popconfirm>
|
|
</div>
|
|
)}
|
|
<Table
|
|
rowKey="id"
|
|
loading={loading}
|
|
dataSource={dataSource}
|
|
columns={columns}
|
|
rowSelection={{
|
|
selectedRowKeys: selectedRows.map(row => row.id),
|
|
onChange: (_, rows) => onSelectionChange(rows),
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ${moduleName}Table;
|
|
`,
|
|
|
|
// 表单组件
|
|
'components/${moduleName}Form.tsx': `import React from 'react';
|
|
import { Form, Input, Button } from 'antd';
|
|
import type { ${moduleName}Request } from '../types';
|
|
|
|
interface ${moduleName}FormProps {
|
|
initialValues?: Partial<${moduleName}Request>;
|
|
onSubmit: (values: ${moduleName}Request) => Promise<void>;
|
|
}
|
|
|
|
const ${moduleName}Form: React.FC<${moduleName}FormProps> = ({
|
|
initialValues,
|
|
onSubmit
|
|
}) => {
|
|
const [form] = Form.useForm();
|
|
|
|
const handleSubmit = async () => {
|
|
try {
|
|
const values = await form.validateFields();
|
|
await onSubmit(values);
|
|
form.resetFields();
|
|
} catch (error) {
|
|
console.error('表单提交失败:', error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Form
|
|
form={form}
|
|
layout="inline"
|
|
initialValues={initialValues}
|
|
style={{ marginBottom: 16 }}
|
|
>
|
|
{/* TODO: 添加表单项 */}
|
|
<Form.Item>
|
|
<Button type="primary" onClick={handleSubmit}>
|
|
提交
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
);
|
|
};
|
|
|
|
export default ${moduleName}Form;
|
|
`
|
|
};
|
|
|
|
// 创建文件
|
|
Object.entries(files).forEach(([filename, content]) => {
|
|
const filePath = path.join(modulePath, filename);
|
|
if (!fs.existsSync(filePath)) {
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
fs.writeFileSync(filePath, content);
|
|
}
|
|
});
|
|
|
|
console.log(`模块 ${moduleName} 创建成功!`);
|
|
console.log(`
|
|
请确保在路由配置文件 src/router/index.tsx 中添加以下路由:
|
|
|
|
{
|
|
path: 'system/${moduleName.toLowerCase()}',
|
|
element: (
|
|
<Suspense fallback={<LoadingComponent />}>
|
|
<${moduleName} />
|
|
</Suspense>
|
|
)
|
|
}
|
|
|
|
并添加懒加载导入:
|
|
const ${moduleName} = lazy(() => import('../pages/System/${moduleName}'));
|
|
`);
|