mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 07:50:25 +08:00
feat: 系统升级支持数据库自动迁移,避免手动执行升级脚本
This commit is contained in:
@@ -11,15 +11,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@vueuse/core": "^12.4.0",
|
||||
"asciinema-player": "^3.8.1",
|
||||
"@vueuse/core": "^12.5.0",
|
||||
"asciinema-player": "^3.9.0",
|
||||
"axios": "^1.6.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"cropperjs": "^1.6.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.6.0",
|
||||
"element-plus": "^2.9.3",
|
||||
"element-plus": "^2.9.4",
|
||||
"js-base64": "^3.7.7",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -28,16 +28,16 @@
|
||||
"monaco-sql-languages": "^0.12.2",
|
||||
"monaco-themes": "^0.4.4",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.3.0",
|
||||
"pinia": "^2.3.1",
|
||||
"qrcode.vue": "^3.6.0",
|
||||
"screenfull": "^6.0.2",
|
||||
"sortablejs": "^1.15.6",
|
||||
"splitpanes": "^3.1.5",
|
||||
"sql-formatter": "^15.4.5",
|
||||
"splitpanes": "^3.1.8",
|
||||
"sql-formatter": "^15.4.10",
|
||||
"trzsz": "^1.1.5",
|
||||
"uuid": "^9.0.1",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^11.0.1",
|
||||
"vue-i18n": "^11.1.0",
|
||||
"vue-router": "^4.5.0",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"xterm": "^5.3.0",
|
||||
@@ -60,9 +60,9 @@
|
||||
"eslint": "^8.35.0",
|
||||
"eslint-plugin-vue": "^9.31.0",
|
||||
"prettier": "^3.2.5",
|
||||
"sass": "^1.83.4",
|
||||
"sass": "^1.84.0",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.0.7",
|
||||
"vite": "^6.1.0",
|
||||
"vite-plugin-progress": "0.0.7",
|
||||
"vue-eslint-parser": "^9.4.3"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function getBaseApiUrl() {
|
||||
export function getBaseApiUrl() {
|
||||
let path = window.location.pathname;
|
||||
if (path == '/') {
|
||||
return window.location.host;
|
||||
@@ -15,7 +15,7 @@ const config = {
|
||||
baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
|
||||
|
||||
// 系统版本
|
||||
version: 'v1.9.2',
|
||||
version: 'v1.9.3',
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -54,3 +54,67 @@ export function getValueByPath(obj: any, path: string) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字段路径设置字段值,若路径不存在,则建对应的路径对象信息
|
||||
* @param obj 对象
|
||||
* @param path 字段路径
|
||||
* @param value 字段值
|
||||
*/
|
||||
export function setValueByPath(obj: any, path: string[], value: any) {
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
const key = path[i];
|
||||
if (!obj[key]) {
|
||||
obj[key] = {};
|
||||
}
|
||||
obj = obj[key];
|
||||
}
|
||||
obj[path[path.length - 1]] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用递归函数进行深度克隆,并支持通过回调函数进行指定字段值的调整
|
||||
*
|
||||
* @param obj 要克隆的对象
|
||||
* @param callback 回调函数,在每个字段被克隆之前调用,可以调整字段的值
|
||||
* @param hash 用于处理循环引用的 WeakMap
|
||||
* @returns 深度克隆后的对象
|
||||
*/
|
||||
export function deepClone(
|
||||
obj: any,
|
||||
callback: (key: string | number, value: any) => any = (key: string | number, value: any) => value,
|
||||
hash = new WeakMap()
|
||||
): any {
|
||||
if (Object(obj) !== obj) return obj; // 基本数据类型直接返回
|
||||
if (hash.has(obj)) return hash.get(obj); // 处理循环引用
|
||||
|
||||
let result: any;
|
||||
|
||||
if (obj instanceof Set) {
|
||||
result = new Set();
|
||||
hash.set(obj, result);
|
||||
obj.forEach((val) => result.add(deepClone(val, callback, hash)));
|
||||
} else if (obj instanceof Map) {
|
||||
result = new Map();
|
||||
hash.set(obj, result);
|
||||
obj.forEach((val, key) => result.set(key, deepClone(val, callback, hash)));
|
||||
} else if (obj instanceof Date) {
|
||||
result = new Date(obj.getTime());
|
||||
} else if (obj instanceof RegExp) {
|
||||
result = new RegExp(obj);
|
||||
} else if (typeof obj === 'object') {
|
||||
result = Array.isArray(obj) ? [] : {};
|
||||
hash.set(obj, result);
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
let value = obj[key];
|
||||
value = callback(key, value);
|
||||
result[key] = deepClone(value, callback, hash);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = obj;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -203,6 +203,15 @@ export function randomPassword(length = 10) {
|
||||
return password.join('');
|
||||
}
|
||||
|
||||
export function randomString(length = 8) {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let result = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += getRandomChar(chars);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getRandomChar(charSet: string) {
|
||||
const randomIndex = Math.floor(Math.random() * charSet.length);
|
||||
return charSet[randomIndex];
|
||||
|
||||
@@ -42,6 +42,7 @@ function initI18n() {
|
||||
// https://vue-i18n.intlify.dev/guide/essentials/fallback.html#explicit-fallback-with-one-locale
|
||||
return createI18n({
|
||||
legacy: false,
|
||||
globalInjection: true, // 在所有组件中都可以使用 $i18n $t $rt $d $n $tm
|
||||
silentTranslationWarn: true,
|
||||
missingWarn: false,
|
||||
silentFallbackWarn: true,
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</template>
|
||||
|
||||
<template #default="scope">
|
||||
<AccountSelectFormItem v-model="scope.row.userId" label="" />
|
||||
<AccountSelectFormItem style="margin-bottom: 0px" v-model="scope.row.userId" label="" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ const encryptField = async (param: any, field: string) => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log(param[field]);
|
||||
}
|
||||
// 使用rsa公钥加密sql
|
||||
// 使用aes加密sql
|
||||
param['_encrypted'] = 1;
|
||||
param[field] = AesEncrypt(param[field]);
|
||||
// console.log('解密结果', DesDecrypt(param[field]));
|
||||
|
||||
@@ -235,14 +235,22 @@ const cmHeaderDesc = new ContextmenuItem('desc', 'db.desc')
|
||||
const cmHeaderFixed = new ContextmenuItem('fixed', 'db.fixed')
|
||||
.withIcon('Paperclip')
|
||||
.withOnClick((data: any) => {
|
||||
data.fixed = true;
|
||||
state.columns.forEach((column: any) => {
|
||||
if (column.dataKey == data.dataKey) {
|
||||
column.fixed = true;
|
||||
}
|
||||
});
|
||||
})
|
||||
.withHideFunc((data: any) => data.fixed);
|
||||
|
||||
const cmHeaderCancelFixed = new ContextmenuItem('cancelFixed', 'db.cancelFiexd')
|
||||
.withIcon('Minus')
|
||||
.withOnClick((data: any) => {
|
||||
data.fixed = false;
|
||||
state.columns.forEach((column: any) => {
|
||||
if (column.dataKey == data.dataKey) {
|
||||
column.fixed = false;
|
||||
}
|
||||
});
|
||||
})
|
||||
.withHideFunc((data: any) => !data.fixed);
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ const pathResolve = (dir: string): any => {
|
||||
|
||||
const { VITE_PORT, VITE_OPEN, VITE_PUBLIC_PATH, VITE_EDITOR } = loadEnv();
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
const alias: Record<string, string> = {
|
||||
'@': pathResolve('src/'),
|
||||
};
|
||||
@@ -28,7 +30,7 @@ const viteConfig: UserConfig = {
|
||||
resolve: {
|
||||
alias,
|
||||
},
|
||||
base: process.env.NODE_ENV === 'production' ? VITE_PUBLIC_PATH : './',
|
||||
base: isProd ? VITE_PUBLIC_PATH : './',
|
||||
optimizeDeps: {
|
||||
include: ['element-plus/es/locale/lang/zh-cn'],
|
||||
},
|
||||
@@ -63,6 +65,9 @@ const viteConfig: UserConfig = {
|
||||
},
|
||||
},
|
||||
},
|
||||
esbuild: {
|
||||
drop: isProd ? ['console', 'debugger'] : [],
|
||||
},
|
||||
define: {
|
||||
__VUE_I18N_LEGACY_API__: JSON.stringify(false),
|
||||
__VUE_I18N_FULL_INSTALL__: JSON.stringify(false),
|
||||
|
||||
Reference in New Issue
Block a user