272 lines
7.4 KiB
TypeScript
272 lines
7.4 KiB
TypeScript
import fs from 'fs';
|
||
import path from 'path';
|
||
|
||
interface GenerateOptions {
|
||
name: string; // 模块名称,如 user, role 等
|
||
description: string; // 中文描述,如 "用户管理"
|
||
baseUrl: string; // API基础路径,如 "/api/v1/users"
|
||
}
|
||
|
||
// 生成 types.ts
|
||
function generateTypes(options: GenerateOptions): string {
|
||
const { name } = options;
|
||
const typeName = name.charAt(0).toUpperCase() + name.slice(1);
|
||
|
||
return `import { BaseResponse, BaseQuery } from '@/types/base';
|
||
|
||
export interface ${typeName}Response extends BaseResponse {
|
||
name: string;
|
||
// TODO: 添加其他字段
|
||
}
|
||
|
||
export interface ${typeName}Query extends BaseQuery {
|
||
name?: string;
|
||
// TODO: 添加其他查询字段
|
||
}
|
||
|
||
export interface ${typeName}Request {
|
||
name: string;
|
||
// TODO: 添加其他请求字段
|
||
}
|
||
`;
|
||
}
|
||
|
||
// 生成 service.ts
|
||
function generateService(options: GenerateOptions): string {
|
||
const { name, baseUrl } = options;
|
||
const typeName = name.charAt(0).toUpperCase() + name.slice(1);
|
||
|
||
return `import { http } from '@/utils/http';
|
||
import type { ${typeName}Response, ${typeName}Query, ${typeName}Request } from './types';
|
||
|
||
// 获取列表
|
||
export const getList = (params?: ${typeName}Query) =>
|
||
http.get<${typeName}Response[]>('${baseUrl}', { params });
|
||
|
||
// 获取详情
|
||
export const getDetail = (id: number) =>
|
||
http.get<${typeName}Response>(\`${baseUrl}/\${id}\`);
|
||
|
||
// 创建
|
||
export const create = (data: ${typeName}Request) =>
|
||
http.post<${typeName}Response>('${baseUrl}', data);
|
||
|
||
// 更新
|
||
export const update = (id: number, data: ${typeName}Request) =>
|
||
http.put<${typeName}Response>(\`${baseUrl}/\${id}\`, data);
|
||
|
||
// 删除
|
||
export const remove = (id: number) =>
|
||
http.delete(\`${baseUrl}/\${id}\`);
|
||
|
||
// 批量删除
|
||
export const batchRemove = (ids: number[]) =>
|
||
http.post('${baseUrl}/batch-delete', { ids });
|
||
`;
|
||
}
|
||
|
||
// 生成页面组件
|
||
function generatePage(options: GenerateOptions): string {
|
||
const { name, description } = options;
|
||
const typeName = name.charAt(0).toUpperCase() + name.slice(1);
|
||
|
||
return `import { useState } from 'react';
|
||
import { Card, Table, Button, Space, Modal, message, Form, Input } from 'antd';
|
||
import type { ${typeName}Response, ${typeName}Query, ${typeName}Request } from './types';
|
||
import * as service from './service';
|
||
import { useRequest } from 'ahooks';
|
||
|
||
const ${typeName}Page = () => {
|
||
const [query, setQuery] = useState<${typeName}Query>({});
|
||
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
||
const [editModalVisible, setEditModalVisible] = useState(false);
|
||
const [editingRecord, setEditingRecord] = useState<${typeName}Response | null>(null);
|
||
const [form] = Form.useForm();
|
||
|
||
// 获取列表数据
|
||
const { data, loading, refresh } = useRequest(() => service.getList(query), {
|
||
refreshDeps: [query]
|
||
});
|
||
|
||
// 删除操作
|
||
const handleDelete = async (id: number) => {
|
||
Modal.confirm({
|
||
title: '确认删除',
|
||
content: '确定要删除这条记录吗?',
|
||
onOk: async () => {
|
||
try {
|
||
await service.remove(id);
|
||
message.success('删除成功');
|
||
refresh();
|
||
} catch (error) {
|
||
message.error('删除失败');
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
// 批量删除
|
||
const handleBatchDelete = () => {
|
||
if (!selectedRowKeys.length) {
|
||
message.warning('请选择要删除的记录');
|
||
return;
|
||
}
|
||
Modal.confirm({
|
||
title: '确认删除',
|
||
content: \`确定要删除这\${selectedRowKeys.length}条记录吗?\`,
|
||
onOk: async () => {
|
||
try {
|
||
await service.batchRemove(selectedRowKeys);
|
||
message.success('删除成功');
|
||
setSelectedRowKeys([]);
|
||
refresh();
|
||
} catch (error) {
|
||
message.error('删除失败');
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
// 打开编辑弹窗
|
||
const handleEdit = async (id: number) => {
|
||
try {
|
||
const detail = await service.getDetail(id);
|
||
setEditingRecord(detail);
|
||
form.setFieldsValue(detail);
|
||
setEditModalVisible(true);
|
||
} catch (error) {
|
||
message.error('获取详情失败');
|
||
}
|
||
};
|
||
|
||
// 打开新增弹窗
|
||
const handleAdd = () => {
|
||
setEditingRecord(null);
|
||
form.resetFields();
|
||
setEditModalVisible(true);
|
||
};
|
||
|
||
// 保存表单
|
||
const handleSave = async () => {
|
||
try {
|
||
const values = await form.validateFields();
|
||
if (editingRecord) {
|
||
await service.update(editingRecord.id, values);
|
||
message.success('更新成功');
|
||
} else {
|
||
await service.create(values);
|
||
message.success('创建成功');
|
||
}
|
||
setEditModalVisible(false);
|
||
refresh();
|
||
} catch (error) {
|
||
message.error('操作失败');
|
||
}
|
||
};
|
||
|
||
const columns = [
|
||
{
|
||
title: '名称',
|
||
dataIndex: 'name',
|
||
key: 'name',
|
||
},
|
||
{
|
||
title: '创建时间',
|
||
dataIndex: 'createTime',
|
||
key: 'createTime',
|
||
},
|
||
{
|
||
title: '操作',
|
||
key: 'action',
|
||
render: (_, record: ${typeName}Response) => (
|
||
<Space>
|
||
<Button type="link" onClick={() => handleEdit(record.id)}>编辑</Button>
|
||
<Button type="link" danger onClick={() => handleDelete(record.id)}>删除</Button>
|
||
</Space>
|
||
),
|
||
},
|
||
];
|
||
|
||
return (
|
||
<>
|
||
<Card title="${description}" extra={
|
||
<Space>
|
||
<Button type="primary" onClick={handleAdd}>新增</Button>
|
||
<Button danger onClick={handleBatchDelete}>批量删除</Button>
|
||
</Space>
|
||
}>
|
||
<Form layout="inline" style={{ marginBottom: 16 }}>
|
||
<Form.Item label="名称" name="name">
|
||
<Input placeholder="请输入名称"
|
||
onChange={e => setQuery(prev => ({ ...prev, name: e.target.value }))}
|
||
/>
|
||
</Form.Item>
|
||
</Form>
|
||
<Table
|
||
rowKey="id"
|
||
columns={columns}
|
||
dataSource={data}
|
||
loading={loading}
|
||
rowSelection={{
|
||
selectedRowKeys,
|
||
onChange: (keys) => setSelectedRowKeys(keys as number[]),
|
||
}}
|
||
/>
|
||
</Card>
|
||
|
||
<Modal
|
||
title={editingRecord ? '编辑' : '新增'}
|
||
open={editModalVisible}
|
||
onOk={handleSave}
|
||
onCancel={() => setEditModalVisible(false)}
|
||
>
|
||
<Form form={form} layout="vertical">
|
||
<Form.Item
|
||
label="名称"
|
||
name="name"
|
||
rules={[{ required: true, message: '请输入名称' }]}
|
||
>
|
||
<Input placeholder="请输入名称" />
|
||
</Form.Item>
|
||
{/* TODO: 添加其他表单项 */}
|
||
</Form>
|
||
</Modal>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default ${typeName}Page;
|
||
`;
|
||
}
|
||
|
||
// 生成文件
|
||
function generateFiles(options: GenerateOptions) {
|
||
const { name } = options;
|
||
const basePath = path.join(process.cwd(), 'src/pages', name);
|
||
|
||
// 创建目录
|
||
if (!fs.existsSync(basePath)) {
|
||
fs.mkdirSync(basePath, { recursive: true });
|
||
}
|
||
|
||
// 生成文件
|
||
fs.writeFileSync(path.join(basePath, 'types.ts'), generateTypes(options));
|
||
fs.writeFileSync(path.join(basePath, 'service.ts'), generateService(options));
|
||
fs.writeFileSync(path.join(basePath, 'index.tsx'), generatePage(options));
|
||
|
||
console.log(`Successfully generated files for module "${name}" in ${basePath}`);
|
||
}
|
||
|
||
// 使用示例
|
||
const options: GenerateOptions = {
|
||
name: process.argv[2],
|
||
description: process.argv[3] || '管理',
|
||
baseUrl: process.argv[4] || `/api/v1/${process.argv[2]}`,
|
||
};
|
||
|
||
if (!options.name) {
|
||
console.error('Please provide a module name!');
|
||
process.exit(1);
|
||
}
|
||
|
||
generateFiles(options);
|