Beta:发布v2.7.5测试版本 (#1896)

* 生产环境时移除console

* 更新第三方库道最新版本,修正导致的兼容问题

* feat: 版本号变更,修复自动化历史的结构体描述

* feat: 放弃element的按需引用,增加自定义表单组件,替换原始的iframe引入模式。

* feat: 放开表单生成器的key输入

* feat: 自动化代码关联属性支持跨数据库关联

* fixed: 修复跨库关联模板

* feat: 允许清空跨数据关联的业务库选项

* feat: 增加用户搜索功能

* feat: 允许单条API同步
---------

Co-authored-by: task <121913992@qq.com>
Co-authored-by: task <ms.yangdan@gmail.com>
This commit is contained in:
PiexlMax(奇淼
2024-09-30 21:27:16 +08:00
committed by GitHub
parent 2086a73557
commit 86cffba4aa
36 changed files with 637 additions and 477 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "gin-vue-admin",
"version": "2.7.4",
"version": "2.7.5",
"private": true,
"scripts": {
"serve": "node openDocument.js && vite --host --mode development",
@@ -11,6 +11,8 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@form-create/designer": "^3.2.6",
"@form-create/element-ui": "^3.2.10",
"@vue-office/docx": "^1.6.2",
"@vue-office/excel": "^1.7.11",
"@vue-office/pdf": "^2.0.2",
@@ -22,7 +24,7 @@
"core-js": "^3.38.1",
"default-passive-events": "^2.0.0",
"echarts": "5.5.1",
"element-plus": "^2.8.1",
"element-plus": "^2.8.4",
"highlight.js": "^11.10.0",
"js-cookie": "^3.0.5",
"marked": "14.1.1",
@@ -36,6 +38,7 @@
"sortablejs": "^1.15.3",
"spark-md5": "^3.0.2",
"tailwindcss": "^3.4.10",
"vform3-builds": "^3.0.10",
"vite-auto-import-svg": "^1.1.0",
"vue": "^3.5.7",
"vue-echarts": "^7.0.3",
@@ -59,8 +62,6 @@
"eslint-plugin-vue": "^9.28.0",
"sass": "^1.78.0",
"terser": "^5.31.6",
"unplugin-auto-import": "^0.18.2",
"unplugin-vue-components": "^0.27.4",
"vite": "^5.4.3",
"vite-plugin-banner": "^0.8.0",
"vite-plugin-importer": "^0.2.5",

View File

@@ -8,8 +8,6 @@
<script setup>
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
// element 2.3.8之前使用下面的语句
// import zhCn from 'element-plus/lib/locale/lang/zh-cn'
import {useAppStore} from "@/pinia";
useAppStore()
defineOptions({

View File

@@ -13,7 +13,7 @@ const config = {
export const viteLogo = (env) => {
if (config.showViteLogo) {
console.log(greenText(`> 欢迎使用Gin-Vue-Admin开源地址https://github.com/flipped-aurora/gin-vue-admin`));
console.log(greenText(`> 当前版本:v2.7.4`));
console.log(greenText(`> 当前版本:v2.7.5`));
console.log(greenText(`> 加群方式:微信shouzi_1994 QQ群470239250`));
console.log(greenText(`> 项目地址https://github.com/flipped-aurora/gin-vue-admin`));
console.log(greenText(`> 插件市场:https://plugin.gin-vue-admin.com`));

View File

@@ -10,7 +10,7 @@ export default {
register(app)
console.log(`
欢迎使用 Gin-Vue-Admin
当前版本:v2.7.4
当前版本:v2.7.5
加群方式:微信shouzi_1994 QQ群622360840
项目地址https://github.com/flipped-aurora/gin-vue-admin
插件市场:https://plugin.gin-vue-admin.com

View File

@@ -1,11 +1,8 @@
import 'element-plus/es/components/message/style/css'
import 'element-plus/es/components/loading/style/css'
import 'element-plus/es/components/notification/style/css'
import 'element-plus/es/components/message-box/style/css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import './style/element_visiable.scss'
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 引入gin-vue-admin前端初始化相关内容
import './core/gin-vue-admin'
// 引入封装的router
@@ -23,6 +20,7 @@ app.config.productionTip = false
app
.use(run)
.use(ElementPlus)
.use(store)
.use(auth)
.use(router)

View File

@@ -163,7 +163,6 @@
<template #default="scope">
<el-button
icon="edit"
type="primary"
link
@click="editApiFunc(scope.row)"
@@ -172,7 +171,6 @@
</el-button>
<el-button
icon="delete"
type="primary"
link
@click="deleteApiFunc(scope.row)"
@@ -282,7 +280,10 @@
fixed="right"
>
<template #default="{row}">
<el-button type="primary" text @click="ignoreApiFunc(row,true)">
<el-button icon="plus" type="primary" link @click="addApiFunc(row)">
单条新增
</el-button>
<el-button icon="sunrise" type="primary" link @click="ignoreApiFunc(row,true)">
忽略
</el-button>
</template>
@@ -365,7 +366,7 @@
fixed="right"
>
<template #default="{row}">
<el-button type="primary" text @click="ignoreApiFunc(row,false)">
<el-button icon="sunny" type="primary" link @click="ignoreApiFunc(row,false)">
取消忽略
</el-button>
</template>
@@ -568,14 +569,49 @@ const ignoreApiFunc = async (row,flag) =>{
}
}
const addApiFunc = async(row)=>{
if(!row.apiGroup){
ElMessage({
type: 'error',
message: '请先选择API分组'
})
return
}
if(!row.description){
ElMessage({
type: 'error',
message: '请先填写API描述'
})
return
}
const res = await createApi(row)
if (res.code === 0) {
ElMessage({
type: 'success',
message: '添加成功',
showClose: true
})
syncApiData.value.newApis = syncApiData.value.newApis.filter(item => !(item.path === row.path && item.method === row.method))
}
getTableData()
getGroup()
}
const closeSyncDialog = () => {
syncApiFlag.value = false
}
const syncing = ref(false)
const enterSyncDialog = async() => {
if( syncApiData.value.newApis.some(item => !item.apiGroup || !item.description)){
ElMessage({
type: 'error',
message: '存在API未分组或未填写描述'
})
return
}
syncing.value = true
const res = await enterSyncApi(syncApiData.value)
syncing.value = false

View File

@@ -1,6 +1,53 @@
<template>
<div>
<warning-bar title="注:右上角头像下拉可切换角色" />
<div class="gva-search-box">
<el-form
ref="searchForm"
:inline="true"
:model="searchInfo"
>
<el-form-item label="用户名">
<el-input
v-model="searchInfo.username"
placeholder="用户名"
/>
</el-form-item>
<el-form-item label="昵称">
<el-input
v-model="searchInfo.nickname"
placeholder="昵称"
/>
</el-form-item>
<el-form-item label="手机号">
<el-input
v-model="searchInfo.phone"
placeholder="手机号"
/>
</el-form-item>
<el-form-item label="邮箱">
<el-input
v-model="searchInfo.email"
placeholder="邮箱"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
@click="onSubmit"
>
查询
</el-button>
<el-button
icon="refresh"
@click="onReset"
>
重置
</el-button>
</el-form-item>
</el-form>
</div>
<div class="gva-table-box">
<div class="gva-btn-list">
<el-button
@@ -246,7 +293,27 @@ defineOptions({
name: 'User',
})
const path = ref(import.meta.env.VITE_BASE_API + '/')
const searchInfo = ref({
username: '',
nickname: '',
phone: '',
email: ''
})
const onSubmit = () => {
page.value = 1
getTableData()
}
const onReset = () => {
searchInfo.value = {
username: '',
nickname: '',
phone: '',
email: ''
}
getTableData()
}
// 初始化相关
const setAuthorityOptions = (AuthorityData, optionsData) => {
AuthorityData &&
@@ -286,7 +353,7 @@ const handleCurrentChange = (val) => {
// 查询
const getTableData = async() => {
const table = await getUserList({ page: page.value, pageSize: pageSize.value })
const table = await getUserList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
@@ -341,11 +408,6 @@ const setAuthorityIds = () => {
})
}
const chooseImg = ref(null)
const openHeaderChange = () => {
chooseImg.value.open()
}
const authOptions = ref([])
const setOptions = (authData) => {
authOptions.value = []

View File

@@ -193,7 +193,30 @@
>
<el-row :gutter="8">
<el-col
:span="3"
:span="4"
>
<el-select
v-model="middleDate.dataSource.dbName"
placeholder="数据库【不填则为GVA库】"
@change="dbNameChange"
clearable
>
<el-option
v-for="item in dbList"
:key="item.aliasName"
:value="item.aliasName"
:label="item.aliasName"
:disabled="item.disable"
>
<div>
<span>{{ item.aliasName }}</span>
<span style="float:right;color:#8492a6;font-size:13px">{{ item.dbName }}</span>
</div>
</el-option>
</el-select>
</el-col>
<el-col
:span="4"
>
<el-select
v-model="middleDate.dataSource.association"
@@ -210,8 +233,7 @@
/>
</el-select>
</el-col>
<el-col :span="7">
<el-col :span="5">
<el-select
v-model="middleDate.dataSource.table" placeholder="请选择数据源表"
filterable allow-create @focus="getDBTableList" @change="selectDB"
@@ -221,9 +243,8 @@
:value="item.tableName"
/>
</el-select>
<!-- <el-input v-model="middleDate.dataSource.table" placeholder="数据源表" /> -->
</el-col>
<el-col :span="7">
<el-col :span="5">
<el-select v-model="middleDate.dataSource.value" placeholder="请先选择需要存储的数据">
<template #label="{ value }">
<span>存储: </span>
@@ -245,9 +266,8 @@
</span>
</el-option>
</el-select>
<!-- <el-input v-model="middleDate.dataSource.value" placeholder="存储用字段" /> -->
</el-col>
<el-col :span="7">
<el-col :span="5">
<el-select v-model="middleDate.dataSource.label" placeholder="请先选择需要展示的数据">
<template #label="{ value }">
<span>展示: </span>
@@ -283,7 +303,7 @@ import { getSysDictionaryList } from '@/api/sysDictionary'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { ref,onMounted } from 'vue'
import { ElMessageBox } from 'element-plus'
import {getColumn, getTable} from "@/api/autoCode";
import {getColumn, getDB, getTable} from "@/api/autoCode";
defineOptions({
name: 'FieldDialog'
@@ -321,6 +341,15 @@ const activeNames = ref([])
const middleDate = ref({})
const dictOptions = ref([])
const dbList = ref([])
const getDbFunc = async() => {
const res = await getDB()
if (res.code === 0) {
dbList.value = res.data.dbList
}
}
const validateDataTypeLong = (rule, value, callback) => {
const regex = /^('([^']*)'(?:,'([^']+)'*)*)$/;
if (middleDate.value.fieldType == "enum" && !regex.test(value)) {
@@ -403,11 +432,18 @@ const associationChange = (val) => {
}
const dbNameChange = () => {
getDBTableList()
middleDate.value.dataSource.table = ''
middleDate.value.dataSource.value = ''
middleDate.value.dataSource.label = ''
}
const dbTableList = ref([])
const getDBTableList = async () => {
const res = await getTable()
console.log(res);
const res = await getTable({ businessDB: middleDate.value.dataSource.dbName })
if (res.code === 0) {
let list = res.data.tables; // 确保这里正确获取到 tables 数组
dbTableList.value = list.map(item => ({
@@ -415,12 +451,15 @@ const getDBTableList = async () => {
value: item.tableName // 这里假设 value 也是 tableName如果不同请调整
}));
}
middleDate.value.dataSource.value = ''
middleDate.value.dataSource.label = ''
}
const dbColumnList = ref([])
const selectDB = async (val) => {
middleDate.value.dataSource.table = val
const res = await getColumn({
businessDB: middleDate.value.dataSource.dbName,
tableName: val
})
@@ -445,6 +484,7 @@ const fieldDialogForm = ref(null)
defineExpose({ fieldDialogForm })
onMounted(()=>{
getDbFunc()
if(middleDate.value.dataSource.table){
selectDB(middleDate.value.dataSource.table)
}

View File

@@ -26,7 +26,7 @@
align="left"
label="结构体描述"
min-width="150"
prop="structCNName"
prop="description"
/>
<el-table-column
align="left"

View File

@@ -1,19 +1,20 @@
<template>
<div style="height:80vh">
<iframe
width="100%"
height="100%"
:src="`${basePath}:${basePort}/form-generator/#/`"
frameborder="0"
/>
</div>
<fc-designer ref="designer" :config="config" height="calc(100vh - 160px)" />
</template>
<script setup>
import { ref } from 'vue'
const basePath = ref(import.meta.env.VITE_BASE_PATH)
const basePort = ref(import.meta.env.VITE_SERVER_PORT)
import {ref} from "vue";
import FcDesigner from '@form-create/designer'
defineOptions({
name: 'FormGenerator'
})
const designer = ref(null)
const config = {
fieldReadonly: false
}
</script>

View File

@@ -1,7 +1,4 @@
import legacyPlugin from '@vitejs/plugin-legacy'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { viteLogo } from './src/core/config'
import Banner from 'vite-plugin-banner'
import * as path from 'path'
@@ -9,7 +6,6 @@ import * as dotenv from 'dotenv'
import * as fs from 'fs'
import vuePlugin from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import fullImportPlugin from './vitePlugin/fullImport/fullImport.js'
import VueFilePathPlugin from './vitePlugin/componentName/index.js'
import { svgBuilder } from 'vite-auto-import-svg'
import { AddSecret } from './vitePlugin/secret'
@@ -101,28 +97,6 @@ export default ({
[Banner(`\n Build based on gin-vue-admin \n Time : ${timestamp}`)],
VueFilePathPlugin("./src/pathInfo.json")
],
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/style/element/index.scss" as *;`,
}
}
},
}
if (NODE_ENV === 'development') {
config.plugins.push(
fullImportPlugin()
)
} else {
config.plugins.push(AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver({
importStyle: 'sass'
})]
}))
}
return config
}

View File

@@ -1,23 +0,0 @@
import * as path from 'path'
export default function fullImportPlugin() {
let config
return {
name: 'fullImportElementPlus',
async configResolved(conf) {
config = conf
},
transform(code, id) {
const sourcePath = path.join(config.root, 'src/main.js').split(path.sep).join('/')
const targetPath = id.split(path.sep).join('/')
if (sourcePath === targetPath) {
const name = 'ElementPlus'
// 引入 ElementPlus 和 样式
code = code.replace(/import\s*{\s*createApp\s*}\s*from\s*['"]vue['"]/, ($1) => $1 + `\nimport ${name} from 'element-plus'`)
code = code.replace(/import\s*['"]\.\/style\/element_visiable\.scss['"]/, ($1) => $1 + `\nimport 'element-plus/theme-chalk/src/index.scss'`)
code = code.replace(/\.mount\(/, ($1) => `.use(${name})` + $1)
return code
}
return code
}
}
}