* fixed: 修复addFunction下前端api.js无法创建的bug。

* feature: 增加严格角色模式

* Update system.vue

* fixed: 多点登录拦截模式下,jwt换票期间不需要拉黑token。

* fixed: 修复使用ast时候产生无意义的换行的问题

* fixed: 修复跨级操作角色权限的越权问题

* feature: 优化严格模式角色鉴权操作。

* fixed: 增加菜单和api设置越权问题的限制

* feature: 增加插件打包前的自动化同步所需菜单和api的功能

* feature: 自动化代码可以默认生成导入导出

* feature: 自动化导入导出对模板进行回滚

* feature: 剔除无用的packfile代码包

* feature: 发布V2.7.3版本公测。

---------

Co-authored-by: task <ms.yangdan@gmail.com>
This commit is contained in:
PiexlMax(奇淼
2024-08-27 13:15:56 +08:00
committed by GitHub
parent 87ced16d63
commit 866fa5643e
52 changed files with 1506 additions and 629 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "gin-vue-admin",
"version": "2.7.2",
"version": "2.7.3",
"private": true,
"scripts": {
"serve": "node openDocument.js && vite --host --mode development",
@@ -19,6 +19,7 @@
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.4.0",
"core-js": "^3.31.1",
"default-passive-events": "^2.0.0",
"echarts": "5.4.3",
"element-plus": "^2.7.4",
"highlight.js": "^11.8.0",

View File

@@ -166,3 +166,22 @@ export const addFunc = (data) => {
data
})
}
export const initMenu = (data) => {
return service({
url: '/autoCode/initMenu',
method: 'post',
data
})
}
export const initAPI = (data) => {
return service({
url: '/autoCode/initAPI',
method: 'post',
data
})
}

View File

@@ -40,3 +40,17 @@ export const getSystemState = () => {
donNotShowLoading: true
})
}
/**
* 重启服务
* @param data
* @returns {*}
*/
export const reloadSystem = (data) => {
return service({
url: '/system/reloadSystem',
method: 'post',
data
})
}

View File

@@ -0,0 +1,68 @@
<template>
<div class="flex gap-2">
<el-tag
v-for="tag in modelValue"
:key="tag"
:closable="editable"
:disable-transitions="false"
@close="handleClose(tag)"
>
{{ tag }}
</el-tag>
<template v-if="editable">
<el-input
v-if="inputVisible"
ref="InputRef"
v-model="inputValue"
class="w-20"
size="small"
@keyup.enter="handleInputConfirm"
@blur="handleInputConfirm"
/>
<el-button v-else class="button-new-tag" size="small" @click="showInput">
+ 新增
</el-button>
</template>
</div>
</template>
<script setup>
defineOptions({
name: 'ArrayCtrl',
})
import { nextTick, ref } from 'vue'
const inputValue = ref('')
const inputVisible = ref(false)
const InputRef = ref(null)
const modelValue = defineModel()
defineProps({
editable: {
type: Boolean,
default: () => false
}
})
const handleClose = (tag) => {
modelValue.value.splice(modelValue.value.indexOf(tag), 1)
}
const showInput = () => {
inputVisible.value = true
nextTick(() => {
InputRef.value?.input?.focus()
})
}
const handleInputConfirm = () => {
if (inputValue.value) {
modelValue.value.push(inputValue.value)
}
inputVisible.value = false
inputValue.value = ''
}
</script>

View File

@@ -15,9 +15,7 @@
<script setup>
import ImageCompress from '@/utils/image'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/pinia/modules/user'
import { getBaseUrl } from '@/utils/format'
defineOptions({
@@ -40,10 +38,6 @@ const props = defineProps({
}
})
const path = ref(import.meta.env.VITE_BASE_API)
const userStore = useUserStore()
const beforeImageUpload = (file) => {
const isJPG = file.type === 'image/jpeg'
const isPng = file.type === 'image/png'

View File

@@ -20,7 +20,7 @@ export const viteLogo = (env) => {
)
console.log(
chalk.green(
`> 当前版本:v2.7.2`
`> 当前版本:v2.7.3`
)
)
console.log(

View File

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

View File

@@ -15,6 +15,8 @@ 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)
app.config.productionTip = false

View File

@@ -231,20 +231,13 @@ const rules = ref({
]
})
const page = ref(1)
const total = ref(0)
const pageSize = ref(999)
const tableData = ref([])
const searchInfo = ref({})
// 查询
const getTableData = async() => {
const table = await getAuthorityList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
const table = await getAuthorityList()
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
tableData.value = table.data
}
}
@@ -294,9 +287,7 @@ const deleteAuth = (row) => {
type: 'success',
message: '删除成功!'
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
}
})

View File

@@ -131,6 +131,7 @@ const authDataEnter = async() => {
// 选择
const selectAuthority = () => {
dataAuthorityId.value = dataAuthorityId.value.filter(item => item)
emit('changeRow', 'dataAuthorityId', dataAuthorityId.value)
needConfirm.value = true
}

View File

@@ -585,23 +585,12 @@ const rules = reactive({
],
})
const page = ref(1)
const total = ref(0)
const pageSize = ref(999)
const tableData = ref([])
const searchInfo = ref({})
// 查询
const getTableData = async() => {
const table = await getMenuList({
page: page.value,
pageSize: pageSize.value,
...searchInfo.value,
})
const table = await getMenuList()
if (table.code === 0) {
tableData.value = table.data.list
total.value = table.data.total
page.value = table.data.page
pageSize.value = table.data.pageSize
tableData.value = table.data
}
}
@@ -693,9 +682,7 @@ const deleteMenu = (ID) => {
type: 'success',
message: '删除成功!',
})
if (tableData.value.length === 1 && page.value > 1) {
page.value--
}
getTableData()
}
})

View File

@@ -301,8 +301,8 @@ watch(() => tableData.value, () => {
const initPage = async() => {
getTableData()
const res = await getAuthorityList({ page: 1, pageSize: 999 })
setOptions(res.data.list)
const res = await getAuthorityList()
setOptions(res.data)
}
initPage()

View File

@@ -167,6 +167,9 @@
<el-form-item label="前端详情">
<el-switch v-model="middleDate.desc" />
</el-form-item>
<el-form-item label="导入/导出">
<el-switch v-model="middleDate.excel" />
</el-form-item>
<el-form-item label="是否排序">
<el-switch v-model="middleDate.sort" />
</el-form-item>

View File

@@ -507,6 +507,15 @@
<el-checkbox v-model="row.desc" />
</template>
</el-table-column>
<el-table-column
align="left"
prop="excel"
label="导入/导出"
>
<template #default="{row}">
<el-checkbox v-model="row.excel" />
</template>
</el-table-column>
<el-table-column
align="left"
prop="fieldJson"
@@ -808,6 +817,7 @@ const llmAutoFunc = async (mode) =>{
form: true,
desc: true,
table: true,
excel: false,
dataSource: {
association:1,
table: '',
@@ -964,6 +974,7 @@ const fieldTemplate = {
form: true,
desc: true,
table: true,
excel: false,
errorText: '',
primaryKey: false,
clearable: true,
@@ -1258,6 +1269,7 @@ const getColumnFunc = async() => {
dictType: '',
form: true,
table: true,
excel: false,
desc: true,
dataSource: {
association:1,

View File

@@ -4,32 +4,231 @@
<WarningBar title="目前只支持标准插件(通过插件模板生成的标准目录插件),非标准插件请自行打包" />
<div class="flex items-center gap-3">
<el-input
v-model="plugName"
placeholder="插件模板处填写的【插件名】"
v-model="plugName"
placeholder="插件模板处填写的【插件名】"
/>
<el-button
type="primary"
@click="pubPlugin"
>打包插件</el-button>
</div>
<el-card class="mt-2 text-center">
<WarningBar title="穿梭框请只选择子级菜单即可" />
<el-input v-model="parentMenu" placeholder="请输入菜单组名,例:公告管理" class="mb-2"></el-input>
<el-transfer
v-model="menus"
:props="{
key: 'ID',
}"
class="plugin-transfer"
:data="menusData"
filterable
:filter-method="filterMenuMethod"
filter-placeholder="请输入菜单名称/路径"
:titles="['可选菜单','使用菜单']"
:button-texts="['移除', '选中']"
>
<template #default="{option}">
{{ option.meta.title }} {{ option.component }}
</template>
</el-transfer>
<div class="flex justify-end mt-2">
<el-button
type="primary"
@click="fmtInitMenu"
>
定义安装菜单
</el-button>
</div>
</el-card>
<el-card class="mt-2 text-center">
<el-transfer
v-model="apis"
:props="{
key: 'ID',
}"
class="plugin-transfer"
:data="apisData"
filterable
:filter-method="filterApiMethod"
filter-placeholder="请输入API描述/PATH"
:titles="['可选API','使用API']"
:button-texts="['移除', '选中']"
>
<template #default="{option}">
{{ option.description }} {{ option.path }}
</template>
</el-transfer>
<div class="flex justify-end mt-2">
<el-button
type="primary"
@click="fmtInitAPI"
>
定义安装API
</el-button>
</div>
</el-card>
</div>
<div class="flex justify-end">
<el-button
type="primary"
@click="pubPlugin"
>
打包插件
</el-button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import WarningBar from '@/components/warningBar/warningBar.vue'
import { pubPlug } from '@/api/autoCode.js'
import { ElMessage } from 'element-plus'
import { pubPlug,initMenu,initAPI } from '@/api/autoCode.js'
import {ElMessage, ElMessageBox} from 'element-plus'
import {getAllApis} from "@/api/api";
import {getMenuList} from "@/api/menu";
const plugName = ref('')
const pubPlugin = async() => {
const res = await pubPlug({ plugName: plugName.value })
if (res.code === 0) {
ElMessage.success(res.msg)
const menus = ref([])
const menusData = ref([])
const apis = ref([])
const apisData = ref([])
const parentMenu = ref('')
const fmtMenu = (menus) => {
// 如果menu存在children递归展开到一级
const res = []
menus.forEach(item => {
if (item.children) {
res.push(...fmtMenu(item.children))
} else {
res.push(item)
}
})
return res
}
const initData = async() => {
const menuRes = await getMenuList()
if (menuRes.code === 0) {
menusData.value = fmtMenu(menuRes.data)
}
const apiRes = await getAllApis()
if (apiRes.code === 0) {
apisData.value = apiRes.data.apis
}
}
const filterMenuMethod = (query, item) => {
return item.meta.title.indexOf(query) > -1 || item.component.indexOf(query) > -1
}
const filterApiMethod = (query, item) => {
return item.description.indexOf(query) > -1 || item.path.indexOf(query) > -1
}
initData()
const pubPlugin = async() => {
ElMessageBox.confirm(
`请检查server下的/plugin/${plugName.value}/plugin.go是否已放开需要的 initialize.Api(ctx) 和 initialize.Menu(ctx)?`,
'打包',
{
confirmButtonText: '打包',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
const res = await pubPlug({ plugName: plugName.value })
if (res.code === 0) {
ElMessage.success(res.msg)
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '关闭打包',
})
})
}
const fmtInitMenu = () => {
if (!parentMenu.value) {
ElMessage.error('请填写菜单组名')
return
}
if (menus.value.length === 0) {
ElMessage.error('请至少选择一个菜单')
return
}
if (plugName.value === '') {
ElMessage.error('请填写插件名')
return
}
ElMessageBox.confirm(
`点击后将会覆盖server下的/plugin/${plugName.value}/initialize/menu. 是否继续?`,
'生成初始菜单',
{
confirmButtonText: '生成',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
const req = {
plugName: plugName.value,
parentMenu: parentMenu.value,
menus: menus.value
}
initMenu(req)
})
.catch(() => {
ElMessage({
type: 'info',
message: '关闭生成菜单',
})
})
}
const fmtInitAPI = () => {
if (apis.value.length === 0) {
ElMessage.error('请至少选择一个API')
return
}
if (plugName.value === '') {
ElMessage.error('请填写插件名')
return
}
ElMessageBox.confirm(
`点击后将会覆盖server下的/plugin/${plugName.value}/initialize/api. 是否继续?`,
'生成初始API',
{
confirmButtonText: '生成',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
const req = {
plugName: plugName.value,
apis: apis.value
}
initAPI(req)
console.log(req)
})
.catch(() => {
ElMessage({
type: 'info',
message: '关闭生成API',
})
})
}
</script>
<style lang="scss">
.plugin-transfer{
.el-transfer-panel{
width: 400px !important;
}
}
</style>

File diff suppressed because it is too large Load Diff