deploy-ease-platform/frontend/scripts/create-module.js
2024-12-02 14:10:09 +08:00

311 lines
7.4 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',
'hooks',
'styles'
];
// 创建目录
directories.forEach(dir => {
const dirPath = path.join(modulePath, dir);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
});
// 创建基础文件
const files = {
// 类型定义
'types.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';
import type { Page } from '@/types/base/page';
const BASE_URL = '/api/v1/${moduleName.toLowerCase()}';
// 获取列表(分页)
export const get${moduleName}s = async (params?: ${moduleName}Query) =>
request.get<Page<${moduleName}Response>>(\`\${BASE_URL}/page\`, { params });
// 创建
export const create${moduleName} = async (data: ${moduleName}Request) =>
request.post<${moduleName}Response>(BASE_URL, data);
// 更新
export const update${moduleName} = async (id: number, data: ${moduleName}Request) =>
request.put<${moduleName}Response>(\`\${BASE_URL}/\${id}\`, data);
// 删除
export const delete${moduleName} = async (id: number) =>
request.delete(\`\${BASE_URL}/\${id}\`);
`,
// 主页面组件
'index.tsx': `import React from 'react';
import { Card } from 'antd';
import type { ${moduleName}Response } from './types';
import { use${moduleName}Data } from './hooks/use${moduleName}Data';
import ${moduleName}Table from './components/${moduleName}Table';
import ${moduleName}Form from './components/${moduleName}Form';
import styles from './styles/index.module.css';
const ${moduleName}: React.FC = () => {
const {
list,
pagination,
loading,
selectedRows,
handleCreate,
handleUpdate,
handleDelete,
handleSelectionChange
} = use${moduleName}Data();
return (
<Card title="${moduleName} 管理" className={styles.container}>
<${moduleName}Form onSubmit={handleCreate} />
<${moduleName}Table
loading={loading}
dataSource={list}
pagination={pagination}
selectedRows={selectedRows}
onDelete={handleDelete}
onUpdate={handleUpdate}
onSelectionChange={handleSelectionChange}
/>
</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';
import styles from '../styles/table.module.css';
interface ${moduleName}TableProps {
loading: boolean;
dataSource: ${moduleName}Response[];
pagination: {
current: number;
pageSize: number;
total: number;
};
selectedRows: ${moduleName}Response[];
onDelete: (id: number) => Promise<void>;
onUpdate: (id: number, data: Partial<${moduleName}Response>) => Promise<void>;
onSelectionChange: (selectedRows: ${moduleName}Response[]) => void;
}
const ${moduleName}Table: React.FC<${moduleName}TableProps> = ({
loading,
dataSource,
pagination,
selectedRows,
onDelete,
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 (
<Table
className={styles.table}
rowKey="id"
loading={loading}
dataSource={dataSource}
columns={columns}
pagination={pagination}
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';
import styles from '../styles/form.module.css';
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 () => {
const values = await form.validateFields();
await onSubmit(values);
form.resetFields();
};
return (
<Form
form={form}
layout="inline"
initialValues={initialValues}
className={styles.form}
>
{/* TODO: 添加表单项 */}
<Form.Item>
<Button type="primary" onClick={handleSubmit}>
提交
</Button>
</Form.Item>
</Form>
);
};
export default ${moduleName}Form;
`,
// 自定义 Hook
'hooks/use${moduleName}Data.ts': `import { useState, useCallback } from 'react';
import type { ${moduleName}Response, ${moduleName}Request } from '../types';
import { useTableData } from '@/hooks/useTableData';
import * as service from '../service';
export const use${moduleName}Data = () => {
const [selectedRows, setSelectedRows] = useState<${moduleName}Response[]>([]);
const {
list,
pagination,
loading,
loadData,
handleCreate,
handleUpdate,
handleDelete
} = useTableData<${moduleName}Response>({
service: {
baseUrl: '/api/v1/${moduleName.toLowerCase()}'
}
});
const handleSelectionChange = useCallback((rows: ${moduleName}Response[]) => {
setSelectedRows(rows);
}, []);
return {
list,
pagination,
loading,
selectedRows,
handleCreate,
handleUpdate,
handleDelete,
handleSelectionChange
};
};
`,
// 样式文件
'styles/index.module.css': `.container {
padding: 24px;
}
`,
'styles/table.module.css': `.table {
margin-top: 16px;
}
`,
'styles/form.module.css': `.form {
margin-bottom: 16px;
}
`
};
// 创建文件
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}'));
`);