deploy-ease-platform/frontend/scripts/generate-page.ts
2024-12-03 18:17:47 +08:00

272 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);