update: 发布dev2.7.6Beta版本 (#1908)
* feat: 优化菜单管理的路径选择框 * fixed: 修复错误的文件命名 * feat: 增加参数管理功能,调整菜单选择组件。 * feat: 恢复config.yaml * feat: 更新AI功能 * feat: 增加API自动填充功能 * feat: 增加AI自动填充表格导出模板 * feat: 增加AI自动填充表格导出模板和AI自动模板填充 * feat: 新增方法支持选择是否鉴权 --------- Co-authored-by: Azir <2075125282@qq.com>
This commit is contained in:
+12
-10
@@ -140,25 +140,30 @@ export const pubPlug = (params) => {
|
||||
}
|
||||
|
||||
|
||||
export const llmAuto = (params) => {
|
||||
let modeName = {
|
||||
"xiaoqi": "小奇",
|
||||
"xiaomiao": "小淼",
|
||||
}
|
||||
export const llmAuto = (data) => {
|
||||
return service({
|
||||
url: '/autoCode/llmAuto',
|
||||
method: 'post',
|
||||
params,
|
||||
data:{...data,mode:'ai'},
|
||||
timeout: 1000 * 60 * 10,
|
||||
loadingOption:{
|
||||
lock: true,
|
||||
fullscreen:true,
|
||||
text: `${modeName[params.mode]}正在思考,请稍候...`,
|
||||
text: `小淼正在思考,请稍候...`,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const butler = (data) => {
|
||||
return service({
|
||||
url: '/autoCode/llmAuto',
|
||||
method: 'post',
|
||||
data:{...data,mode:'butler'},
|
||||
timeout: 1000 * 60 * 10,
|
||||
})
|
||||
}
|
||||
|
||||
export const addFunc = (data) => {
|
||||
return service({
|
||||
url: '/autoCode/addFunc',
|
||||
@@ -182,6 +187,3 @@ export const initAPI = (data) => {
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import service from '@/utils/request'
|
||||
// @Tags SysParams
|
||||
// @Summary 创建参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysParams true "创建参数"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /sysParams/createSysParams [post]
|
||||
export const createSysParams = (data) => {
|
||||
return service({
|
||||
url: '/sysParams/createSysParams',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SysParams
|
||||
// @Summary 删除参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysParams true "删除参数"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysParams/deleteSysParams [delete]
|
||||
export const deleteSysParams = (params) => {
|
||||
return service({
|
||||
url: '/sysParams/deleteSysParams',
|
||||
method: 'delete',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SysParams
|
||||
// @Summary 批量删除参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.IdsReq true "批量删除参数"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysParams/deleteSysParams [delete]
|
||||
export const deleteSysParamsByIds = (params) => {
|
||||
return service({
|
||||
url: '/sysParams/deleteSysParamsByIds',
|
||||
method: 'delete',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SysParams
|
||||
// @Summary 更新参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysParams true "更新参数"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /sysParams/updateSysParams [put]
|
||||
export const updateSysParams = (data) => {
|
||||
return service({
|
||||
url: '/sysParams/updateSysParams',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SysParams
|
||||
// @Summary 用id查询参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query model.SysParams true "用id查询参数"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /sysParams/findSysParams [get]
|
||||
export const findSysParams = (params) => {
|
||||
return service({
|
||||
url: '/sysParams/findSysParams',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SysParams
|
||||
// @Summary 分页获取参数列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query request.PageInfo true "分页获取参数列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysParams/getSysParamsList [get]
|
||||
export const getSysParamsList = (params) => {
|
||||
return service({
|
||||
url: '/sysParams/getSysParamsList',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SysParams
|
||||
// @Summary 不需要鉴权的参数接口
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query systemReq.SysParamsSearch true "分页获取参数列表"
|
||||
// @Success 200 {object} response.Response{data=object,msg=string} "获取成功"
|
||||
// @Router /sysParams/getSysParam [get]
|
||||
export const getSysParam = (params) => {
|
||||
return service({
|
||||
url: '/sysParams/getSysParam',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -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.5`));
|
||||
console.log(greenText(`> 当前版本:v2.7.6`));
|
||||
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`));
|
||||
|
||||
@@ -10,7 +10,7 @@ export default {
|
||||
register(app)
|
||||
console.log(`
|
||||
欢迎使用 Gin-Vue-Admin
|
||||
当前版本:v2.7.5
|
||||
当前版本:v2.7.6
|
||||
加群方式:微信:shouzi_1994 QQ群:622360840
|
||||
项目地址:https://github.com/flipped-aurora/gin-vue-admin
|
||||
插件市场:https://plugin.gin-vue-admin.com
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"/src/view/about/index.vue": "About",
|
||||
"/src/view/dashboard/index.vue": "Dashboard",
|
||||
"/src/view/error/index.vue": "Error",
|
||||
"/src/view/error/reload.vue": "Reload",
|
||||
"/src/view/example/breakpoint/breakpoint.vue": "BreakPoint",
|
||||
@@ -32,6 +33,7 @@
|
||||
"/src/view/superAdmin/menu/icon.vue": "Icon",
|
||||
"/src/view/superAdmin/menu/menu.vue": "Menus",
|
||||
"/src/view/superAdmin/operation/sysOperationRecord.vue": "SysOperationRecord",
|
||||
"/src/view/superAdmin/params/sysParams.vue": "SysParams",
|
||||
"/src/view/superAdmin/user/user.vue": "User",
|
||||
"/src/view/system/state.vue": "State",
|
||||
"/src/view/systemTools/autoCode/component/fieldDialog.vue": "FieldDialog",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useDictionaryStore } from '@/pinia/modules/dictionary'
|
||||
import { getSysParam } from '@/api/sysParams'
|
||||
// 获取字典方法 使用示例 getDict('sex').then(res) 或者 async函数下 const res = await getDict('sex')
|
||||
export const getDict = async(type) => {
|
||||
const dictionaryStore = useDictionaryStore()
|
||||
@@ -24,3 +25,11 @@ export const showDictLabel = (
|
||||
})
|
||||
return Reflect.has(dictMap, code) ? dictMap[code] : ''
|
||||
}
|
||||
|
||||
|
||||
export const getParams = async (key)=>{
|
||||
const res = await getSysParam({key})
|
||||
if(res.code === 0){
|
||||
return res.data.value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { GvaPluginTable,GvaTable, GvaChart, GvaWiki , GvaNotice , GvaQuickLink , GvaCard , GvaBanner } from "./componenst"
|
||||
import { GvaPluginTable,GvaTable, GvaChart, GvaWiki , GvaNotice , GvaQuickLink , GvaCard , GvaBanner } from "./components"
|
||||
defineOptions({
|
||||
name: 'Dashboard'
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -204,12 +204,12 @@
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-lg">同步路由</span>
|
||||
<div>
|
||||
<el-button @click="closeSyncDialog">
|
||||
<el-button :loading="apiCompletionLoading" @click="closeSyncDialog">
|
||||
取 消
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="syncing"
|
||||
:loading="syncing||apiCompletionLoading"
|
||||
@click="enterSyncDialog"
|
||||
>
|
||||
确 定
|
||||
@@ -218,8 +218,17 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<h4>新增路由 <span class="text-xs text-gray-500 ml-2 font-normal">存在于当前路由中,但是不存在于api表</span></h4>
|
||||
<h4>新增路由 <span class="text-xs text-gray-500 mx-2 font-normal">存在于当前路由中,但是不存在于api表</span>
|
||||
<el-button type="primary" size="small" @click="apiCompletion">
|
||||
<el-icon size="18">
|
||||
<ai-gva />
|
||||
</el-icon>
|
||||
自动填充
|
||||
</el-button>
|
||||
</h4>
|
||||
<el-table
|
||||
v-loading="syncing||apiCompletionLoading"
|
||||
element-loading-text="小淼正在思考..."
|
||||
:data="syncApiData.newApis"
|
||||
>
|
||||
<el-table-column
|
||||
@@ -481,6 +490,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import ExportExcel from '@/components/exportExcel/exportExcel.vue'
|
||||
import ExportTemplate from '@/components/exportExcel/exportTemplate.vue'
|
||||
import ImportExcel from '@/components/exportExcel/importExcel.vue'
|
||||
import {butler} from "@/api/autoCode";
|
||||
|
||||
defineOptions({
|
||||
name: 'Api',
|
||||
@@ -843,6 +853,34 @@ const deleteApiFunc = async(row) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
const apiCompletionLoading = ref(false)
|
||||
const apiCompletion = async () =>{
|
||||
apiCompletionLoading.value = true
|
||||
const routerPaths = syncApiData.value.newApis.filter(item => !item.apiGroup || !item.description).map(item => item.path)
|
||||
const res = await butler({data:routerPaths,command:'apiCompletion'})
|
||||
apiCompletionLoading.value = false
|
||||
if (res.code === 0) {
|
||||
try{
|
||||
const data = JSON.parse(res.data)
|
||||
syncApiData.value.newApis.forEach(item => {
|
||||
const target = data.find(d => d.path === item.path)
|
||||
if(target){
|
||||
if(!item.apiGroup){
|
||||
item.apiGroup = target.apiGroup
|
||||
}
|
||||
if (!item.description) {
|
||||
item.description = target.description
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: 'AI自动填充失败,请重新生成'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="flex justify-between items-center gap-2 w-full">
|
||||
<el-cascader
|
||||
v-if="pathIsSelect"
|
||||
placeholder="请选择文件路径"
|
||||
:options="pathOptions"
|
||||
v-model="activeComponent"
|
||||
filterable
|
||||
class="w-full"
|
||||
clearable
|
||||
@change="emitChange"
|
||||
/>
|
||||
<el-input v-else v-model="tempPath" placeholder="页面:view/xxx/xx.vue 插件:plugin/xx/xx.vue" @change="emitChange" />
|
||||
<el-button @click="togglePathIsSelect">{{ pathIsSelect ? '手动输入' : '快捷选择' }} </el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import pathInfo from "@/pathInfo.json";
|
||||
|
||||
const props = defineProps({
|
||||
component: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['change'])
|
||||
|
||||
const pathOptions = ref([])
|
||||
const tempPath = ref('')
|
||||
const activeComponent = ref('')
|
||||
const pathIsSelect = ref(true)
|
||||
|
||||
const togglePathIsSelect = () => {
|
||||
if(pathIsSelect.value){
|
||||
tempPath.value = activeComponent.value?.join('/')
|
||||
}else{
|
||||
activeComponent.value = tempPath.value.split('/')
|
||||
console.log(activeComponent.value)
|
||||
}
|
||||
|
||||
pathIsSelect.value = !pathIsSelect.value
|
||||
emitChange()
|
||||
}
|
||||
|
||||
function convertToCascaderOptions(data) {
|
||||
const result = [];
|
||||
|
||||
for (const path in data) {
|
||||
const label = data[path];
|
||||
const parts = path.split('/').filter(Boolean);
|
||||
|
||||
// 如果第一个部分是 'src',则从第二个部分开始处理
|
||||
const startIndex = parts[0] === 'src' ? 1 : 0;
|
||||
|
||||
let currentLevel = result;
|
||||
|
||||
for (let i = startIndex; i < parts.length; i++) {
|
||||
const part = parts[i];
|
||||
let node = currentLevel.find(item => item.value === part);
|
||||
|
||||
if (!node) {
|
||||
node = {
|
||||
value: part,
|
||||
label: part,
|
||||
children: []
|
||||
};
|
||||
currentLevel.push(node);
|
||||
}
|
||||
|
||||
if (i === parts.length - 1) {
|
||||
// 如果是路径的最后一部分,设置标签并移除 children
|
||||
node.label = label;
|
||||
delete node.children;
|
||||
}
|
||||
|
||||
currentLevel = node.children || [];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
pathOptions.value = convertToCascaderOptions(pathInfo)
|
||||
initCascader(props.component)
|
||||
})
|
||||
|
||||
const initCascader = (value) => {
|
||||
// 新增的时候
|
||||
if(value === ''){
|
||||
pathIsSelect.value = true
|
||||
return
|
||||
}
|
||||
|
||||
// 编辑的时候,根据路径判断是选择框还是输入框
|
||||
if (pathInfo[`/src/${value}` || pathInfo[value]]) {
|
||||
activeComponent.value = value.split('/').filter(Boolean);
|
||||
tempPath.value = ''
|
||||
pathIsSelect.value = true
|
||||
return
|
||||
}
|
||||
tempPath.value = value
|
||||
activeComponent.value = []
|
||||
pathIsSelect.value = false
|
||||
}
|
||||
|
||||
const emitChange = () => {
|
||||
emits('change', pathIsSelect.value ? activeComponent.value?.join('/') : tempPath.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -165,24 +165,9 @@
|
||||
label="文件路径"
|
||||
prop="component"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.component"
|
||||
filterable
|
||||
allow-create
|
||||
autocomplete="off"
|
||||
style="width: 100%"
|
||||
placeholder="页面:view/xxx/xx.vue 插件:plugin/xx/xx.vue"
|
||||
default-first-option
|
||||
@change="fmtComponent"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item,path) in pathOptions"
|
||||
:key="path"
|
||||
:label="path"
|
||||
:value="path"
|
||||
/>
|
||||
</el-select>
|
||||
<span style="font-size: 12px; margin-right: 12px">如果菜单包含子菜单,请创建router-view二级路由页面或者</span><el-button
|
||||
<components-cascader :component="form.component" @change="fmtComponent" />
|
||||
<span style="font-size: 12px; margin-right: 12px">如果菜单包含子菜单,请创建router-view二级路由页面或者</span>
|
||||
<el-button
|
||||
style="margin-top: 4px"
|
||||
@click="form.component = 'view/routerHolder.vue'"
|
||||
>
|
||||
@@ -556,27 +541,19 @@ import {
|
||||
import icon from '@/view/superAdmin/menu/icon.vue'
|
||||
import WarningBar from '@/components/warningBar/warningBar.vue'
|
||||
import { canRemoveAuthorityBtnApi } from '@/api/authorityBtn'
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import {reactive, ref} from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { QuestionFilled } from '@element-plus/icons-vue'
|
||||
import pathInfo from '@/pathInfo.json'
|
||||
|
||||
import { toDoc } from '@/utils/doc'
|
||||
import { toLowerCase } from '@/utils/stringFun'
|
||||
import {toLowerCase} from "@/utils/stringFun";
|
||||
import ComponentsCascader from "@/view/superAdmin/menu/components/components-cascader.vue";
|
||||
|
||||
import pathInfo from "@/pathInfo.json";
|
||||
|
||||
defineOptions({
|
||||
name: 'Menus',
|
||||
})
|
||||
|
||||
const pathOptions = reactive({})
|
||||
|
||||
onMounted(()=>{
|
||||
for (let pathInfoKey in pathInfo) {
|
||||
// 取消掉最前面的 /src/
|
||||
pathOptions[pathInfoKey.replace(/^\/src\//, '')] = pathInfo[pathInfoKey]
|
||||
}
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
path: [{ required: true, message: '请输入菜单name', trigger: 'blur' }],
|
||||
component: [{ required: true, message: '请输入文件路径', trigger: 'blur' }],
|
||||
@@ -608,9 +585,9 @@ const addParameter = (form) => {
|
||||
})
|
||||
}
|
||||
|
||||
const fmtComponent = () => {
|
||||
form.value.component = form.value.component.replace(/\\/g, '/')
|
||||
form.value.name = toLowerCase(pathOptions[form.value.component])
|
||||
const fmtComponent = (component) => {
|
||||
form.value.component = component.replace(/\\/g, '/')
|
||||
form.value.name = toLowerCase(pathInfo["/src/"+component])
|
||||
form.value.path = form.value.name
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,453 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="gva-search-box">
|
||||
<el-form ref="elSearchFormRef" :inline="true" :model="searchInfo" class="demo-form-inline" :rules="searchRule" @keyup.enter="onSubmit">
|
||||
<el-form-item label="创建日期" prop="createdAt">
|
||||
<template #label>
|
||||
<span>
|
||||
创建日期
|
||||
<el-tooltip content="搜索范围是开始日期(包含)至结束日期(不包含)">
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<el-date-picker v-model="searchInfo.startCreatedAt" type="datetime" placeholder="开始日期" :disabled-date="time=> searchInfo.endCreatedAt ? time.getTime() > searchInfo.endCreatedAt.getTime() : false"></el-date-picker>
|
||||
—
|
||||
<el-date-picker v-model="searchInfo.endCreatedAt" type="datetime" placeholder="结束日期" :disabled-date="time=> searchInfo.startCreatedAt ? time.getTime() < searchInfo.startCreatedAt.getTime() : false"></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="参数名称" prop="name">
|
||||
<el-input v-model="searchInfo.name" placeholder="搜索条件" />
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item label="参数键" prop="key">
|
||||
<el-input v-model="searchInfo.key" placeholder="搜索条件" />
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="showAllQuery">
|
||||
<!-- 将需要控制显示状态的查询条件添加到此范围内 -->
|
||||
</template>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="search" @click="onSubmit">查询</el-button>
|
||||
<el-button icon="refresh" @click="onReset">重置</el-button>
|
||||
<el-button link type="primary" icon="arrow-down" @click="showAllQuery=true" v-if="!showAllQuery">展开</el-button>
|
||||
<el-button link type="primary" icon="arrow-up" @click="showAllQuery=false" v-else>收起</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="gva-table-box">
|
||||
<div class="gva-btn-list">
|
||||
<el-button type="primary" icon="plus" @click="openDialog">新增</el-button>
|
||||
<el-button icon="delete" style="margin-left: 10px;" :disabled="!multipleSelection.length" @click="onDelete">删除</el-button>
|
||||
|
||||
</div>
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
style="width: 100%"
|
||||
tooltip-effect="dark"
|
||||
:data="tableData"
|
||||
row-key="ID"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
|
||||
<el-table-column align="left" label="日期" prop="createdAt" width="180">
|
||||
<template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="left" label="参数名称" prop="name" width="120" />
|
||||
<el-table-column align="left" label="参数键" prop="key" width="120" />
|
||||
<el-table-column align="left" label="参数值" prop="value" width="120" />
|
||||
<el-table-column align="left" label="参数说明" prop="desc" width="120" />
|
||||
<el-table-column align="left" label="操作" fixed="right" min-width="240">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link class="table-button" @click="getDetails(scope.row)"><el-icon style="margin-right: 5px"><InfoFilled /></el-icon>查看详情</el-button>
|
||||
<el-button type="primary" link icon="edit" class="table-button" @click="updateSysParamsFunc(scope.row)">变更</el-button>
|
||||
<el-button type="primary" link icon="delete" @click="deleteRow(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="gva-pagination">
|
||||
<el-pagination
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-drawer destroy-on-close size="800" v-model="dialogFormVisible" :show-close="false" :before-close="closeDialog">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-lg">{{type==='create'?'添加':'修改'}}</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="enterDialog">确 定</el-button>
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-form :model="formData" label-position="top" ref="elFormRef" :rules="rule" label-width="80px">
|
||||
<el-form-item label="参数名称:" prop="name" >
|
||||
<el-input v-model="formData.name" :clearable="true" placeholder="请输入参数名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数键:" prop="key" >
|
||||
<el-input v-model="formData.key" :clearable="true" placeholder="请输入参数键" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数值:" prop="value" >
|
||||
<el-input type="textarea" :rows="5" v-model="formData.value" :clearable="true" placeholder="请输入参数值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数说明:" prop="desc" >
|
||||
<el-input v-model="formData.desc" :clearable="true" placeholder="请输入参数说明" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="usage-instructions bg-gray-100 border border-gray-300 rounded-lg p-4 mt-5">
|
||||
<h3 class="mb-3 text-lg text-gray-800">使用说明</h3>
|
||||
<p class="mb-2 text-sm text-gray-600">
|
||||
前端可以通过引入 <code class="bg-blue-100 px-1 py-0.5 rounded">import { getParams } from '@/utils/dictionary'</code> 然后通过 <code class="bg-blue-100 px-1 py-0.5 rounded">await getParams(key)</code> 来获取对应的参数。
|
||||
</p>
|
||||
<p class="mb-2 text-sm text-gray-600">
|
||||
后端可以调用 <code class="bg-blue-100 px-1 py-0.5 rounded">new(system.SysParamsService).GetSysParam(key)</code> 来获取对应的 value 值。
|
||||
</p>
|
||||
<p class="text-sm text-gray-600">
|
||||
后端需要提前 <code class="bg-blue-100 px-1 py-0.5 rounded">import "github.com/flipped-aurora/gin-vue-admin/server/service/system"</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</el-drawer>
|
||||
|
||||
<el-drawer destroy-on-close size="800" v-model="detailShow" :show-close="true" :before-close="closeDetailShow">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="参数名称">
|
||||
{{ detailFrom.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="参数键">
|
||||
{{ detailFrom.key }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="参数值">
|
||||
{{ detailFrom.value }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="参数说明">
|
||||
{{ detailFrom.desc }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-drawer>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
createSysParams,
|
||||
deleteSysParams,
|
||||
deleteSysParamsByIds,
|
||||
updateSysParams,
|
||||
findSysParams,
|
||||
getSysParamsList
|
||||
} from '@/api/sysParams'
|
||||
|
||||
// 全量引入格式化工具 请按需保留
|
||||
import { getDictFunc, formatDate, formatBoolean, filterDict ,filterDataSource, returnArrImg, onDownloadFile } from '@/utils/format'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'SysParams'
|
||||
})
|
||||
|
||||
// 控制更多查询条件显示/隐藏状态
|
||||
const showAllQuery = ref(false)
|
||||
|
||||
// 自动化生成的字典(可能为空)以及字段
|
||||
const formData = ref({
|
||||
name: '',
|
||||
key: '',
|
||||
value: '',
|
||||
desc: '',
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 验证规则
|
||||
const rule = reactive({
|
||||
name : [{
|
||||
required: true,
|
||||
message: '',
|
||||
trigger: ['input','blur'],
|
||||
},
|
||||
{
|
||||
whitespace: true,
|
||||
message: '不能只输入空格',
|
||||
trigger: ['input', 'blur'],
|
||||
}
|
||||
],
|
||||
key : [{
|
||||
required: true,
|
||||
message: '',
|
||||
trigger: ['input','blur'],
|
||||
},
|
||||
{
|
||||
whitespace: true,
|
||||
message: '不能只输入空格',
|
||||
trigger: ['input', 'blur'],
|
||||
}
|
||||
],
|
||||
value : [{
|
||||
required: true,
|
||||
message: '',
|
||||
trigger: ['input','blur'],
|
||||
},
|
||||
{
|
||||
whitespace: true,
|
||||
message: '不能只输入空格',
|
||||
trigger: ['input', 'blur'],
|
||||
}
|
||||
],
|
||||
})
|
||||
|
||||
const searchRule = reactive({
|
||||
createdAt: [
|
||||
{ validator: (rule, value, callback) => {
|
||||
if (searchInfo.value.startCreatedAt && !searchInfo.value.endCreatedAt) {
|
||||
callback(new Error('请填写结束日期'))
|
||||
} else if (!searchInfo.value.startCreatedAt && searchInfo.value.endCreatedAt) {
|
||||
callback(new Error('请填写开始日期'))
|
||||
} else if (searchInfo.value.startCreatedAt && searchInfo.value.endCreatedAt && (searchInfo.value.startCreatedAt.getTime() === searchInfo.value.endCreatedAt.getTime() || searchInfo.value.startCreatedAt.getTime() > searchInfo.value.endCreatedAt.getTime())) {
|
||||
callback(new Error('开始日期应当早于结束日期'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}, trigger: 'change' }
|
||||
],
|
||||
})
|
||||
|
||||
const elFormRef = ref()
|
||||
const elSearchFormRef = ref()
|
||||
|
||||
// =========== 表格控制部分 ===========
|
||||
const page = ref(1)
|
||||
const total = ref(0)
|
||||
const pageSize = ref(10)
|
||||
const tableData = ref([])
|
||||
const searchInfo = ref({})
|
||||
|
||||
// 重置
|
||||
const onReset = () => {
|
||||
searchInfo.value = {}
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const onSubmit = () => {
|
||||
elSearchFormRef.value?.validate(async(valid) => {
|
||||
if (!valid) return
|
||||
page.value = 1
|
||||
pageSize.value = 10
|
||||
getTableData()
|
||||
})
|
||||
}
|
||||
|
||||
// 分页
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 修改页面容量
|
||||
const handleCurrentChange = (val) => {
|
||||
page.value = val
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 查询
|
||||
const getTableData = async() => {
|
||||
const table = await getSysParamsList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
|
||||
if (table.code === 0) {
|
||||
tableData.value = table.data.list
|
||||
total.value = table.data.total
|
||||
page.value = table.data.page
|
||||
pageSize.value = table.data.pageSize
|
||||
}
|
||||
}
|
||||
|
||||
getTableData()
|
||||
|
||||
// ============== 表格控制部分结束 ===============
|
||||
|
||||
// 获取需要的字典 可能为空 按需保留
|
||||
const setOptions = async () =>{
|
||||
}
|
||||
|
||||
// 获取需要的字典 可能为空 按需保留
|
||||
setOptions()
|
||||
|
||||
|
||||
// 多选数据
|
||||
const multipleSelection = ref([])
|
||||
// 多选
|
||||
const handleSelectionChange = (val) => {
|
||||
multipleSelection.value = val
|
||||
}
|
||||
|
||||
// 删除行
|
||||
const deleteRow = (row) => {
|
||||
ElMessageBox.confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteSysParamsFunc(row)
|
||||
})
|
||||
}
|
||||
|
||||
// 多选删除
|
||||
const onDelete = async() => {
|
||||
ElMessageBox.confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async() => {
|
||||
const IDs = []
|
||||
if (multipleSelection.value.length === 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: '请选择要删除的数据'
|
||||
})
|
||||
return
|
||||
}
|
||||
multipleSelection.value &&
|
||||
multipleSelection.value.map(item => {
|
||||
IDs.push(item.ID)
|
||||
})
|
||||
const res = await deleteSysParamsByIds({ IDs })
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功'
|
||||
})
|
||||
if (tableData.value.length === IDs.length && page.value > 1) {
|
||||
page.value--
|
||||
}
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 行为控制标记(弹窗内部需要增还是改)
|
||||
const type = ref('')
|
||||
|
||||
// 更新行
|
||||
const updateSysParamsFunc = async(row) => {
|
||||
const res = await findSysParams({ ID: row.ID })
|
||||
type.value = 'update'
|
||||
if (res.code === 0) {
|
||||
formData.value = res.data
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 删除行
|
||||
const deleteSysParamsFunc = async (row) => {
|
||||
const res = await deleteSysParams({ ID: row.ID })
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功'
|
||||
})
|
||||
if (tableData.value.length === 1 && page.value > 1) {
|
||||
page.value--
|
||||
}
|
||||
getTableData()
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗控制标记
|
||||
const dialogFormVisible = ref(false)
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = () => {
|
||||
type.value = 'create'
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
dialogFormVisible.value = false
|
||||
formData.value = {
|
||||
name: '',
|
||||
key: '',
|
||||
value: '',
|
||||
desc: '',
|
||||
}
|
||||
}
|
||||
// 弹窗确定
|
||||
const enterDialog = async () => {
|
||||
elFormRef.value?.validate( async (valid) => {
|
||||
if (!valid) return
|
||||
let res
|
||||
switch (type.value) {
|
||||
case 'create':
|
||||
res = await createSysParams(formData.value)
|
||||
break
|
||||
case 'update':
|
||||
res = await updateSysParams(formData.value)
|
||||
break
|
||||
default:
|
||||
res = await createSysParams(formData.value)
|
||||
break
|
||||
}
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '创建/更改成功'
|
||||
})
|
||||
closeDialog()
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const detailFrom = ref({})
|
||||
|
||||
// 查看详情控制标记
|
||||
const detailShow = ref(false)
|
||||
|
||||
|
||||
// 打开详情弹窗
|
||||
const openDetailShow = () => {
|
||||
detailShow.value = true
|
||||
}
|
||||
|
||||
|
||||
// 打开详情
|
||||
const getDetails = async (row) => {
|
||||
// 打开弹窗
|
||||
const res = await findSysParams({ ID: row.ID })
|
||||
if (res.code === 0) {
|
||||
detailFrom.value = res.data
|
||||
openDetailShow()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 关闭详情弹窗
|
||||
const closeDetailShow = () => {
|
||||
detailShow.value = false
|
||||
detailFrom.value = {}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -5,26 +5,27 @@
|
||||
title="此功能为开发环境使用,不建议发布到生产,具体使用效果请点我观看。"
|
||||
/>
|
||||
<div class="gva-search-box">
|
||||
<div class="text-lg mb-2 text-gray-600">使用AI创建</div>
|
||||
<div class="text-lg mb-2 text-gray-600">使用AI创建<a class="text-blue-600 text-sm ml-4" href="https://plugin.gin-vue-admin.com/#/layout/userInfo/center" target="_blank">获取AiPath</a></div>
|
||||
<div class="relative">
|
||||
<el-input v-model="prompt" type="textarea" :rows="5" :maxlength="100" :placeholder="`【Beta】试试描述你的表,让AI帮你完成。\n目前正在测试阶段,遇到问题请及时反馈。\n此功能需要到插件市场个人中心获取自己的AI-Path,把AI-Path填入config.yaml下的autocode-->ai-path,重启项目即可使用。`" resize="none" />
|
||||
<el-input v-model="prompt"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
:maxlength="100"
|
||||
:placeholder="`现已完全免费\n试试描述你的表,让AI帮你完成。\n此功能需要到插件市场个人中心获取自己的AI-Path,把AI-Path填入config.yaml下的autocode-->ai-path,重启项目即可使用。\n按下 Ctrl+Enter 或 Cmd+Enter 直接生成`"
|
||||
resize="none"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"/>
|
||||
<div class="flex absolute right-2 bottom-2">
|
||||
<el-tooltip
|
||||
content="小奇存在失败概率,面向所有用户开放使用(失败了重新生成一下就好)。"
|
||||
effect="light"
|
||||
>
|
||||
<el-button type="primary" @click="llmAutoFunc('xiaoqi')">
|
||||
<template #content>
|
||||
<div>【完全免费】前往<a class="text-blue-600" href="https://plugin.gin-vue-admin.com/#/layout/userInfo/center" target="_blank">插件市场个人中心</a>申请AIPath,填入config.yaml的ai-path属性即可使用。</div>
|
||||
</template>
|
||||
<el-button type="primary" @click="llmAutoFunc()">
|
||||
<el-icon size="18">
|
||||
<ai-gva />
|
||||
</el-icon> 小奇
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="小淼基本啥也能设计出来,但是需要消耗积分,测试阶段授权用户自动获得基础积分,开源用户需要填表申请。"
|
||||
>
|
||||
<el-button type="primary" @click="llmAutoFunc('xiaomiao')">
|
||||
<el-icon size="18">
|
||||
<ai-gva />
|
||||
</el-icon> 小淼
|
||||
</el-icon> 生成
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
@@ -156,10 +157,17 @@
|
||||
prop="structName"
|
||||
class="w-full"
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<el-input
|
||||
v-model="form.structName"
|
||||
placeholder="首字母自动转换大写"
|
||||
/>
|
||||
<el-button type="primary" @click="llmAutoFunc(true)">
|
||||
<el-icon size="18">
|
||||
<ai-gva />
|
||||
</el-icon> 生成
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
@@ -420,6 +428,7 @@
|
||||
row-key="fieldName"
|
||||
>
|
||||
<el-table-column
|
||||
fixed="left"
|
||||
align="left"
|
||||
type="index"
|
||||
width="60"
|
||||
@@ -431,12 +440,14 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="left"
|
||||
align="left"
|
||||
type="index"
|
||||
label="序列"
|
||||
width="60"
|
||||
/>
|
||||
<el-table-column
|
||||
fixed="left"
|
||||
align="left"
|
||||
type="index"
|
||||
label="主键"
|
||||
@@ -447,6 +458,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="left"
|
||||
align="left"
|
||||
prop="fieldName"
|
||||
label="字段名称"
|
||||
@@ -525,6 +537,7 @@
|
||||
<el-table-column
|
||||
align="left"
|
||||
prop="excel"
|
||||
width="100"
|
||||
label="导入/导出"
|
||||
>
|
||||
<template #default="{row}">
|
||||
@@ -791,6 +804,21 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import WarningBar from '@/components/warningBar/warningBar.vue'
|
||||
import Sortable from 'sortablejs'
|
||||
|
||||
const handleFocus = () => {
|
||||
document.addEventListener('keydown', handleKeydown);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
document.removeEventListener('keydown', handleKeydown);
|
||||
};
|
||||
|
||||
|
||||
const handleKeydown = (event) => {
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') {
|
||||
llmAutoFunc();
|
||||
}
|
||||
};
|
||||
|
||||
const getOnlyNumber = () => {
|
||||
let randomNumber = '';
|
||||
while (randomNumber.length < 16) {
|
||||
@@ -801,51 +829,21 @@ const getOnlyNumber = () => {
|
||||
|
||||
const prompt = ref("")
|
||||
|
||||
const llmAutoFunc = async (mode) =>{
|
||||
const res = await llmAuto({prompt:prompt.value,mode:mode})
|
||||
const llmAutoFunc = async (flag) =>{
|
||||
if (flag&&!form.value.structName) {
|
||||
ElMessage.error('请输入结构体名称')
|
||||
return
|
||||
}
|
||||
if (!flag&&!prompt.value) {
|
||||
ElMessage.error('请输入描述')
|
||||
return
|
||||
}
|
||||
const res = await llmAuto({prompt:flag?'结构体名称为'+form.value.structName:prompt.value})
|
||||
if (res.code === 0) {
|
||||
form.value.fields = []
|
||||
const json = JSON.parse(res.data)
|
||||
for (let key in json){
|
||||
if(key === "fields"){
|
||||
json[key].forEach(item => {
|
||||
if (item.primaryKey) {
|
||||
form.value.gvaModel = false
|
||||
}
|
||||
form.value.fields.push({
|
||||
onlyNumber: getOnlyNumber(),
|
||||
fieldName: toUpperCase(item.fieldName),
|
||||
fieldDesc: item.fieldDesc,
|
||||
fieldType: item.fieldType,
|
||||
dataType: "",
|
||||
fieldJson: item.fieldJson||item.columnName,
|
||||
primaryKey: item.primaryKey,
|
||||
dataTypeLong: item.dataTypeLong,
|
||||
columnName: item.columnName,
|
||||
comment: item.comment || item.fieldDesc,
|
||||
require: false,
|
||||
errorText: '',
|
||||
clearable: true,
|
||||
fieldSearchType: '',
|
||||
fieldIndexType: '',
|
||||
dictType: '',
|
||||
form: true,
|
||||
desc: true,
|
||||
table: true,
|
||||
excel: false,
|
||||
dataSource: {
|
||||
association:1,
|
||||
table: '',
|
||||
label: '',
|
||||
value: ''
|
||||
}
|
||||
})
|
||||
})
|
||||
}else{
|
||||
if(mode === "xiaomiao"){
|
||||
form.value[key] = json[key]
|
||||
}
|
||||
}
|
||||
form.value[key] = json[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,8 +193,11 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否鉴权:">
|
||||
<el-switch v-model="autoFunc.isAuth" active-text="是" inactive-text="否" />
|
||||
</el-form-item>
|
||||
<el-form-item label="路由path:">
|
||||
<el-input v-model="autoFunc.router" placeholder="路由path" />
|
||||
<el-input v-model="autoFunc.router" placeholder="路由path" @input="autoFunc.router = autoFunc.router.replace(/\//g, '')" />
|
||||
<div>API路径: [{{ autoFunc.method }}] /{{ autoFunc.abbreviation }}/{{ autoFunc.router }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -241,7 +244,8 @@ const autoFunc = ref({
|
||||
humpPackageName:"",
|
||||
businessDB:"",
|
||||
method:"",
|
||||
funcDesc: ""
|
||||
funcDesc: "",
|
||||
isAuth:false,
|
||||
})
|
||||
|
||||
const addFuncBtn = (row) => {
|
||||
|
||||
@@ -211,6 +211,8 @@
|
||||
label-position="right"
|
||||
:rules="rule"
|
||||
label-width="100px"
|
||||
v-loading="aiLoading"
|
||||
element-loading-text="小淼正在思考..."
|
||||
>
|
||||
|
||||
<el-form-item
|
||||
@@ -248,25 +250,30 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
label="模板名称:"
|
||||
prop="name"
|
||||
label="AI帮写:"
|
||||
prop="ai"
|
||||
>
|
||||
<el-input
|
||||
v-model="formData.name"
|
||||
:clearable="true"
|
||||
placeholder="请输入模板名称"
|
||||
/>
|
||||
<div class="relative w-full">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="prompt"
|
||||
:clearable="true"
|
||||
:rows="5"
|
||||
placeholder="试试描述你要做的导出功能让AI帮你完成,在此之前请选择你需要导出的表所在的业务库,如不做选择,则默认使用gva库"
|
||||
/>
|
||||
<el-button
|
||||
class="absolute bottom-2 right-2"
|
||||
type="primary"
|
||||
@click="autoExport"
|
||||
><el-icon><ai-gva /></el-icon>帮写</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
label="表名称:"
|
||||
clearable
|
||||
prop="tableName"
|
||||
label="表名称:"
|
||||
clearable
|
||||
prop="tableName"
|
||||
>
|
||||
<!-- <el-input
|
||||
v-model="formData.tableName"
|
||||
:clearable="true"
|
||||
placeholder="请输入要导出的表名称"
|
||||
/>-->
|
||||
<div
|
||||
class="w-full flex gap-4"
|
||||
>
|
||||
@@ -283,11 +290,22 @@
|
||||
:value="item.tableName"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-button type="primary" @click="getColumnFunc">自动生成模板</el-button>
|
||||
<el-button :disabled="!formData.tableName" type="primary" @click="getColumnFunc(true)"><el-icon><ai-gva/></el-icon>自动补全</el-button>
|
||||
<el-button :disabled="!formData.tableName" type="primary" @click="getColumnFunc(false)">自动生成模板</el-button>
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
label="模板名称:"
|
||||
prop="name"
|
||||
>
|
||||
<el-input
|
||||
v-model="formData.name"
|
||||
:clearable="true"
|
||||
placeholder="请输入模板名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
label="模板标识:"
|
||||
prop="templateID"
|
||||
@@ -438,7 +456,7 @@ import { formatDate } from '@/utils/format'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ref, reactive } from 'vue'
|
||||
import WarningBar from '@/components/warningBar/warningBar.vue'
|
||||
import {getDB, getTable, getColumn} from '@/api/autoCode'
|
||||
import {getDB, getTable, getColumn, butler} from '@/api/autoCode'
|
||||
|
||||
defineOptions({
|
||||
name: 'ExportTemplate'
|
||||
@@ -469,6 +487,8 @@ const formData = ref({
|
||||
joinTemplate: []
|
||||
})
|
||||
|
||||
const prompt = ref('')
|
||||
|
||||
const typeSearchOptions = ref([
|
||||
{
|
||||
label: '=',
|
||||
@@ -592,6 +612,24 @@ const searchInfo = ref({})
|
||||
|
||||
const dbList = ref([])
|
||||
const tableOptions = ref([])
|
||||
const aiLoading = ref(false)
|
||||
|
||||
|
||||
const autoExport = async () => {
|
||||
aiLoading.value = true
|
||||
const tables = tableOptions.value.map(item => item.tableName)
|
||||
const aiRes = await butler({prompt:prompt.value,businessDB: formData.value.dbName||"",tables:tables,command:'autoExportTemplate'})
|
||||
aiLoading.value = false
|
||||
if (aiRes.code === 0) {
|
||||
const aiData = JSON.parse(aiRes.data)
|
||||
formData.value.name = aiData.name
|
||||
formData.value.tableName = aiData.tableName
|
||||
formData.value.templateID = aiData.templateID
|
||||
formData.value.templateInfo = JSON.stringify(aiData.templateInfo, null, 2)
|
||||
formData.value.joinTemplate = aiData.joinTemplate
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const getDbFunc = async() => {
|
||||
const res = await getDB()
|
||||
@@ -616,8 +654,7 @@ const getTableFunc = async() => {
|
||||
formData.value.tableName = ''
|
||||
}
|
||||
getTableFunc()
|
||||
|
||||
const getColumnFunc = async () => {
|
||||
const getColumnFunc = async (aiFLag) => {
|
||||
if(!formData.value.tableName) {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
@@ -626,11 +663,26 @@ const getColumnFunc = async () => {
|
||||
return
|
||||
}
|
||||
formData.value.templateInfo = ""
|
||||
aiLoading.value = true
|
||||
const res = await getColumn({
|
||||
businessDB: formData.value.dbName,
|
||||
tableName: formData.value.tableName
|
||||
})
|
||||
if(res.code === 0) {
|
||||
if(aiFLag){
|
||||
const aiRes = await butler({data:res.data.columns,command:'exportCompletion'})
|
||||
if (aiRes.code === 0) {
|
||||
const aiData = JSON.parse(aiRes.data)
|
||||
aiLoading.value = false
|
||||
formData.value.templateInfo = JSON.stringify(aiData.templateInfo, null, 2)
|
||||
formData.value.name = aiData.name
|
||||
formData.value.templateID = aiData.templateID
|
||||
return
|
||||
}
|
||||
ElMessage.warning('AI自动补全失败,已调整为逻辑填写')
|
||||
}
|
||||
|
||||
|
||||
// 把返回值的data.columns做尊换,制作一组JSON数据,columnName做key,columnComment做value
|
||||
const templateInfo = {}
|
||||
res.data.columns.forEach(item => {
|
||||
@@ -638,6 +690,7 @@ const getColumnFunc = async () => {
|
||||
})
|
||||
formData.value.templateInfo = JSON.stringify(templateInfo, null, 2)
|
||||
}
|
||||
aiLoading.value = false
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user