@yorha2b-lab/autodev 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,8 @@
7
7
 
8
8
  基于视觉大模型的前端(Umi+Antd)全自动 CRUD 代码生成器 🚀
9
9
 
10
- ![Demo](https://via.placeholder.com/800x400?text=Coming+Soon)
10
+ <video src="https://github.com/user-attachments/assets/6d42fce1-c815-482b-8c6a-4a3b9415ba47.mp4" controls="controls" muted="muted" style="max-width: 100%; display: block; margin: 20px auto;">
11
+ </video>
11
12
 
12
13
  拒绝重复劳动!为什么你需要 Auto CRUD Copilot?
13
14
  告别手写 Table/Form:截图即代码,提升你的开发效率,告别烦人的复制粘贴。
@@ -170,4 +171,14 @@ A: 工具本身开源免费,但调用的 AI 模型(如 GPT-4v, Qwen-VL)可
170
171
 
171
172
  ---
172
173
 
173
- ⭐ 如果这个项目对你有帮助,请给个Star支持一下!
174
+ ## ⚖️ Disclaimer
175
+
176
+ Auto CRUD Copilot is a **fan-made, non-commercial, open-source tool**.
177
+
178
+ - The themes, names (YoRHa, 2B, etc.), and catchphrases included in this project are inspired by **NieR:Automata**, which is a trademark and copyright of **Square Enix Co., Ltd. / PlatinumGames Inc.**
179
+ - This project is not affiliated with, endorsed by, or representative of Square Enix in any way.
180
+ - Please support the original masterpiece: [NieR:Automata Official Site](https://nierautomata.square-enix-games.com/).
181
+
182
+ **Glory to Mankind.**
183
+
184
+ ⭐ 如果这个项目对你有帮助,请给个Star支持一下!
package/bin/autodev.js CHANGED
@@ -14,7 +14,7 @@ const localEnv = path.resolve(process.cwd(), '.env')
14
14
  const pkgEnv = path.resolve(__dirname, '../.env')
15
15
 
16
16
  require("dotenv").config({
17
- path: fs.existsSync(localEnv) ? localEnv : pkgEnv
17
+ path: fs.existsSync(localEnv) ? localEnv : pkgEnv
18
18
  })
19
19
 
20
20
  const { program } = require('commander')
@@ -26,6 +26,18 @@ program.version('1.0.0').description('AI驱动的前端CRUD代码生成器')
26
26
 
27
27
  program.option('-t, --template <type>', '指定前端框架模板', 'react')
28
28
 
29
+ program
30
+ .command('init')
31
+ .description('在当前目录初始化 .env 和 config.js 配置文件')
32
+ .action(() => {
33
+ const tplConfig = path.resolve(__dirname, '../config.js')
34
+ const tplEnv = path.resolve(__dirname, '../.env.example')
35
+ fs.copyFileSync(tplConfig, path.join(process.cwd(), 'config.js'))
36
+ fs.copyFileSync(tplEnv, path.join(process.cwd(), '.env'))
37
+ console.log('✅ 已生成 config.js')
38
+ console.log('✅ 已生成 .env')
39
+ })
40
+
29
41
  program
30
42
  .command('watch:page')
31
43
  .description('监听截图,自动生成完整的增删改查页面')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yorha2b-lab/autodev",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "基于视觉大模型的前端(Umi+Antd)全自动 CRUD 代码生成器",
5
5
  "bin": {
6
6
  "autodev": "bin/autodev.js"
@@ -1,10 +1,13 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
  const chokidar = require('chokidar')
4
- const config = require('../../config.js')
4
+ const { getConfig } = require('../utils/utils.js')
5
5
  const { alignSwaggerFields } = require('../services/llm.js')
6
6
 
7
7
  const watchApi = () => {
8
+
9
+ const config = getConfig()
10
+
8
11
  const watcher = chokidar.watch('./swagger', {
9
12
  persistent: true,
10
13
  ignored: /(^|[\/\\])\../,
@@ -3,15 +3,15 @@ const ora = require('ora')
3
3
  const path = require('path')
4
4
  const chokidar = require('chokidar')
5
5
  const Handlebars = require('handlebars')
6
- const config = require('../../config.js')
7
6
  const pagePrompt = require('../prompts/watch-page.js')
8
7
  const { createTaskQueue } = require('../core/task-queue')
9
8
  const stringify = require('json-stringify-pretty-compact')
10
9
  const { recognizePage, generateMock } = require('../services/llm.js')
11
- const { copyHooks, copyComponents, getExistingMenus } = require('../utils/utils.js')
10
+ const { getConfig, copyHooks, copyComponents, getExistingMenus } = require('../utils/utils.js')
12
11
 
13
12
  const watchPage = options => {
14
13
 
14
+ const config = getConfig()
15
15
  const compilerPath = path.join(__dirname, `../core/${options.template}-compiler.js`)
16
16
 
17
17
  if (!fs.existsSync(compilerPath)) {
@@ -1,5 +1,5 @@
1
1
  module.exports = (columns, fileName) => `
2
2
  根据这些字段生成一个简单的get接口mock数据: ${JSON.stringify(columns)},
3
3
  格式如下:
4
- '/api/${fileName}': {data:模块对象列表},
4
+ 'POST /api/${fileName}': {data:模块对象列表},
5
5
  `
@@ -1,11 +1,12 @@
1
1
  const JSON5 = require('json5')
2
2
  const sharp = require('sharp')
3
3
  const OpenAI = require('openai')
4
- const config = require('../../config.js')
5
4
  const mockPrompt = require('../prompts/mock.js')
5
+ const { getConfig } = require('../utils/utils.js')
6
6
  const apiPrompt = require('../prompts/watch-api.js')
7
7
  const { UI_DESIGNER, API_DESIGNER, MOCK_DESIGNER } = require('../prompts/system.js')
8
8
 
9
+ const config = getConfig()
9
10
  const openai = new OpenAI({ apiKey: process.env.API_KEY, baseURL: process.env.BASE_URL })
10
11
 
11
12
  const askAI = async (model, messages, retryCount = 0) => {
@@ -1,7 +1,16 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
- const config = require('../../config.js')
4
3
 
4
+ const getConfig = () => {
5
+ const localConfigPath = path.join(process.cwd(), 'config.js')
6
+ const defaultConfigPath = path.resolve(__dirname, '../../config.js')
7
+ let config = require(defaultConfigPath)
8
+ if (fs.existsSync(localConfigPath)) {
9
+ const userConfig = require(localConfigPath)
10
+ config = { ...config, ...userConfig }
11
+ }
12
+ return config
13
+ }
5
14
 
6
15
  /**
7
16
  * 大模型输出的标准 JSON 无法携带 render: (text) => <Tag> 等箭头函数。
@@ -20,21 +29,7 @@ const cleanCode = str => {
20
29
  .trim() + '\n'
21
30
  }
22
31
 
23
- const copyHooks = options => {
24
- const targetDir = path.join(process.cwd(), config.hooksDir)
25
- if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
26
- const hookDir = path.join(__dirname, `../../templates/${options.template}/hooks`)
27
- fs.readdirSync(hookDir).forEach(file => fs.copyFileSync(path.join(hookDir, file), path.join(targetDir, file)))
28
- }
29
-
30
- const copyComponents = options => {
31
- const targetDir = path.join(process.cwd(), config.componentsDir)
32
- if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
33
- const componentsDir = path.join(__dirname, `../../templates/${options.template}/components`)
34
- fs.readdirSync(componentsDir).forEach(file => fs.copyFileSync(path.join(componentsDir, file), path.join(targetDir, file)))
35
- }
36
-
37
- const getExistingMenus = (dir = config.pagesDir) => {
32
+ const getExistingMenus = (dir = 'src/pages') => {
38
33
  const pagesDir = path.join(process.cwd(), dir)
39
34
  if (!fs.existsSync(pagesDir)) return []
40
35
  return fs.readdirSync(pagesDir)
@@ -66,4 +61,18 @@ const generateSmartImports = (codeStr, hasTabs) => {
66
61
  return imports.filter(Boolean).join('\n')
67
62
  }
68
63
 
69
- module.exports = { copyHooks, cleanCode, copyComponents, getExistingMenus, generateSmartImports }
64
+ const copyHooks = (options, hooksDir = 'src/hooks') => {
65
+ const targetDir = path.join(process.cwd(), hooksDir)
66
+ if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
67
+ const hookDir = path.join(__dirname, `../../templates/${options.template}/hooks`)
68
+ fs.readdirSync(hookDir).forEach(file => fs.copyFileSync(path.join(hookDir, file), path.join(targetDir, file)))
69
+ }
70
+
71
+ const copyComponents = (options, componentsDir = 'src/components') => {
72
+ const targetDir = path.join(process.cwd(), componentsDir)
73
+ if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
74
+ const componentsDirectory = path.join(__dirname, `../../templates/${options.template}/components`)
75
+ fs.readdirSync(componentsDirectory).forEach(file => fs.copyFileSync(path.join(componentsDirectory, file), path.join(targetDir, file)))
76
+ }
77
+
78
+ module.exports = { getConfig, copyHooks, cleanCode, copyComponents, getExistingMenus, generateSmartImports }
@@ -3,7 +3,7 @@ import { formNode } from './index'
3
3
 
4
4
  export const MyBaseForm = ({ item, form }) => {
5
5
 
6
- const renderFormContent = item => {
6
+ const renderFormContent = ({ item }) => {
7
7
 
8
8
  if (!item.name) {
9
9
  return typeof item.render === 'function' ? item.render(item) : (item.value ?? '-')