Express 是一个基于 Node.js 的 轻量级 Web 服务框架
让你快速启动一个本地 HTTP 服务(比如 POST/GET 接口),响应浏览器或其他前端发来的请求。
①下载wxpress
npm install express
下不了就-D -W
根目录下就是src同目录,创建一个js 或者cjs的node脚本文件
crud-generator-server.cjs
②执行脚本:node crud-generator-server.cjs
F:\vue3\ZRKJvue3\zrkj-aigov-city-web>node crud-generator-server.cjs
✅ CRUD 页面生成服务已启动:http://localhost:3001
// crud-generator-server.js
const fs = require('fs');
const path = require('path');
const express = require('express');
const app = express();
app.use(express.json());
app.post('/generate-page', (req, res) => {
const { tableName } = req.body;
if (!tableName) {
return res.status(400).json({ message: 'Missing tableName' });
}
const targetDir = path.resolve(__dirname, 'src/views/systemTools/addPages');
const filePath = path.join(targetDir, `${tableName}.vue`);
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
const template = `
<template>
<div class="common-warp-pages">
<BasicTable @register="registerTable">
<template #toolbar>
<a-button type="primary" @click="handleAdd('add')">新增</a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
{ label: '查看', onClick: () => handleView(record) },
{ label: '修改', onClick: () => openAddDrawer(true, { isUpdate: true, record, formSchema }) },
{ label: '删除', onClick: () => handleDelete(record.id) }
]" />
</template>
</template>
</BasicTable>
<AddDrawer @register="registerDrawer" @success="handleSuccess" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { BasicTable, useTable, BasicColumn } from '@/components/Table';
import { FormSchema } from '@/components/Form/src/types/form';
import { TableAction } from '@/components/Table';
import { useDrawer } from '@/components/Drawer';
import AddDrawer from '@/views/systemTools/components/AddDrawer.vue';
const [registerDrawer, { openDrawer: openAddDrawer }] = useDrawer();
interface RowItem {
id: number;
name: string;
age: number;
address: string;
userId?: number;
status?: string;
}
const allData = ref<RowItem[]>([
{ id: 1, name: '张三', age: 18, address: '北京', userId: 1, status: '0' },
{ id: 2, name: '李四', age: 25, address: '上海', userId: 2, status: '1' },
{ id: 3, name: '王五', age: 30, address: '广州', userId: 3, status: '0' },
]);
const filteredData = ref<RowItem[]>([...allData.value]);
const searchSchemas: FormSchema[] = [
{ field: 'name', label: '姓名', component: 'Input' },
];
const formSchema: FormSchema[] = [
{ field: 'content', label: '描述', component: 'InputTextArea' },
{ field: 'name', label: '姓名', component: 'Input', required: true },
{ field: 'age', label: '年龄', component: 'InputNumber', required: true },
{ field: 'address', label: '地址', component: 'Input', required: true },
];
const columns: BasicColumn[] = [
{ title: '姓名', dataIndex: 'name' },
{ title: '年龄', dataIndex: 'age' },
{ title: '地址', dataIndex: 'address' },
];
const [registerTable] = useTable({
columns,
dataSource: filteredData,
useSearchForm: true,
formConfig: {
labelWidth: 100,
schemas: searchSchemas,
},
rowKey: 'id',
showIndexColumn: true,
actionColumn: {
width: 150,
title: '操作',
dataIndex: 'action',
fixed: 'right',
align: 'center',
},
});
const handleAdd = () => {
openAddDrawer(true, { isUpdate: false, formSchema });
};
const handleView = (record: RowItem) => {
openAddDrawer(true, { isUpdate: true, record });
};
const handleDelete = (id: number) => {
allData.value = allData.value.filter((item) => item.id !== id);
handleSearch();
};
const handleSearch = () => {
filteredData.value = [...allData.value];
};
const handleSuccess = (val: RowItem) => {
const idx = allData.value.findIndex((i) => i.id === val.id);
if (idx > -1) {
allData.value[idx] = { ...val };
} else {
const newId = allData.value.length ? Math.max(...allData.value.map((i) => i.id)) + 1 : 1;
allData.value.unshift({ ...val, id: newId });
}
handleSearch();
};
</script>
`;
fs.writeFileSync(filePath, template.trim(), 'utf-8');
res.json({ message: `${tableName}.vue 页面已生成` });
});
app.listen(3001, () => {
console.log('✅ CRUD 页面生成服务已启动:http://localhost:3001');
});
③跨域后端cors这里自己起的太麻烦了就proxy代理替换一下
在config.ts文件里面
proxy: {
'/generate-page': {
target: 'http://localhost:3001',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/generate-page/, '/generate-page'),
},
}
④生成页面 一个页面按钮点击方法用fetch
// 生成页面
const pageCreate = async () => {
try {
const res = await fetch('/generate-page', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tableName: 'DemoTable3' }),
});
if (!res.ok) {
throw new Error(`请求失败,状态码:${res.status}`);
}
createMessage.success('页面生成成功!');
} catch (error) {
console.error(error);
createMessage.error('页面生成失败,请稍后重试');
}
};
效果出来然后需要自己去对应文件路径配置路由
⑤最终页面效果
还有很多方面需要完善只是简单的实现了一下。