From 1d858118d5168243295a7d8c9594d84daf88a50f Mon Sep 17 00:00:00 2001 From: "meilin.huang" <954537473@qq.com> Date: Thu, 13 Apr 2023 20:11:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=8F=9C=E5=8D=95=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=96=B9=E5=BC=8F=E8=B0=83=E6=95=B4=E3=80=81?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96=E3=80=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=B0=E5=A2=9E=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mayfly_go_web/src/common/Api.ts | 39 ++++++++- mayfly_go_web/src/common/openApi.ts | 16 ++-- mayfly_go_web/src/common/request.ts | 7 +- mayfly_go_web/src/common/rsa.ts | 2 +- mayfly_go_web/src/common/sysconfig.ts | 2 +- mayfly_go_web/src/router/index.ts | 74 +++++++++------- mayfly_go_web/src/store/userInfo.ts | 2 +- mayfly_go_web/src/views/home/api.ts | 2 +- .../views/login/component/AccountLogin.vue | 29 ++----- mayfly_go_web/src/views/ops/db/SqlExec.vue | 2 +- mayfly_go_web/src/views/ops/db/api.ts | 36 ++++---- .../views/ops/db/component/tab/TableData.vue | 87 +++++++++++++++---- mayfly_go_web/src/views/ops/db/db.ts | 11 ++- mayfly_go_web/src/views/ops/machine/api.ts | 60 ++++++------- mayfly_go_web/src/views/ops/mongo/api.ts | 20 ++--- mayfly_go_web/src/views/ops/redis/api.ts | 42 ++++----- mayfly_go_web/src/views/ops/tag/api.ts | 26 +++--- mayfly_go_web/src/views/personal/api.ts | 6 +- mayfly_go_web/src/views/system/api.ts | 52 +++++------ server/go.mod | 4 +- server/internal/sys/api/account.go | 38 ++++---- server/internal/sys/router/account.go | 5 ++ 22 files changed, 329 insertions(+), 233 deletions(-) diff --git a/mayfly_go_web/src/common/Api.ts b/mayfly_go_web/src/common/Api.ts index ba22ddcc..62b55efd 100644 --- a/mayfly_go_web/src/common/Api.ts +++ b/mayfly_go_web/src/common/Api.ts @@ -28,7 +28,7 @@ class Api { /** * 操作该权限,即请求对应的url - * @param {Object} param 请求该权限的参数 + * @param {Object} param 请求该api的参数 */ request(param: any = null, options: any = null): Promise { return request.send(this, param, options); @@ -36,7 +36,8 @@ class Api { /** * 操作该权限,即请求对应的url - * @param {Object} param 请求该权限的参数 + * @param {Object} param 请求该api的参数 + * @param headers headers */ requestWithHeaders(param: any, headers: any): Promise { return request.sendWithHeaders(this, param, headers); @@ -50,9 +51,41 @@ class Api { * @param url url * @param method 请求方法(get,post,put,delete...) */ - static create(url: string, method: string) { + static create(url: string, method: string) :Api { return new Api(url, method); } + + /** + * 创建get api + * @param url url + */ + static newGet(url: string): Api { + return Api.create(url, 'get'); + } + + /** + * new post api + * @param url url + */ + static newPost(url: string): Api { + return Api.create(url, 'post'); + } + + /** + * new put api + * @param url url + */ + static newPut(url: string): Api { + return Api.create(url, 'put'); + } + + /** + * new delete api + * @param url url + */ + static newDelete(url: string): Api { + return Api.create(url, 'delete'); + } } diff --git a/mayfly_go_web/src/common/openApi.ts b/mayfly_go_web/src/common/openApi.ts index de8fa114..c5cf61ef 100644 --- a/mayfly_go_web/src/common/openApi.ts +++ b/mayfly_go_web/src/common/openApi.ts @@ -1,11 +1,11 @@ -import request from './request' +import Api from './Api' export default { - login: (param: any) => request.request('POST', '/sys/accounts/login', param), - changePwd: (param: any) => request.request('POST', '/sys/accounts/change-pwd', param), - getPublicKey: () => request.request('GET', '/common/public-key'), - getConfigValue: (param: any) => request.request('GET', '/sys/configs/value', param), - captcha: () => request.request('GET', '/sys/captcha'), - logout: (param: any) => request.request('POST', '/sys/accounts/logout/{token}', param), - getMenuRoute: (param: any) => request.request('Get', '/sys/resources/account', param) + login: Api.newPost("/sys/accounts/login"), + changePwd: Api.newPost("/sys/accounts/change-pwd"), + getPublicKey: Api.newGet("/common/public-key"), + getConfigValue: Api.newGet("/sys/configs/value"), + captcha: Api.newGet("/sys/captcha"), + logout: Api.newPost("/sys/accounts/logout/{token}"), + getPermissions: Api.newGet("/sys/accounts/permissions") } \ No newline at end of file diff --git a/mayfly_go_web/src/common/request.ts b/mayfly_go_web/src/common/request.ts index 149f0760..a0ae7aad 100755 --- a/mayfly_go_web/src/common/request.ts +++ b/mayfly_go_web/src/common/request.ts @@ -22,7 +22,8 @@ export interface Result { data?: any; } -const baseUrl: string = config.baseApiUrl as string +const baseUrl: string = config.baseApiUrl +const baseWsUrl: string = config.baseWsUrl /** * 通知错误消息 @@ -115,9 +116,8 @@ function request(method: string, url: string, params: any = null, headers: any = query.headers = headers } - const lowMethod = method.toLowerCase(); // post和put使用json格式传参 - if (lowMethod === 'post' || lowMethod === 'put') { + if (method === 'post' || method === 'put') { query.data = params; } else { query.params = params; @@ -155,6 +155,7 @@ function getApiUrl(url: string) { return baseUrl + url + '?token=' + getSession('token'); } + export default { request, send, diff --git a/mayfly_go_web/src/common/rsa.ts b/mayfly_go_web/src/common/rsa.ts index daac4671..691435df 100644 --- a/mayfly_go_web/src/common/rsa.ts +++ b/mayfly_go_web/src/common/rsa.ts @@ -9,7 +9,7 @@ export async function getRsaPublicKey() { if (publicKey) { return publicKey } - publicKey = await openApi.getPublicKey() as string + publicKey = await openApi.getPublicKey.request() as string sessionStorage.setItem('RsaPublicKey', publicKey) return publicKey } diff --git a/mayfly_go_web/src/common/sysconfig.ts b/mayfly_go_web/src/common/sysconfig.ts index f4c1a77d..60e25058 100644 --- a/mayfly_go_web/src/common/sysconfig.ts +++ b/mayfly_go_web/src/common/sysconfig.ts @@ -11,7 +11,7 @@ const UseWartermarkConfigKey = "UseWartermark" * @returns 配置值 */ export async function getConfigValue(key: string) : Promise { - return await openApi.getConfigValue({key}) as string + return await openApi.getConfigValue.request({key}) as string } /** diff --git a/mayfly_go_web/src/router/index.ts b/mayfly_go_web/src/router/index.ts index 637d9b6e..b56325c4 100644 --- a/mayfly_go_web/src/router/index.ts +++ b/mayfly_go_web/src/router/index.ts @@ -46,8 +46,8 @@ export function initAllFun() { useRoutesList().setRoutesList(setFilterMenuFun(dynamicRoutes[0].children, useUserInfo().userInfo.menus)) } -// 后端控制路由:模拟执行路由数据初始化 -export function initBackEndControlRoutesFun() { +// 后端控制路由:执行路由数据初始化 +export async function initBackEndControlRoutesFun() { NextLoading.start(); // 界面 loading 动画开始执行 const token = getSession('token'); // 获取浏览器缓存 token 值 if (!token) { @@ -55,11 +55,8 @@ export function initBackEndControlRoutesFun() { return false } useUserInfo().setUserInfo({}); - let menuRoute = getSession('menus') - if (!menuRoute) { - menuRoute = getBackEndControlRoutes(); // 获取路由 - // const oldRoutes = res; // 获取接口原始路由(未处理component) - } + // 获取路由 + let menuRoute = await getBackEndControlRoutes(); dynamicRoutes[0].children = backEndRouterConverter(menuRoute); // 处理路由(component) // 添加404界面 router.addRoute(pathMatch); @@ -72,8 +69,16 @@ export function initBackEndControlRoutesFun() { } // 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 -export function getBackEndControlRoutes() { - return openApi.getMenuRoute({}); +export async function getBackEndControlRoutes() { + try { + const menuAndPermission = await openApi.getPermissions.request(); + // 赋值权限码,用于控制按钮等 + useUserInfo().userInfo.permissions = menuAndPermission.permissions; + return menuAndPermission.menus; + } catch (e: any) { + console.error(e); + return [] + } } // 后端控制路由,后端返回路由 转换为vue route @@ -124,18 +129,18 @@ export function backEndRouterConverter(routes: any, parentPath: string = "/") { * @returns 返回处理成函数后的 component */ export function dynamicImport(dynamicViewsModules: Record, component: string) { - const keys = Object.keys(dynamicViewsModules); - const matchKeys = keys.filter((key) => { - const k = key.replace(/..\/views|../, ''); - return k.startsWith(`${component}`) || k.startsWith(`/${component}`); - }); - if (matchKeys?.length === 1) { - const matchKey = matchKeys[0]; - return dynamicViewsModules[matchKey]; - } - if (matchKeys?.length > 1) { - return false; - } + const keys = Object.keys(dynamicViewsModules); + const matchKeys = keys.filter((key) => { + const k = key.replace(/..\/views|../, ''); + return k.startsWith(`${component}`) || k.startsWith(`/${component}`); + }); + if (matchKeys?.length === 1) { + const matchKey = matchKeys[0]; + return dynamicViewsModules[matchKey]; + } + if (matchKeys?.length > 1) { + return false; + } } // 多级嵌套数组处理成一维数组 @@ -167,7 +172,6 @@ export function formatTwoStageRoutes(arr: any) { } }); useKeepALiveNames().setCacheKeepAlive(cacheList); - // store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList); return newArr; } @@ -227,21 +231,22 @@ export function resetRoute() { }); } -// 初始化方法执行 -const { isRequestRoutes } = useThemeConfig(pinia).themeConfig; -if (!isRequestRoutes) { - // 未开启后端控制路由 - initAllFun(); -} else if (isRequestRoutes) { - // 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 - initBackEndControlRoutesFun(); +export async function initRouter() { + // 初始化方法执行 + const { isRequestRoutes } = useThemeConfig(pinia).themeConfig; + if (!isRequestRoutes) { + // 未开启后端控制路由 + initAllFun(); + } else if (isRequestRoutes) { + // 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 + await initBackEndControlRoutesFun(); + } } - let SysWs: any; // 路由加载前 -router.beforeEach((to, from, next) => { +router.beforeEach(async (to, from, next) => { NProgress.configure({ showSpinner: false }); if (to.meta.title) NProgress.start(); @@ -278,7 +283,10 @@ router.beforeEach((to, from, next) => { if (!SysWs && to.path != '/machine/terminal') { SysWs = sockets.sysMsgSocket(); } - if (useRoutesList().routesList.length > 0) { + if (useRoutesList().routesList.length == 0) { + await initRouter(); + next({ path: to.path, query: to.query }); + } else { next(); } }); diff --git a/mayfly_go_web/src/store/userInfo.ts b/mayfly_go_web/src/store/userInfo.ts index fae8ce99..c75fbb8a 100644 --- a/mayfly_go_web/src/store/userInfo.ts +++ b/mayfly_go_web/src/store/userInfo.ts @@ -1,5 +1,5 @@ import { defineStore } from 'pinia'; -import { getSession } from '@/common/utils/storage.ts'; +import { getSession } from '@/common/utils/storage'; export const useUserInfo = defineStore('userInfo', { state: (): UserInfoState => ({ diff --git a/mayfly_go_web/src/views/home/api.ts b/mayfly_go_web/src/views/home/api.ts index 91436e9b..2553330b 100644 --- a/mayfly_go_web/src/views/home/api.ts +++ b/mayfly_go_web/src/views/home/api.ts @@ -1,6 +1,6 @@ import Api from '@/common/Api'; export const indexApi = { - getIndexCount: Api.create("/common/index/count", 'get'), + getIndexCount: Api.newGet("/common/index/count"), } diff --git a/mayfly_go_web/src/views/login/component/AccountLogin.vue b/mayfly_go_web/src/views/login/component/AccountLogin.vue index b4114f55..a7440bd7 100644 --- a/mayfly_go_web/src/views/login/component/AccountLogin.vue +++ b/mayfly_go_web/src/views/login/component/AccountLogin.vue @@ -63,7 +63,7 @@ import { nextTick, onMounted, ref, toRefs, reactive, computed } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import { ElMessage } from 'element-plus'; -import { initBackEndControlRoutesFun } from '@/router/index'; +import { initRouter } from '@/router/index'; import { setSession, setUserInfo2Session, setUseWatermark2Session } from '@/common/utils/storage'; import { formatAxis } from '@/common/utils/format'; import openApi from '@/common/openApi'; @@ -71,7 +71,6 @@ import { RsaEncrypt } from '@/common/rsa'; import { useLoginCaptcha, useWartermark } from '@/common/sysconfig'; import { letterAvatar } from '@/common/utils/string'; import { useUserInfo } from '@/store/userInfo'; -import { useThemeConfig } from '@/store/themeConfig'; const rules = { username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], @@ -138,7 +137,7 @@ const getCaptcha = async () => { if (!state.isUseLoginCaptcha) { return; } - let res: any = await openApi.captcha(); + let res: any = await openApi.captcha.request(); state.captchaImage = res.base64Captcha; state.loginForm.cid = res.cid; }; @@ -167,10 +166,9 @@ const onSignIn = async () => { try { const loginReq = { ...state.loginForm }; loginReq.password = await RsaEncrypt(originPwd); - loginRes = await openApi.login(loginReq); + loginRes = await openApi.login.request(loginReq); // 存储 token 到浏览器缓存 setSession('token', loginRes.token); - setSession('menus', loginRes.menus); } catch (e: any) { state.loading.signIn = false; state.loginForm.captcha = ''; @@ -192,8 +190,6 @@ const onSignIn = async () => { // 头像 photo: letterAvatar(state.loginForm.username), time: new Date().getTime(), - // // 菜单资源code数组 - // menus: loginRes.menus, permissions: loginRes.permissions, lastLoginTime: loginRes.lastLoginTime, lastLoginIp: loginRes.lastLoginIp, @@ -202,20 +198,9 @@ const onSignIn = async () => { // 存储用户信息到浏览器缓存 setUserInfo2Session(userInfos); // 1、请注意执行顺序(存储用户信息到vuex) - useUserInfo().setUserInfo(userInfos) - // store.dispatch('userInfos/setUserInfos', userInfos); - if (!useThemeConfig().themeConfig.isRequestRoutes) { - // 前端控制路由,2、请注意执行顺序 - // await initAllFun(); - await initBackEndControlRoutesFun(); - signInSuccess(); - } else { - // 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 - // 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/" - await initBackEndControlRoutesFun(); - // 执行完 initBackEndControlRoutesFun,再执行 signInSuccess - signInSuccess(); - } + useUserInfo().setUserInfo(userInfos); + await initRouter(); + signInSuccess(); }; // 登录成功后的跳转 @@ -248,7 +233,7 @@ const changePwd = () => { const changePwdReq: any = { ...form }; changePwdReq.oldPassword = await RsaEncrypt(form.oldPassword); changePwdReq.newPassword = await RsaEncrypt(form.newPassword); - await openApi.changePwd(changePwdReq); + await openApi.changePwd.request(changePwdReq); ElMessage.success('密码修改成功, 新密码已填充至登录密码框'); state.loginForm.password = state.changePwdDialog.form.newPassword; state.changePwdDialog.visible = false; diff --git a/mayfly_go_web/src/views/ops/db/SqlExec.vue b/mayfly_go_web/src/views/ops/db/SqlExec.vue index 4a84de8d..82845e42 100644 --- a/mayfly_go_web/src/views/ops/db/SqlExec.vue +++ b/mayfly_go_web/src/views/ops/db/SqlExec.vue @@ -135,7 +135,7 @@ const state = reactive({ tabs, dataTabsTableHeight: '600', editorHeight: '600', - tagTreeHeight: window.innerHeight - 173 + 'px', + tagTreeHeight: window.innerHeight - 178 + 'px', genSqlDialog: { visible: false, sql: '', diff --git a/mayfly_go_web/src/views/ops/db/api.ts b/mayfly_go_web/src/views/ops/db/api.ts index 563ba4d4..c8a35706 100644 --- a/mayfly_go_web/src/views/ops/db/api.ts +++ b/mayfly_go_web/src/views/ops/db/api.ts @@ -2,27 +2,27 @@ import Api from '@/common/Api'; export const dbApi = { // 获取权限列表 - dbs: Api.create("/dbs", 'get'), - saveDb: Api.create("/dbs", 'post'), - getAllDatabase: Api.create("/dbs/databases", 'post'), - getDbPwd: Api.create("/dbs/{id}/pwd", 'get'), - deleteDb: Api.create("/dbs/{id}", 'delete'), - dumpDb: Api.create("/dbs/{id}/dump", 'post'), - tableInfos: Api.create("/dbs/{id}/t-infos", 'get'), - tableIndex: Api.create("/dbs/{id}/t-index", 'get'), - tableDdl: Api.create("/dbs/{id}/t-create-ddl", 'get'), - tableMetadata: Api.create("/dbs/{id}/t-metadata", 'get'), - columnMetadata: Api.create("/dbs/{id}/c-metadata", 'get'), + dbs: Api.newGet("/dbs"), + saveDb: Api.newPost("/dbs"), + getAllDatabase: Api.newPost("/dbs/databases"), + getDbPwd: Api.newGet("/dbs/{id}/pwd"), + deleteDb: Api.newDelete("/dbs/{id}"), + dumpDb: Api.newPost("/dbs/{id}/dump"), + tableInfos: Api.newGet("/dbs/{id}/t-infos"), + tableIndex: Api.newGet("/dbs/{id}/t-index"), + tableDdl: Api.newGet("/dbs/{id}/t-create-ddl"), + tableMetadata: Api.newGet("/dbs/{id}/t-metadata"), + columnMetadata: Api.newGet("/dbs/{id}/c-metadata"), // 获取表即列提示 - hintTables: Api.create("/dbs/{id}/hint-tables", 'get'), - sqlExec: Api.create("/dbs/{id}/exec-sql", 'post'), + hintTables: Api.newGet("/dbs/{id}/hint-tables"), + sqlExec: Api.newPost("/dbs/{id}/exec-sql"), // 保存sql - saveSql: Api.create("/dbs/{id}/sql", 'post'), + saveSql: Api.newPost("/dbs/{id}/sql"), // 获取保存的sql - getSql: Api.create("/dbs/{id}/sql", 'get'), + getSql: Api.newGet("/dbs/{id}/sql"), // 获取保存的sql names - getSqlNames: Api.create("/dbs/{id}/sql-names", 'get'), - deleteDbSql: Api.create("/dbs/{id}/sql", 'delete'), + getSqlNames: Api.newGet("/dbs/{id}/sql-names"), + deleteDbSql: Api.newDelete("/dbs/{id}/sql"), // 获取数据库sql执行记录 - getSqlExecs: Api.create("/dbs/{dbId}/sql-execs", 'get'), + getSqlExecs: Api.newGet("/dbs/{dbId}/sql-execs"), } \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/db/component/tab/TableData.vue b/mayfly_go_web/src/views/ops/db/component/tab/TableData.vue index 2ecc195e..14672b0a 100644 --- a/mayfly_go_web/src/views/ops/db/component/tab/TableData.vue +++ b/mayfly_go_web/src/views/ops/db/component/tab/TableData.vue @@ -6,7 +6,7 @@ - + @@ -37,8 +37,8 @@ - + @@ -113,6 +133,7 @@ import { dateStrFormat } from '@/common/utils/date'; import DbTable from '../DbTable.vue' const emits = defineEmits(['genInsertSql']) +const dataForm: any = ref(null); const props = defineProps({ data: { @@ -136,7 +157,7 @@ const state = reactive({ condition: '', // 当前条件框的条件 loading: false, // 是否在加载数据 columnNames: [], - columns: [], + columns: [] as any, pageNum: 1, count: 0, selectionDatas: [] as any, @@ -149,6 +170,12 @@ const state = reactive({ condition: '=', value: null }, + addDataDialog: { + data: {}, + title: '', + placeholder: '', + visible: false, + }, tableHeight: '600', hasUpdatedFileds: false, }); @@ -163,6 +190,7 @@ const { count, hasUpdatedFileds, conditionDialog, + addDataDialog, } = toRefs(state); watch(() => props.tableHeight, (newValue: any) => { @@ -323,20 +351,43 @@ const cancelUpdateFields = () => { dbTableRef.value.cancelUpdateFields(); } +const onShowAddDataDialog = async () => { + state.addDataDialog.title = `添加'${state.table}'表数据` + state.addDataDialog.visible = true; +}; + +const closeAddDataDialog = () => { + state.addDataDialog.visible = false; + state.addDataDialog.data = {}; +} + // 添加新数据行 const addRow = async () => { - const columns = state.ti.getNowDb().getColumns(state.table); - // key: 字段名,value: 字段名提示 - let obj: any = {}; - columns.forEach((item: any) => { - obj[`${item.columnName}`] = `'${item.columnComment || ''} ${item.columnName}[${item.columnType}]${item.nullable == 'YES' ? '' : '[not null]'}'`; - }); - let columnNames = Object.keys(obj).join(','); - let values = Object.values(obj).join(','); - let sql = `INSERT INTO ${state.table} (${columnNames}) VALUES (${values});`; - state.ti.getNowDbInst().promptExeSql(state.ti.db, sql, null, () => { - onRefresh(); + dataForm.value.validate(async (valid: boolean) => { + if (valid) { + const data = state.addDataDialog.data; + // key: 字段名,value: 字段名提示 + let obj: any = {}; + for (let item of state.columns) { + const value = data[item.columnName] + if (!value) { + continue + } + obj[`${item.columnName}`] = DbInst.wrapValueByType(value); + } + let columnNames = Object.keys(obj).join(','); + let values = Object.values(obj).join(','); + let sql = `INSERT INTO ${state.table} (${columnNames}) VALUES (${values});`; + state.ti.getNowDbInst().promptExeSql(state.ti.db, sql, null, () => { + closeAddDataDialog(); + onRefresh(); + }); + } else { + ElMessage.error('请正确填写数据信息'); + return false; + } }); + }; diff --git a/mayfly_go_web/src/views/ops/db/db.ts b/mayfly_go_web/src/views/ops/db/db.ts index 1452064b..552bb573 100644 --- a/mayfly_go_web/src/views/ops/db/db.ts +++ b/mayfly_go_web/src/views/ops/db/db.ts @@ -274,12 +274,21 @@ export class DbInst { * 根据字段类型包装字段值,如为字符串等则添加‘’,数字类型则直接返回即可 */ static wrapColumnValue(columnType: string, value: any) { - if (columnType.match(/int|double|float|nubmer|decimal|byte|bit/gi)) { + if (this.isNumber(columnType)) { return value; } return `'${value}'`; }; + /** + * 判断字段类型是否为数字类型 + * @param columnType 字段类型 + * @returns + */ + static isNumber(columnType: string) { + return columnType.match(/int|double|float|nubmer|decimal|byte|bit/gi); + }; + /** * * @param str 字符串 diff --git a/mayfly_go_web/src/views/ops/machine/api.ts b/mayfly_go_web/src/views/ops/machine/api.ts index a08e98f9..abcf394c 100644 --- a/mayfly_go_web/src/views/ops/machine/api.ts +++ b/mayfly_go_web/src/views/ops/machine/api.ts @@ -2,45 +2,45 @@ import Api from '@/common/Api'; export const machineApi = { // 获取权限列表 - list: Api.create("/machines", 'get'), - getMachinePwd: Api.create("/machines/{id}/pwd", 'get'), - info: Api.create("/machines/{id}/sysinfo", 'get'), - stats: Api.create("/machines/{id}/stats", 'get'), - process: Api.create("/machines/{id}/process", 'get'), + list: Api.newGet("/machines"), + getMachinePwd: Api.newGet("/machines/{id}/pwd"), + info: Api.newGet("/machines/{id}/sysinfo"), + stats: Api.newGet("/machines/{id}/stats"), + process: Api.newGet("/machines/{id}/process"), // 终止进程 - killProcess: Api.create("/machines/{id}/process", 'delete'), - closeCli: Api.create("/machines/{id}/close-cli", 'delete'), - testConn: Api.create("/machines/test-conn", 'post'), + killProcess: Api.newDelete("/machines/{id}/process"), + closeCli: Api.newDelete("/machines/{id}/close-cli"), + testConn: Api.newPost("/machines/test-conn"), // 保存按钮 - saveMachine: Api.create("/machines", 'post'), + saveMachine: Api.newPost("/machines"), // 调整状态 - changeStatus: Api.create("/machines/{id}/{status}", 'put'), + changeStatus: Api.newPut("/machines/{id}/{status}"), // 删除机器 - del: Api.create("/machines/{id}", 'delete'), - scripts: Api.create("/machines/{machineId}/scripts", 'get'), - runScript: Api.create("/machines/{machineId}/scripts/{scriptId}/run", 'get'), - saveScript: Api.create("/machines/{machineId}/scripts", 'post'), - deleteScript: Api.create("/machines/{machineId}/scripts/{scriptId}", 'delete'), + del: Api.newDelete("/machines/{id}"), + scripts: Api.newGet("/machines/{machineId}/scripts"), + runScript: Api.newGet("/machines/{machineId}/scripts/{scriptId}/run"), + saveScript: Api.newPost("/machines/{machineId}/scripts"), + deleteScript: Api.newDelete("/machines/{machineId}/scripts/{scriptId}"), // 获取配置文件列表 - files: Api.create("/machines/{id}/files", 'get'), - lsFile: Api.create("/machines/{machineId}/files/{fileId}/read-dir", 'get'), - rmFile: Api.create("/machines/{machineId}/files/{fileId}/remove", 'delete'), - uploadFile: Api.create("/machines/{machineId}/files/{fileId}/upload?token={token}", 'post'), - fileContent: Api.create("/machines/{machineId}/files/{fileId}/read", 'get'), - createFile: Api.create("/machines/{machineId}/files/{id}/create-file", 'post'), + files: Api.newGet("/machines/{id}/files"), + lsFile: Api.newGet("/machines/{machineId}/files/{fileId}/read-dir"), + rmFile: Api.newDelete("/machines/{machineId}/files/{fileId}/remove"), + uploadFile: Api.newPost("/machines/{machineId}/files/{fileId}/upload?token={token}"), + fileContent: Api.newGet("/machines/{machineId}/files/{fileId}/read"), + createFile: Api.newPost("/machines/{machineId}/files/{id}/create-file"), // 修改文件内容 - updateFileContent: Api.create("/machines/{machineId}/files/{id}/write", 'post'), + updateFileContent: Api.newPost("/machines/{machineId}/files/{id}/write"), // 添加文件or目录 - addConf: Api.create("/machines/{machineId}/files", 'post'), + addConf: Api.newPost("/machines/{machineId}/files"), // 删除配置的文件or目录 - delConf: Api.create("/machines/{machineId}/files/{id}", 'delete'), - terminal: Api.create("/api/machines/{id}/terminal", 'get'), - recDirNames: Api.create("/machines/rec/names", 'get') + delConf: Api.newDelete("/machines/{machineId}/files/{id}"), + terminal: Api.newGet("/api/machines/{id}/terminal"), + recDirNames: Api.newGet("/machines/rec/names") } export const authCertApi = { - baseList : Api.create("/sys/authcerts/base", 'get'), - list: Api.create("/sys/authcerts", 'get'), - save: Api.create("/sys/authcerts", 'post'), - delete: Api.create("/sys/authcerts/{id}", 'delete'), + baseList : Api.newGet("/sys/authcerts/base"), + list: Api.newGet("/sys/authcerts"), + save: Api.newPost("/sys/authcerts"), + delete: Api.newDelete("/sys/authcerts/{id}"), } \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/mongo/api.ts b/mayfly_go_web/src/views/ops/mongo/api.ts index 55976a2c..b64f3cc0 100644 --- a/mayfly_go_web/src/views/ops/mongo/api.ts +++ b/mayfly_go_web/src/views/ops/mongo/api.ts @@ -1,14 +1,14 @@ import Api from '@/common/Api'; export const mongoApi = { - mongoList : Api.create("/mongos", 'get'), - saveMongo : Api.create("/mongos", 'post'), - deleteMongo : Api.create("/mongos/{id}", 'delete'), - databases: Api.create("/mongos/{id}/databases", 'get'), - collections: Api.create("/mongos/{id}/collections", 'get'), - runCommand: Api.create("/mongos/{id}/run-command", 'post'), - findCommand: Api.create("/mongos/{id}/command/find", 'post'), - updateByIdCommand: Api.create("/mongos/{id}/command/update-by-id", 'post'), - deleteByIdCommand: Api.create("/mongos/{id}/command/delete-by-id", 'post'), - insertCommand: Api.create("/mongos/{id}/command/insert", 'post'), + mongoList : Api.newGet("/mongos"), + saveMongo : Api.newPost("/mongos"), + deleteMongo : Api.newDelete("/mongos/{id}"), + databases: Api.newGet("/mongos/{id}/databases"), + collections: Api.newGet("/mongos/{id}/collections"), + runCommand: Api.newPost("/mongos/{id}/run-command"), + findCommand: Api.newPost("/mongos/{id}/command/find"), + updateByIdCommand: Api.newPost("/mongos/{id}/command/update-by-id"), + deleteByIdCommand: Api.newPost("/mongos/{id}/command/delete-by-id"), + insertCommand: Api.newPost("/mongos/{id}/command/insert"), } \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/redis/api.ts b/mayfly_go_web/src/views/ops/redis/api.ts index 4fb6d37a..1f4e135d 100644 --- a/mayfly_go_web/src/views/ops/redis/api.ts +++ b/mayfly_go_web/src/views/ops/redis/api.ts @@ -1,26 +1,26 @@ import Api from '@/common/Api'; export const redisApi = { - redisList : Api.create("/redis", 'get'), - getRedisPwd: Api.create("/redis/{id}/pwd", 'get'), - redisInfo: Api.create("/redis/{id}/info", 'get'), - clusterInfo: Api.create("/redis/{id}/cluster-info", 'get'), - saveRedis: Api.create("/redis", 'post'), - delRedis: Api.create("/redis/{id}", 'delete'), + redisList: Api.newGet("/redis"), + getRedisPwd: Api.newGet("/redis/{id}/pwd"), + redisInfo: Api.newGet("/redis/{id}/info"), + clusterInfo: Api.newGet("/redis/{id}/cluster-info"), + saveRedis: Api.newPost("/redis"), + delRedis: Api.newDelete("/redis/{id}"), // 获取权限列表 - scan: Api.create("/redis/{id}/{db}/scan", 'post'), - getStringValue: Api.create("/redis/{id}/{db}/string-value", 'get'), - saveStringValue: Api.create("/redis/{id}/{db}/string-value", 'post'), - getHashValue: Api.create("/redis/{id}/{db}/hash-value", 'get'), - hscan: Api.create("/redis/{id}/{db}/hscan", 'get'), - hget: Api.create("/redis/{id}/{db}/hget", 'get'), - hdel: Api.create("/redis/{id}/{db}/hdel", 'delete'), - saveHashValue: Api.create("/redis/{id}/{db}/hash-value", 'post'), - getSetValue: Api.create("/redis/{id}/{db}/set-value", 'get'), - saveSetValue: Api.create("/redis/{id}/{db}/set-value", 'post'), - del: Api.create("/redis/{id}/{db}/scan/{cursor}/{count}", 'delete'), - delKey: Api.create("/redis/{id}/{db}/key", 'delete'), - getListValue: Api.create("/redis/{id}/{db}/list-value", 'get'), - saveListValue: Api.create("/redis/{id}/{db}/list-value", 'post'), - setListValue: Api.create("/redis/{id}/{db}/list-value/lset", 'post'), + scan: Api.newPost("/redis/{id}/{db}/scan"), + getStringValue: Api.newGet("/redis/{id}/{db}/string-value"), + saveStringValue: Api.newPost("/redis/{id}/{db}/string-value"), + getHashValue: Api.newGet("/redis/{id}/{db}/hash-value"), + hscan: Api.newGet("/redis/{id}/{db}/hscan"), + hget: Api.newGet("/redis/{id}/{db}/hget"), + hdel: Api.newDelete("/redis/{id}/{db}/hdel"), + saveHashValue: Api.newPost("/redis/{id}/{db}/hash-value"), + getSetValue: Api.newGet("/redis/{id}/{db}/set-value"), + saveSetValue: Api.newPost("/redis/{id}/{db}/set-value"), + del: Api.newDelete("/redis/{id}/{db}/scan/{cursor}/{count}"), + delKey: Api.newDelete("/redis/{id}/{db}/key"), + getListValue: Api.newGet("/redis/{id}/{db}/list-value"), + saveListValue: Api.newPost("/redis/{id}/{db}/list-value"), + setListValue: Api.newPost("/redis/{id}/{db}/list-value/lset"), } \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/tag/api.ts b/mayfly_go_web/src/views/ops/tag/api.ts index 7188e631..28f1a2b2 100644 --- a/mayfly_go_web/src/views/ops/tag/api.ts +++ b/mayfly_go_web/src/views/ops/tag/api.ts @@ -1,20 +1,20 @@ import Api from '@/common/Api'; export const tagApi = { - getAccountTags: Api.create("/tag-trees/account-has", 'get'), - listByQuery: Api.create("/tag-trees/query", 'get'), - getTagTrees: Api.create("/tag-trees", 'get'), - saveTagTree: Api.create("/tag-trees", 'post'), - delTagTree: Api.create("/tag-trees/{id}", 'delete'), + getAccountTags: Api.newGet("/tag-trees/account-has"), + listByQuery: Api.newGet("/tag-trees/query"), + getTagTrees: Api.newGet("/tag-trees"), + saveTagTree: Api.newPost("/tag-trees"), + delTagTree: Api.newDelete("/tag-trees/{id}"), - getTeams: Api.create("/teams", 'get'), - saveTeam: Api.create("/teams", 'post'), - delTeam: Api.create("/teams/{id}", 'delete'), + getTeams: Api.newGet("/teams"), + saveTeam: Api.newPost("/teams"), + delTeam: Api.newDelete("/teams/{id}"), - getTeamMem: Api.create("/teams/{teamId}/members", 'get'), - saveTeamMem: Api.create("/teams/{teamId}/members", 'post'), - delTeamMem: Api.create("/teams/{teamId}/members/{accountId}", 'delete'), + getTeamMem: Api.newGet("/teams/{teamId}/members"), + saveTeamMem: Api.newPost("/teams/{teamId}/members"), + delTeamMem: Api.newDelete("/teams/{teamId}/members/{accountId}"), - getTeamTagIds: Api.create("/teams/{teamId}/tags", 'get'), - saveTeamTags: Api.create("/teams/{teamId}/tags", 'post'), + getTeamTagIds: Api.newGet("/teams/{teamId}/tags"), + saveTeamTags: Api.newPost("/teams/{teamId}/tags"), } \ No newline at end of file diff --git a/mayfly_go_web/src/views/personal/api.ts b/mayfly_go_web/src/views/personal/api.ts index ef594c39..7ec9a080 100644 --- a/mayfly_go_web/src/views/personal/api.ts +++ b/mayfly_go_web/src/views/personal/api.ts @@ -1,8 +1,8 @@ import Api from '@/common/Api'; export const personApi = { - accountInfo: Api.create("/sys/accounts/self", 'get'), - updateAccount: Api.create("/sys/accounts/self", 'put'), - getMsgs: Api.create("/sys/accounts/msgs", 'get'), + accountInfo: Api.newGet("/sys/accounts/self"), + updateAccount: Api.newPut("/sys/accounts/self"), + getMsgs: Api.newGet("/sys/accounts/msgs"), } diff --git a/mayfly_go_web/src/views/system/api.ts b/mayfly_go_web/src/views/system/api.ts index 45f21991..5fe7fb84 100644 --- a/mayfly_go_web/src/views/system/api.ts +++ b/mayfly_go_web/src/views/system/api.ts @@ -1,43 +1,43 @@ import Api from '@/common/Api'; export const resourceApi = { - list: Api.create("/sys/resources", 'get'), - detail: Api.create("/sys/resources/{id}", 'get'), - save: Api.create("/sys/resources", 'post'), - update: Api.create("/sys/resources/{id}", 'put'), - del: Api.create("/sys/resources/{id}", 'delete'), - changeStatus: Api.create("/sys/resources/{id}/{status}", 'put') + list: Api.newGet("/sys/resources"), + detail: Api.newGet("/sys/resources/{id}"), + save: Api.newPost("/sys/resources"), + update: Api.newPut("/sys/resources/{id}"), + del: Api.newDelete("/sys/resources/{id}"), + changeStatus: Api.newPut("/sys/resources/{id}/{status}") } export const roleApi = { - list: Api.create("/sys/roles", 'get'), - save: Api.create("/sys/roles", 'post'), - update: Api.create("/sys/roles/{id}", 'put'), - del: Api.create("/sys/roles/{id}", 'delete'), + list: Api.newGet("/sys/roles"), + save: Api.newPost("/sys/roles"), + update: Api.newPut("/sys/roles/{id}"), + del: Api.newDelete("/sys/roles/{id}"), // 获取指定角色拥有的资源id - roleResourceIds: Api.create("/sys/roles/{id}/resourceIds", 'get'), - roleResources: Api.create("/sys/roles/{id}/resources", 'get'), - saveResources: Api.create("/sys/roles/{id}/resources", 'post') + roleResourceIds: Api.newGet("/sys/roles/{id}/resourceIds"), + roleResources: Api.newGet("/sys/roles/{id}/resources"), + saveResources: Api.newPost("/sys/roles/{id}/resources") } export const accountApi = { - list: Api.create("/sys/accounts", 'get'), - save: Api.create("/sys/accounts", 'post'), - update: Api.create("/sys/accounts/{id}", 'put'), - del: Api.create("/sys/accounts/{id}", 'delete'), - changeStatus: Api.create("/sys/accounts/change-status/{id}/{status}", 'put'), - roleIds: Api.create("/sys/accounts/{id}/roleIds", 'get'), - roles: Api.create("/sys/accounts/{id}/roles", 'get'), - resources: Api.create("/sys/accounts/{id}/resources", 'get'), - saveRoles: Api.create("/sys/accounts/roles", 'post') + list: Api.newGet("/sys/accounts"), + save: Api.newPost("/sys/accounts"), + update: Api.newPut("/sys/accounts/{id}"), + del: Api.newDelete("/sys/accounts/{id}"), + changeStatus: Api.newPut("/sys/accounts/change-status/{id}/{status}"), + roleIds: Api.newGet("/sys/accounts/{id}/roleIds"), + roles: Api.newGet("/sys/accounts/{id}/roles"), + resources: Api.newGet("/sys/accounts/{id}/resources"), + saveRoles: Api.newPost("/sys/accounts/roles") } export const configApi = { - list: Api.create("/sys/configs", 'get'), - save: Api.create("/sys/configs", 'post'), - getValue: Api.create("/sys/configs/value", 'get'), + list: Api.newGet("/sys/configs"), + save: Api.newPost("/sys/configs"), + getValue: Api.newGet("/sys/configs/value"), } export const logApi = { - list: Api.create("/syslogs", "get") + list: Api.newGet("/syslogs") } \ No newline at end of file diff --git a/server/go.mod b/server/go.mod index eaf70b53..db0d74c2 100644 --- a/server/go.mod +++ b/server/go.mod @@ -18,8 +18,8 @@ require ( golang.org/x/crypto v0.8.0 // ssh gopkg.in/yaml.v3 v3.0.1 // gorm - gorm.io/driver/mysql v1.4.7 - gorm.io/gorm v1.24.6 + gorm.io/driver/mysql v1.5.0 + gorm.io/gorm v1.25.0 ) require ( diff --git a/server/internal/sys/api/account.go b/server/internal/sys/api/account.go index cae7b8bb..026b5b24 100644 --- a/server/internal/sys/api/account.go +++ b/server/internal/sys/api/account.go @@ -39,6 +39,10 @@ func (a *Account) Login(rc *req.Ctx) { biz.IsTrue(captcha.Verify(loginForm.Cid, loginForm.Captcha), "验证码错误") } + clientIp := rc.GinCtx.ClientIP() + rc.ReqParam = loginForm.Username + rc.ReqParam = fmt.Sprintf("username: %s | ip: %s", loginForm.Username, clientIp) + originPwd, err := utils.DefaultRsaDecrypt(loginForm.Password, true) biz.ErrIsNilAppendErr(err, "解密密码错误: %s") @@ -50,6 +54,20 @@ func (a *Account) Login(rc *req.Ctx) { // 校验密码强度是否符合 biz.IsTrueBy(CheckPasswordLever(originPwd), biz.NewBizErrCode(401, "您的密码安全等级较低,请修改后重新登录")) + // 保存登录消息 + go a.saveLogin(account, clientIp) + + rc.ResData = map[string]interface{}{ + "token": req.CreateToken(account.Id, account.Username), + "name": account.Name, + "username": account.Username, + "lastLoginTime": account.LastLoginTime, + "lastLoginIp": account.LastLoginIp, + } +} + +func (a *Account) GetPermissions(rc *req.Ctx) { + account := rc.LoginAccount var resources vo.AccountResourceVOList // 获取账号菜单资源 @@ -66,23 +84,9 @@ func (a *Account) Login(rc *req.Ctx) { } // 保存该账号的权限codes req.SavePermissionCodes(account.Id, permissions) - - clientIp := rc.GinCtx.ClientIP() - // 保存登录消息 - go a.saveLogin(account, clientIp) - - rc.ReqParam = fmt.Sprintf("登录ip: %s", clientIp) - // 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志 - rc.LoginAccount = &model.LoginAccount{Id: account.Id, Username: account.Username} - rc.ResData = map[string]interface{}{ - "token": req.CreateToken(account.Id, account.Username), - "name": account.Name, - "username": account.Username, - "lastLoginTime": account.LastLoginTime, - "lastLoginIp": account.LastLoginIp, - "menus": menus.ToTrees(0), - "permissions": permissions, + "menus": menus.ToTrees(0), + "permissions": permissions, } } @@ -143,7 +147,7 @@ func (a *Account) saveLogin(account *entity.Account, ip string) { // 创建登录消息 loginMsg := &entity.Msg{ RecipientId: int64(account.Id), - Msg: fmt.Sprintf("于%s登录", now.Format("2006-01-02 15:04:05")), + Msg: fmt.Sprintf("于[%s]-[%s]登录", ip, now.Format("2006-01-02 15:04:05")), Type: 1, } loginMsg.CreateTime = &now diff --git a/server/internal/sys/router/account.go b/server/internal/sys/router/account.go index 46b575d9..a59a1fe3 100644 --- a/server/internal/sys/router/account.go +++ b/server/internal/sys/router/account.go @@ -27,6 +27,11 @@ func InitAccountRouter(router *gin.RouterGroup) { Handle(a.Login) }) + // 获取个人账号的权限资源信息 + account.GET("/permissions", func(c *gin.Context) { + req.NewCtxWithGin(c).Handle(a.GetPermissions) + }) + changePwdLog := req.NewLogInfo("用户修改密码").WithSave(true) account.POST("change-pwd", func(g *gin.Context) { req.NewCtxWithGin(g).