-
{{"{{"}}type==='create'?'添加':'修改'{{"}}"}}
+
{{"{{"}}type==='create'?'新增':'编辑'{{"}}"}}
确 定
取 消
@@ -369,7 +722,7 @@
-
+
{{- range .Fields}}
{{- if .Desc }}
@@ -912,4 +1265,5 @@ defineOptions({
-{{- end}}
\ No newline at end of file
+{{- end}}
+{{- end}}
diff --git a/server/service/system/auto_code_template.go b/server/service/system/auto_code_template.go
index 542072ec7..bf366ee1b 100644
--- a/server/service/system/auto_code_template.go
+++ b/server/service/system/auto_code_template.go
@@ -290,6 +290,32 @@ func (s *autoCodeTemplate) AddFunc(info request.AutoFunc) error {
return nil
}
+func (s *autoCodeTemplate) GetApiAndServer(info request.AutoFunc) (map[string]string, error) {
+ autoPkg := model.SysAutoCodePackage{}
+ err := global.GVA_DB.First(&autoPkg, "package_name = ?", info.Package).Error
+ if err != nil {
+ return nil, err
+ }
+ if autoPkg.Template != "package" {
+ info.IsPlugin = true
+ }
+
+ apiStr, err := s.getTemplateStr("api.go", info)
+ if err != nil {
+ return nil, err
+ }
+ serverStr, err := s.getTemplateStr("server.go", info)
+ if err != nil {
+ return nil, err
+ }
+ jsStr, err := s.getTemplateStr("api.js", info)
+ if err != nil {
+ return nil, err
+ }
+ return map[string]string{"api": apiStr, "server": serverStr, "js": jsStr}, nil
+
+}
+
func (s *autoCodeTemplate) getTemplateStr(t string, info request.AutoFunc) (string, error) {
tempPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "resource", "function", t+".tpl")
files, err := template.ParseFiles(tempPath)
@@ -374,10 +400,19 @@ func (s *autoCodeTemplate) addTemplateToFile(t string, info request.AutoFunc) er
switch t {
case "api.go":
+ if info.IsAi && info.ApiFunc != "" {
+ getTemplateStr = info.ApiFunc
+ }
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "api", "v1", info.Package, info.HumpPackageName+".go")
case "server.go":
+ if info.IsAi && info.ServerFunc != "" {
+ getTemplateStr = info.ServerFunc
+ }
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "service", info.Package, info.HumpPackageName+".go")
case "api.js":
+ if info.IsAi && info.JsFunc != "" {
+ getTemplateStr = info.JsFunc
+ }
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Web, "api", info.Package, info.PackageName+".js")
}
if info.IsPlugin {
diff --git a/server/utils/upload/minio_oss.go b/server/utils/upload/minio_oss.go
new file mode 100644
index 000000000..3a6af72ce
--- /dev/null
+++ b/server/utils/upload/minio_oss.go
@@ -0,0 +1,98 @@
+package upload
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "io"
+ "mime/multipart"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/flipped-aurora/gin-vue-admin/server/global"
+ "github.com/flipped-aurora/gin-vue-admin/server/utils"
+ "github.com/minio/minio-go/v7"
+ "github.com/minio/minio-go/v7/pkg/credentials"
+ "go.uber.org/zap"
+)
+
+var MinioClient *Minio // 优化性能,但是不支持动态配置
+
+type Minio struct {
+ Client *minio.Client
+ bucket string
+}
+
+func GetMinio(endpoint, accessKeyID, secretAccessKey, bucketName string, useSSL bool) (*Minio, error) {
+ if MinioClient != nil {
+ return MinioClient, nil
+ }
+ // Initialize minio client object.
+ minioClient, err := minio.New(endpoint, &minio.Options{
+ Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+ Secure: useSSL, // Set to true if using https
+ })
+ if err != nil {
+ return nil, err
+ }
+ // 尝试创建bucket
+ err = minioClient.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{})
+ if err != nil {
+ // Check to see if we already own this bucket (which happens if you run this twice)
+ exists, errBucketExists := minioClient.BucketExists(context.Background(), bucketName)
+ if errBucketExists == nil && exists {
+ // log.Printf("We already own %s\n", bucketName)
+ } else {
+ return nil, err
+ }
+ }
+ MinioClient = &Minio{Client: minioClient, bucket: bucketName}
+ return MinioClient, nil
+}
+
+func (m *Minio) UploadFile(file *multipart.FileHeader) (filePathres, key string, uploadErr error) {
+ f, openError := file.Open()
+ // mutipart.File to os.File
+ if openError != nil {
+ global.GVA_LOG.Error("function file.Open() Failed", zap.Any("err", openError.Error()))
+ return "", "", errors.New("function file.Open() Failed, err:" + openError.Error())
+ }
+
+ filecontent := bytes.Buffer{}
+ _, err := io.Copy(&filecontent, f)
+ if err != nil {
+ global.GVA_LOG.Error("读取文件失败", zap.Any("err", err.Error()))
+ return "", "", errors.New("读取文件失败, err:" + err.Error())
+ }
+ f.Close() // 创建文件 defer 关闭
+
+
+ // 对文件名进行加密存储
+ ext := filepath.Ext(file.Filename)
+ filename := utils.MD5V([]byte(strings.TrimSuffix(file.Filename, ext))) + ext
+ if global.GVA_CONFIG.Minio.BasePath == "" {
+ filePathres = "uploads" + "/" + time.Now().Format("2006-01-02") + "/" + filename
+ } else {
+ filePathres = global.GVA_CONFIG.Minio.BasePath + "/" + time.Now().Format("2006-01-02") + "/" + filename
+ }
+
+ // 设置超时10分钟
+ ctx, cancel := context.WithTimeout(context.Background(), time.Minute*10)
+ defer cancel()
+
+ // Upload the file with PutObject 大文件自动切换为分片上传
+ info, err := m.Client.PutObject(ctx, global.GVA_CONFIG.Minio.BucketName, filePathres, &filecontent, file.Size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
+ if err != nil {
+ global.GVA_LOG.Error("上传文件到minio失败", zap.Any("err", err.Error()))
+ return "", "", errors.New("上传文件到minio失败, err:" + err.Error())
+ }
+ return global.GVA_CONFIG.Minio.BucketUrl + "/" + info.Key, filePathres, nil
+}
+
+func (m *Minio) DeleteFile(key string) error {
+ // Delete the object from MinIO
+ ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
+ err := m.Client.RemoveObject(ctx, m.bucket, key, minio.RemoveObjectOptions{})
+ return err
+}
diff --git a/server/utils/upload/upload.go b/server/utils/upload/upload.go
index 72fa44429..28266ab18 100644
--- a/server/utils/upload/upload.go
+++ b/server/utils/upload/upload.go
@@ -33,6 +33,13 @@ func NewOss() OSS {
return &AwsS3{}
case "cloudflare-r2":
return &CloudflareR2{}
+ case "minio":
+ minioClient, err := GetMinio(global.GVA_CONFIG.Minio.Endpoint, global.GVA_CONFIG.Minio.AccessKeyId, global.GVA_CONFIG.Minio.AccessKeySecret, global.GVA_CONFIG.Minio.BucketName, global.GVA_CONFIG.Minio.UseSSL)
+ if err != nil {
+ global.GVA_LOG.Warn("你配置了使用minio,但是初始化失败,请检查minio可用性或安全配置: " + err.Error())
+ panic("minio初始化失败") // 建议这样做,用户自己配置了minio,如果报错了还要把服务开起来,使用起来也很危险
+ }
+ return minioClient
default:
return &Local{}
}
diff --git a/web/package.json b/web/package.json
index bf2d07abc..dc7131596 100644
--- a/web/package.json
+++ b/web/package.json
@@ -10,6 +10,9 @@
"fix-memory-limit": "cross-env LIMIT=4096 increase-memory-limit"
},
"dependencies": {
+ "@codemirror/lang-go": "^6.0.1",
+ "@codemirror/lang-javascript": "^6.2.2",
+ "@codemirror/theme-one-dark": "^6.1.2",
"@element-plus/icons-vue": "^2.3.1",
"@form-create/designer": "^3.2.6",
"@form-create/element-ui": "^3.2.10",
@@ -21,10 +24,11 @@
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.7.7",
"chokidar": "^4.0.0",
+ "codemirror": "^6.0.1",
"core-js": "^3.38.1",
"default-passive-events": "^2.0.0",
"echarts": "5.5.1",
- "element-plus": "^2.8.4",
+ "element-plus": "^2.8.5",
"highlight.js": "^11.10.0",
"js-cookie": "^3.0.5",
"marked": "14.1.1",
@@ -41,6 +45,7 @@
"vform3-builds": "^3.0.10",
"vite-auto-import-svg": "^1.1.0",
"vue": "^3.5.7",
+ "vue-codemirror": "^6.1.1",
"vue-echarts": "^7.0.3",
"vue-router": "^4.4.3",
"vuedraggable": "^4.1.0"
diff --git a/web/src/main.js b/web/src/main.js
index 766c970d1..8f43f06ad 100644
--- a/web/src/main.js
+++ b/web/src/main.js
@@ -13,7 +13,7 @@ import run from '@/core/gin-vue-admin.js'
import auth from '@/directive/auth'
import { store } from '@/pinia'
import App from './App.vue'
-//消除警告
+// 消除警告
import 'default-passive-events'
const app = createApp(App)
diff --git a/web/src/pathInfo.json b/web/src/pathInfo.json
index 23497294c..e08798c04 100644
--- a/web/src/pathInfo.json
+++ b/web/src/pathInfo.json
@@ -51,7 +51,7 @@
"/src/view/superAdmin/user/user.vue": "User",
"/src/view/system/state.vue": "State",
"/src/view/systemTools/autoCode/component/fieldDialog.vue": "FieldDialog",
- "/src/view/systemTools/autoCode/component/previewCodeDialg.vue": "PreviewCodeDialg",
+ "/src/view/systemTools/autoCode/component/previewCodeDialog.vue": "PreviewCodeDialog",
"/src/view/systemTools/autoCode/index.vue": "AutoCode",
"/src/view/systemTools/autoCodeAdmin/index.vue": "AutoCodeAdmin",
"/src/view/systemTools/autoPkg/autoPkg.vue": "AutoPkg",
diff --git a/web/src/view/layout/aside/asideComponent/menuItem.vue b/web/src/view/layout/aside/asideComponent/menuItem.vue
index b20bbfb60..a43b24afd 100644
--- a/web/src/view/layout/aside/asideComponent/menuItem.vue
+++ b/web/src/view/layout/aside/asideComponent/menuItem.vue
@@ -1,7 +1,7 @@
+ >
@@ -19,11 +19,23 @@ import { Marked } from "marked";
import { markedHighlight } from "marked-highlight";
import hljs from 'highlight.js'
import { ElMessage } from 'element-plus'
-import { onMounted, ref } from 'vue'
+import { onMounted, ref, watchEffect } from 'vue'
import {useAppStore} from "@/pinia";
const appStore = useAppStore()
+const useCode = ref({})
+
+const createKey = [
+ "enter.go",
+ "gorm_biz.go",
+ "router_biz.go",
+ "api",
+ "router",
+ "initialize",
+ "gen.go",
+]
+
onMounted(() => {
const isDarkMode = appStore.config.darkMode === 'dark';
if (isDarkMode) {
@@ -39,6 +51,19 @@ const props = defineProps({
default() {
return {}
}
+ },
+ isAdd: {
+ type: Boolean,
+ default: false
+ }
+})
+
+watchEffect(() => {
+ for (const key in props.previewCode) {
+ if (props.isAdd && createKey.some(createKeyItem => key.includes(createKeyItem))) {
+ continue;
+ }
+ useCode.value[key] = props.previewCode[key]
}
})
@@ -48,7 +73,6 @@ onMounted(() => {
markedHighlight({
langPrefix: 'hljs language-',
highlight(code, lang, info) {
- console.log(code,lang,info)
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
if (lang === 'vue') {
return hljs.highlight(code, { language: 'html' }).value;
@@ -57,11 +81,11 @@ onMounted(() => {
}
})
);
- for (const key in props.previewCode) {
+ for (const key in useCode.value) {
if (activeName.value === '') {
activeName.value = key
}
- document.getElementById(key).innerHTML = marked.parse(props.previewCode[key])
+ document.getElementById(key).innerHTML = marked.parse(useCode.value[key])
}
})
diff --git a/web/src/view/systemTools/autoCode/index.vue b/web/src/view/systemTools/autoCode/index.vue
index 62d952f74..55cd21116 100644
--- a/web/src/view/systemTools/autoCode/index.vue
+++ b/web/src/view/systemTools/autoCode/index.vue
@@ -4,7 +4,7 @@
href="https://www.bilibili.com/video/BV1kv4y1g7nT?p=3"
title="此功能为开发环境使用,不建议发布到生产,具体使用效果请点我观看。"
/>
-
+
-
+
从数据库创建
自动化结构
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -551,7 +554,7 @@
label="字段Json"
>
-
+
-
+
-
+
-
+
导出json
@@ -697,32 +704,35 @@
show-file-list="false"
accept=".json"
>
- 导入json
+ 导入json
清除暂存
暂存
- 预览代码
-
-
生成代码
+
+ {{isAdd?'查看代码':'预览代码'}}
+
@@ -784,6 +794,7 @@
@@ -794,7 +805,7 @@
diff --git a/web/tailwind.config.js b/web/tailwind.config.js
index 0130bdd1f..bff67d2c4 100644
--- a/web/tailwind.config.js
+++ b/web/tailwind.config.js
@@ -22,9 +22,6 @@ module.exports = {
},
},
darkMode: "class",
- plugins: [],
- corePlugins: {
- preflight: false
- }
+ plugins: []
}
diff --git a/web/vitePlugin/componentName/index.js b/web/vitePlugin/componentName/index.js
index 66d3ec065..78a4840b6 100644
--- a/web/vitePlugin/componentName/index.js
+++ b/web/vitePlugin/componentName/index.js
@@ -55,7 +55,6 @@ const vueFilePathPlugin = (outputFilePath) => {
const watchDirectories = [path.join(root, 'src/view'), path.join(root, 'src/plugin')];
const watcher = chokidar.watch(watchDirectories, { persistent: true, ignoreInitial: true });
watcher.on('all', (event, path) => {
- console.log(`File ${path} has been ${event}`);
generatePathNameMap();
});
};
@@ -67,8 +66,10 @@ const vueFilePathPlugin = (outputFilePath) => {
configResolved(resolvedConfig) {
root = resolvedConfig.root;
},
- buildEnd() {
+ buildStart() {
generatePathNameMap();
+ },
+ buildEnd() {
if (process.env.NODE_ENV === 'development') {
watchDirectoryChanges();
}