mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 16:00:25 +08:00
fix: machine file & i18n & icon
This commit is contained in:
@@ -11,15 +11,15 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@vueuse/core": "^12.0.0",
|
"@vueuse/core": "^12.3.0",
|
||||||
"asciinema-player": "^3.8.1",
|
"asciinema-player": "^3.8.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
"cropperjs": "^1.6.1",
|
"cropperjs": "^1.6.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.6.0",
|
||||||
"element-plus": "^2.9.1",
|
"element-plus": "^2.9.2",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
"trzsz": "^1.1.5",
|
"trzsz": "^1.1.5",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^10.0.5",
|
"vue-i18n": "^11.0.1",
|
||||||
"vue-router": "^4.5.0",
|
"vue-router": "^4.5.0",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
@@ -60,9 +60,9 @@
|
|||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-plugin-vue": "^9.31.0",
|
"eslint-plugin-vue": "^9.31.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.82.0",
|
"sass": "^1.83.1",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.2",
|
||||||
"vite": "^6.0.6",
|
"vite": "^6.0.7",
|
||||||
"vue-eslint-parser": "^9.4.3"
|
"vue-eslint-parser": "^9.4.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const allSvgIcons = import.meta.glob('./**/*.svg', { eager: true, as: 'raw' });
|
const allSvgIcons = import.meta.glob('./**/*.svg', { eager: true, query: 'raw' });
|
||||||
|
|
||||||
const iconNames = [];
|
const iconNames = [];
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ function convertSvgToSymbol(svgString, symbolId) {
|
|||||||
// 转为 df/input
|
// 转为 df/input
|
||||||
const name = path.replace('.svg', '').replace(/^\.\//, '');
|
const name = path.replace('.svg', '').replace(/^\.\//, '');
|
||||||
iconNames.push(`icon ${name}`);
|
iconNames.push(`icon ${name}`);
|
||||||
svgsymbols += convertSvgToSymbol(allSvgIcons[path], name);
|
svgsymbols += convertSvgToSymbol(allSvgIcons[path].default, name);
|
||||||
}
|
}
|
||||||
svgsymbols += '</svg>';
|
svgsymbols += '</svg>';
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ export const I18nEnum = {
|
|||||||
export const ResourceTypeEnum = {
|
export const ResourceTypeEnum = {
|
||||||
Machine: EnumValue.of(1, '机器').setExtra({ icon: 'Monitor', iconColor: 'var(--el-color-primary)' }).tagTypeSuccess(),
|
Machine: EnumValue.of(1, '机器').setExtra({ icon: 'Monitor', iconColor: 'var(--el-color-primary)' }).tagTypeSuccess(),
|
||||||
Db: EnumValue.of(2, '数据库实例').setExtra({ icon: 'Coin', iconColor: 'var(--el-color-warning)' }).tagTypeWarning(),
|
Db: EnumValue.of(2, '数据库实例').setExtra({ icon: 'Coin', iconColor: 'var(--el-color-warning)' }).tagTypeWarning(),
|
||||||
Redis: EnumValue.of(3, 'redis').setExtra({ icon: 'iconfont icon-redis', iconColor: 'var(--el-color-danger)' }).tagTypeInfo(),
|
Redis: EnumValue.of(3, 'redis').setExtra({ icon: 'icon redis/redis', iconColor: 'var(--el-color-danger)' }).tagTypeInfo(),
|
||||||
Mongo: EnumValue.of(4, 'mongo').setExtra({ icon: 'iconfont icon-mongo', iconColor: 'var(--el-color-success)' }).tagTypeDanger(),
|
Mongo: EnumValue.of(4, 'mongo').setExtra({ icon: 'icon mongo/mongo', iconColor: 'var(--el-color-success)' }).tagTypeDanger(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// 标签关联的资源类型
|
// 标签关联的资源类型
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
virtual-triggering
|
virtual-triggering
|
||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
|
<div class="ml5 mt5">{{ $t(title) }}</div>
|
||||||
<div class="icon-selector-warp">
|
<div class="icon-selector-warp">
|
||||||
<div class="ml10 mt10">{{ title }}</div>
|
|
||||||
<el-tabs v-model="state.fontIconTabActive" @tab-click="onIconClick">
|
<el-tabs v-model="state.fontIconTabActive" @tab-click="onIconClick">
|
||||||
<el-tab-pane lazy label="ele" name="ele">
|
<el-tab-pane lazy label="ele" name="ele">
|
||||||
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
|
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
|
||||||
@@ -57,7 +57,7 @@ const props = defineProps({
|
|||||||
// 输入框占位文本
|
// 输入框占位文本
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
default: () => '请输入内容搜索图标或者选择图标',
|
default: () => 'components.iconSelector.placeholder',
|
||||||
},
|
},
|
||||||
// 输入框占位文本
|
// 输入框占位文本
|
||||||
size: {
|
size: {
|
||||||
@@ -67,7 +67,7 @@ const props = defineProps({
|
|||||||
// 弹窗标题
|
// 弹窗标题
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: () => '请选择图标',
|
default: () => 'components.iconSelector.title',
|
||||||
},
|
},
|
||||||
// 禁用
|
// 禁用
|
||||||
disabled: {
|
disabled: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="monaco-editor" style="border: 1px solid var(--el-border-color-light, #ebeef5); height: 100%">
|
<div class="monaco-editor" style="border: 1px solid var(--el-border-color-light, #ebeef5); height: 100%">
|
||||||
<div class="monaco-editor-content" ref="monacoTextarea" :style="{ height: height }"></div>
|
<div class="monaco-editor-content" ref="monacoTextareaRef" :style="{ height: height }"></div>
|
||||||
<el-select v-if="canChangeMode" class="code-mode-select" v-model="languageMode" @change="changeLanguage" filterable>
|
<el-select v-if="canChangeMode" class="code-mode-select" v-model="languageMode" @change="changeLanguage" filterable>
|
||||||
<el-option v-for="mode in languageArr" :key="mode.value" :label="mode.label" :value="mode.value"> </el-option>
|
<el-option v-for="mode in languageArr" :key="mode.value" :label="mode.label" :value="mode.value"> </el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch, toRefs, reactive, onMounted, onBeforeUnmount } from 'vue';
|
import { watch, toRefs, reactive, onMounted, onBeforeUnmount, useTemplateRef, Ref } from 'vue';
|
||||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
// 相关语言
|
// 相关语言
|
||||||
import 'monaco-editor/esm/vs/basic-languages/shell/shell.contribution.js';
|
import 'monaco-editor/esm/vs/basic-languages/shell/shell.contribution.js';
|
||||||
@@ -45,6 +45,7 @@ import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
|||||||
// import Dracula from 'monaco-themes/themes/Dracula.json'
|
// import Dracula from 'monaco-themes/themes/Dracula.json'
|
||||||
import SolarizedLight from 'monaco-themes/themes/Solarized-light.json';
|
import SolarizedLight from 'monaco-themes/themes/Solarized-light.json';
|
||||||
import { language as shellLan } from 'monaco-editor/esm/vs/basic-languages/shell/shell.js';
|
import { language as shellLan } from 'monaco-editor/esm/vs/basic-languages/shell/shell.js';
|
||||||
|
|
||||||
import { ElOption, ElSelect } from 'element-plus';
|
import { ElOption, ElSelect } from 'element-plus';
|
||||||
|
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
@@ -53,9 +54,6 @@ import { useThemeConfig } from '@/store/themeConfig';
|
|||||||
const { themeConfig } = storeToRefs(useThemeConfig());
|
const { themeConfig } = storeToRefs(useThemeConfig());
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
language: {
|
language: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
@@ -74,12 +72,11 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: () => {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//定义事件
|
const modelValue = defineModel<any>('modelValue', { required: true });
|
||||||
const emit = defineEmits(['update:modelValue']);
|
|
||||||
|
|
||||||
const languageArr = [
|
const languageArr = [
|
||||||
{
|
{
|
||||||
@@ -154,7 +151,7 @@ const defaultOptions = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const monacoTextarea: any = ref();
|
const monacoTextareaRef: Ref<any> = useTemplateRef('monacoTextareaRef');
|
||||||
|
|
||||||
let monacoEditorIns: editor.IStandaloneCodeEditor = null as any;
|
let monacoEditorIns: editor.IStandaloneCodeEditor = null as any;
|
||||||
let completionItemProvider: any = null;
|
let completionItemProvider: any = null;
|
||||||
@@ -177,7 +174,7 @@ const { languageMode } = toRefs(state);
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
state.languageMode = props.language;
|
state.languageMode = props.language;
|
||||||
initMonacoEditorIns();
|
initMonacoEditorIns();
|
||||||
setEditorValue(props.modelValue);
|
setEditorValue(modelValue.value);
|
||||||
registerCompletionItemProvider();
|
registerCompletionItemProvider();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -191,18 +188,15 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(modelValue, (newValue: any) => {
|
||||||
() => props.modelValue,
|
if (!monacoEditorIns.hasTextFocus()) {
|
||||||
(newValue: any) => {
|
state.languageMode = props.language;
|
||||||
if (!monacoEditorIns.hasTextFocus()) {
|
if (newValue == null) {
|
||||||
state.languageMode = props.language;
|
newValue = '';
|
||||||
if (newValue == null) {
|
|
||||||
newValue = '';
|
|
||||||
}
|
|
||||||
monacoEditorIns?.setValue(newValue);
|
|
||||||
}
|
}
|
||||||
|
monacoEditorIns?.setValue(newValue);
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.language,
|
() => props.language,
|
||||||
@@ -227,11 +221,11 @@ const initMonacoEditorIns = () => {
|
|||||||
monaco.editor.defineTheme('SolarizedLight', SolarizedLight);
|
monaco.editor.defineTheme('SolarizedLight', SolarizedLight);
|
||||||
defaultOptions.language = state.languageMode;
|
defaultOptions.language = state.languageMode;
|
||||||
defaultOptions.theme = themeConfig.value.editorTheme;
|
defaultOptions.theme = themeConfig.value.editorTheme;
|
||||||
monacoEditorIns = monaco.editor.create(monacoTextarea.value, Object.assign(defaultOptions, props.options as any));
|
monacoEditorIns = monaco.editor.create(monacoTextareaRef.value, Object.assign(defaultOptions, props.options as any));
|
||||||
|
|
||||||
// 监听内容改变,双向绑定
|
// 监听内容改变,双向绑定
|
||||||
monacoEditorIns.onDidChangeModelContent(() => {
|
monacoEditorIns.onDidChangeModelContent(() => {
|
||||||
emit('update:modelValue', monacoEditorIns.getModel()?.getValue());
|
modelValue.value = monacoEditorIns.getModel()?.getValue();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
66
frontend/src/components/monaco/MonacoEditorBox.ts
Normal file
66
frontend/src/components/monaco/MonacoEditorBox.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { VNode, h, render } from 'vue';
|
||||||
|
import MonacoEditorDialog from './MonacoEditorDialog.vue';
|
||||||
|
import * as monaco from 'monaco-editor';
|
||||||
|
|
||||||
|
export type MonacoEditorDialogProps = {
|
||||||
|
content: string;
|
||||||
|
title: string;
|
||||||
|
language: string;
|
||||||
|
height?: string;
|
||||||
|
width?: string;
|
||||||
|
options?: any; // 可选项,如字体大小等
|
||||||
|
canChangeLang?: boolean; // 是否可以切换语言
|
||||||
|
showConfirmButton?: boolean;
|
||||||
|
confirmFn?: Function; // 点击确认的回调函数,入参editor value
|
||||||
|
closeFn?: Function; // 点击取消 或 关闭弹窗的回调函数
|
||||||
|
completionItemProvider?: monaco.languages.CompletionItemProvider; // 自定义补全项
|
||||||
|
};
|
||||||
|
|
||||||
|
const MonacoEditorBox = (props: MonacoEditorDialogProps): void => {
|
||||||
|
const boxId = 'monaco-editor-dialog-id';
|
||||||
|
let boxInstance: VNode;
|
||||||
|
|
||||||
|
const container = document.getElementById(boxId);
|
||||||
|
if (!container) {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.id = boxId;
|
||||||
|
|
||||||
|
if (props.showConfirmButton === undefined) {
|
||||||
|
props.showConfirmButton = true;
|
||||||
|
}
|
||||||
|
if (props.canChangeLang === undefined) {
|
||||||
|
props.canChangeLang = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建 虚拟dom
|
||||||
|
boxInstance = h(MonacoEditorDialog, {
|
||||||
|
...props,
|
||||||
|
modelValue: props.content,
|
||||||
|
'onUpdate:modelValue': (value: string) => {
|
||||||
|
props.content = value;
|
||||||
|
},
|
||||||
|
// 'onUpdate:visible': (value: boolean) => {},
|
||||||
|
visible: true,
|
||||||
|
onClose: () => {
|
||||||
|
// 卸载组件
|
||||||
|
if (boxInstance) {
|
||||||
|
render(null, container);
|
||||||
|
boxInstance = null as any;
|
||||||
|
}
|
||||||
|
// 移除 container DOM 元素
|
||||||
|
document.body.removeChild(container);
|
||||||
|
props.closeFn && props.closeFn();
|
||||||
|
console.log('close editor');
|
||||||
|
},
|
||||||
|
onConfirm: () => {
|
||||||
|
props.confirmFn && props.confirmFn(props.content);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// 将虚拟dom渲染到 container dom 上
|
||||||
|
render(boxInstance, container);
|
||||||
|
// 最后将 container 追加到 body 上
|
||||||
|
document.body.appendChild(container);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MonacoEditorBox;
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { VNode, h, render } from 'vue';
|
|
||||||
import MonacoEditorDialogComp from './MonacoEditorDialogComp.vue';
|
|
||||||
|
|
||||||
export type MonacoEditorDialogProps = {
|
|
||||||
content: string;
|
|
||||||
title: string;
|
|
||||||
language: string;
|
|
||||||
height?: string;
|
|
||||||
width?: string;
|
|
||||||
showConfirmButton?: boolean;
|
|
||||||
confirmFn?: Function; // 点击确认的回调函数,入参editor value
|
|
||||||
cancelFn?: Function; // 点击取消 或 关闭弹窗的回调函数
|
|
||||||
};
|
|
||||||
|
|
||||||
const boxId = 'monaco-editor-dialog-id';
|
|
||||||
|
|
||||||
let boxInstance: VNode;
|
|
||||||
|
|
||||||
const MonacoEditorDialog = (props: MonacoEditorDialogProps): void => {
|
|
||||||
const container = document.getElementById(boxId);
|
|
||||||
if (!container) {
|
|
||||||
const container = document.createElement('div');
|
|
||||||
container.id = boxId;
|
|
||||||
// 创建 虚拟dom
|
|
||||||
boxInstance = h(MonacoEditorDialogComp);
|
|
||||||
// 将虚拟dom渲染到 container dom 上
|
|
||||||
render(boxInstance, container);
|
|
||||||
// 最后将 container 追加到 body 上
|
|
||||||
document.body.appendChild(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
const boxVue = boxInstance.component;
|
|
||||||
if (boxVue) {
|
|
||||||
// 调用open方法显示弹框,注意不能使用boxVue.ctx来调用组件函数(build打包后ctx会获取不到)
|
|
||||||
boxVue.exposed?.open(props);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MonacoEditorDialog;
|
|
||||||
133
frontend/src/components/monaco/MonacoEditorDialog.vue
Normal file
133
frontend/src/components/monaco/MonacoEditorDialog.vue
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog :title="props.title" v-model="dialogVisible" :width="props.width" @close="close">
|
||||||
|
<monaco-editor
|
||||||
|
ref="editorRef"
|
||||||
|
:height="props.height"
|
||||||
|
class="editor"
|
||||||
|
:language="props.language"
|
||||||
|
v-model="modelValue"
|
||||||
|
:options="props.options"
|
||||||
|
:can-change-mode="props.canChangeLang"
|
||||||
|
/>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">{{ i18n.global.t('common.cancel') }}</el-button>
|
||||||
|
<el-button v-if="props.showConfirmButton" @click="confirm" type="primary">{{ i18n.global.t('common.confirm') }}</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { ElDialog, ElButton, ElMessage } from 'element-plus';
|
||||||
|
// import base style
|
||||||
|
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
||||||
|
import { MonacoEditorDialogProps } from './MonacoEditorBox';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
import { registerCompletionItemProvider } from './completionItemProvider';
|
||||||
|
|
||||||
|
const editorRef: any = ref(null);
|
||||||
|
|
||||||
|
const props = defineProps<MonacoEditorDialogProps>();
|
||||||
|
|
||||||
|
const modelValue = defineModel<string>('modelValue', {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const dialogVisible = defineModel<boolean>('visible', {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'confirm']);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.language,
|
||||||
|
() => {
|
||||||
|
// 格式化输出html;
|
||||||
|
const language = props.language;
|
||||||
|
if (language === 'html' || language == 'xml') {
|
||||||
|
modelValue.value = formatXML(modelValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.completionItemProvider) {
|
||||||
|
registerCompletionItemProvider(language, props.completionItemProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
editorRef.value?.focus();
|
||||||
|
editorRef.value?.format();
|
||||||
|
}, 300);
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认按钮
|
||||||
|
*/
|
||||||
|
const confirm = async () => {
|
||||||
|
let value = modelValue.value;
|
||||||
|
if (props.language === 'json') {
|
||||||
|
let val;
|
||||||
|
try {
|
||||||
|
val = JSON.parse(value);
|
||||||
|
if (typeof val !== 'object') {
|
||||||
|
ElMessage.error('请输入正确的json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ElMessage.error('请输入正确的json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 压缩json字符串
|
||||||
|
value = JSON.stringify(val);
|
||||||
|
} else if (props.language === 'html') {
|
||||||
|
// 压缩html字符串
|
||||||
|
value = compressHTML(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('confirm', value);
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
dialogVisible.value = false;
|
||||||
|
emit('close');
|
||||||
|
setTimeout(() => {
|
||||||
|
modelValue.value = '';
|
||||||
|
}, 200);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatXML = function (xml: string, tab?: string) {
|
||||||
|
let formatted = '',
|
||||||
|
indent = '';
|
||||||
|
tab = tab || ' ';
|
||||||
|
xml.split(/>\s*</).forEach(function (node) {
|
||||||
|
if (node.match(/^\/\w/)) indent = indent.substring(tab!.length);
|
||||||
|
formatted += indent + '<' + node + '>\r\n';
|
||||||
|
if (node.match(/^<?\w[^>]*[^\/]$/)) indent += tab;
|
||||||
|
});
|
||||||
|
return formatted.substring(1, formatted.length - 3);
|
||||||
|
};
|
||||||
|
|
||||||
|
function compressHTML(html: string) {
|
||||||
|
return (
|
||||||
|
html
|
||||||
|
.replace(/[\r\n\t]+/g, ' ') // 移除换行符和制表符
|
||||||
|
// .replace(/<!--[\s\S]*?-->/g, '') // 移除注释
|
||||||
|
.replace(/\s{2,}/g, ' ') // 合并多个空格为一个空格
|
||||||
|
.replace(/>\s+</g, '><')
|
||||||
|
); // 移除标签之间的空格
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.editor {
|
||||||
|
font-size: 9pt;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<el-dialog :title="state.title" v-model="state.dialogVisible" :width="state.width" @close="cancel">
|
|
||||||
<monaco-editor ref="editorRef" :height="state.height" class="editor" :language="state.language" v-model="contentValue" can-change-mode />
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="cancel">{{ i18n.global.t('common.cancel') }}</el-button>
|
|
||||||
<el-button v-if="state.showConfirmButton" @click="confirm" type="primary">{{ i18n.global.t('common.confirm') }}</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { toRefs, ref, reactive } from 'vue';
|
|
||||||
import { ElDialog, ElButton, ElMessage } from 'element-plus';
|
|
||||||
// import base style
|
|
||||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
|
||||||
import { MonacoEditorDialogProps } from './MonacoEditorDialog';
|
|
||||||
import { i18n } from '@/i18n';
|
|
||||||
|
|
||||||
const editorRef: any = ref(null);
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
dialogVisible: false,
|
|
||||||
height: '450px',
|
|
||||||
width: '800px',
|
|
||||||
contentValue: '',
|
|
||||||
title: '',
|
|
||||||
language: '',
|
|
||||||
showConfirmButton: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
let confirmFn: any;
|
|
||||||
let cancelFn: any;
|
|
||||||
|
|
||||||
const { contentValue } = toRefs(state);
|
|
||||||
|
|
||||||
function compressHTML(html: string) {
|
|
||||||
return (
|
|
||||||
html
|
|
||||||
.replace(/[\r\n\t]+/g, ' ') // 移除换行符和制表符
|
|
||||||
// .replace(/<!--[\s\S]*?-->/g, '') // 移除注释
|
|
||||||
.replace(/\s{2,}/g, ' ') // 合并多个空格为一个空格
|
|
||||||
.replace(/>\s+</g, '><')
|
|
||||||
); // 移除标签之间的空格
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 确认按钮
|
|
||||||
*/
|
|
||||||
const confirm = async () => {
|
|
||||||
if (confirmFn) {
|
|
||||||
if (state.language === 'json') {
|
|
||||||
let val;
|
|
||||||
try {
|
|
||||||
val = JSON.parse(contentValue.value);
|
|
||||||
if (typeof val !== 'object') {
|
|
||||||
ElMessage.error('请输入正确的json');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
ElMessage.error('请输入正确的json');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 压缩json字符串
|
|
||||||
confirmFn(JSON.stringify(val));
|
|
||||||
} else if (state.language === 'html') {
|
|
||||||
// 压缩html字符串
|
|
||||||
confirmFn(compressHTML(contentValue.value));
|
|
||||||
} else {
|
|
||||||
confirmFn(contentValue.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.dialogVisible = false;
|
|
||||||
setTimeout(() => {
|
|
||||||
state.contentValue = '';
|
|
||||||
state.title = '';
|
|
||||||
}, 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
const cancel = () => {
|
|
||||||
state.dialogVisible = false;
|
|
||||||
// 没有执行成功,并且取消回调函数存在,则执行
|
|
||||||
cancelFn && cancelFn();
|
|
||||||
setTimeout(() => {
|
|
||||||
state.contentValue = '';
|
|
||||||
state.title = '';
|
|
||||||
}, 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatXML = function (xml: string, tab?: string) {
|
|
||||||
let formatted = '',
|
|
||||||
indent = '';
|
|
||||||
tab = tab || ' ';
|
|
||||||
xml.split(/>\s*</).forEach(function (node) {
|
|
||||||
if (node.match(/^\/\w/)) indent = indent.substring(tab!.length);
|
|
||||||
formatted += indent + '<' + node + '>\r\n';
|
|
||||||
if (node.match(/^<?\w[^>]*[^\/]$/)) indent += tab;
|
|
||||||
});
|
|
||||||
return formatted.substring(1, formatted.length - 3);
|
|
||||||
};
|
|
||||||
|
|
||||||
const open = (optionProps: MonacoEditorDialogProps) => {
|
|
||||||
confirmFn = optionProps.confirmFn;
|
|
||||||
cancelFn = optionProps.cancelFn;
|
|
||||||
|
|
||||||
if (optionProps.showConfirmButton === undefined) {
|
|
||||||
state.showConfirmButton = true;
|
|
||||||
} else {
|
|
||||||
state.showConfirmButton = optionProps.showConfirmButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
const language = optionProps.language;
|
|
||||||
state.language = language;
|
|
||||||
state.title = optionProps.title;
|
|
||||||
if (optionProps.height) {
|
|
||||||
state.height = optionProps.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.contentValue = optionProps.content;
|
|
||||||
// 格式化输出html;
|
|
||||||
if (language === 'html' || language == 'xml') {
|
|
||||||
state.contentValue = formatXML(optionProps.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
editorRef.value?.focus();
|
|
||||||
editorRef.value?.format();
|
|
||||||
}, 300);
|
|
||||||
|
|
||||||
state.dialogVisible = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({ open });
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.editor {
|
|
||||||
font-size: 9pt;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -444,5 +444,9 @@ export default {
|
|||||||
last5runTimes: 'Last 5 running times',
|
last5runTimes: 'Last 5 running times',
|
||||||
calculationing: 'In the calculation result',
|
calculationing: 'In the calculation result',
|
||||||
},
|
},
|
||||||
|
iconSelector: {
|
||||||
|
title: 'please select the icon',
|
||||||
|
placeholder: 'please enter content search icon or select icon',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -452,5 +452,9 @@ export default {
|
|||||||
last5runTimes: '最近5次运行时间',
|
last5runTimes: '最近5次运行时间',
|
||||||
calculationing: '计算结果中',
|
calculationing: '计算结果中',
|
||||||
},
|
},
|
||||||
|
iconSelector: {
|
||||||
|
title: '请选择图标',
|
||||||
|
placeholder: '请输入内容搜索图标或者选择图标',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,8 +88,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 第三方图标字体间距/大小设置
|
// 第三方图标字体间距/大小设置
|
||||||
.el-menu-item .iconfont,
|
.el-menu-item .icon,
|
||||||
.el-sub-menu .iconfont,
|
.el-sub-menu .icon,
|
||||||
.el-menu-item .fa,
|
.el-menu-item .fa,
|
||||||
.el-sub-menu .fa {
|
.el-sub-menu .fa {
|
||||||
@include mixins.generalIcon;
|
@include mixins.generalIcon;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="dataSql" :label="$t('db.srcDataSql')" required>
|
<el-form-item prop="dataSql" :label="$t('db.srcDataSql')" required>
|
||||||
<monaco-editor height="150px" class="task-sql" language="sql" v-model="form.dataSql" />
|
<monaco-editor height="200px" class="task-sql" language="sql" v-model="form.dataSql" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -90,8 +90,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-row>
|
<el-row class="w100">
|
||||||
<el-col :span="8">
|
<el-col :span="12">
|
||||||
<el-form-item class="w100" prop="updField">
|
<el-form-item class="w100" prop="updField">
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ $t('db.updateField') }}
|
{{ $t('db.updateField') }}
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="8">
|
<el-col :span="12">
|
||||||
<el-form-item class="w100" prop="updFieldVal">
|
<el-form-item class="w100" prop="updFieldVal">
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ $t('db.updateFieldValue') }}
|
{{ $t('db.updateFieldValue') }}
|
||||||
@@ -116,8 +116,12 @@
|
|||||||
<el-input v-model.trim="form.updFieldVal" :placeholder="$t('db.updateFieldValuePlaceholder')" auto-complete="off" />
|
<el-input v-model.trim="form.updFieldVal" :placeholder="$t('db.updateFieldValuePlaceholder')" auto-complete="off" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-col :span="8">
|
<el-form-item>
|
||||||
|
<el-row class="w100">
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item class="w100" prop="updFieldSrc">
|
<el-form-item class="w100" prop="updFieldSrc">
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ $t('db.fieldValueSrc') }}
|
{{ $t('db.fieldValueSrc') }}
|
||||||
@@ -136,7 +140,7 @@
|
|||||||
|
|
||||||
<el-tab-pane :label="$t('db.fieldMap')" :name="fieldTab" :disabled="!baseFieldCompleted">
|
<el-tab-pane :label="$t('db.fieldMap')" :name="fieldTab" :disabled="!baseFieldCompleted">
|
||||||
<el-form-item prop="fieldMap" :label="$t('db.fieldMap')" required>
|
<el-form-item prop="fieldMap" :label="$t('db.fieldMap')" required>
|
||||||
<el-table :data="form.fieldMap" :max-height="650" size="small">
|
<el-table :data="form.fieldMap" :max-height="fieldMapTableHeight" size="small">
|
||||||
<el-table-column prop="src" :label="$t('db.srcField')" :width="200" />
|
<el-table-column prop="src" :label="$t('db.srcField')" :width="200" />
|
||||||
<el-table-column prop="target" :label="$t('db.targetField')">
|
<el-table-column prop="target" :label="$t('db.targetField')">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -159,10 +163,10 @@
|
|||||||
<EnumSelect :enums="DbDataSyncDuplicateStrategyEnum" v-model="form.duplicateStrategy" @change="handleDuplicateStrategy" />
|
<EnumSelect :enums="DbDataSyncDuplicateStrategyEnum" v-model="form.duplicateStrategy" @change="handleDuplicateStrategy" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="fieldMap" :label="$t('db.selectSql')">
|
<el-form-item prop="fieldMap" :label="$t('db.selectSql')">
|
||||||
<el-input type="textarea" v-model="state.previewDataSql" readonly :input-style="{ height: '300px' }" />
|
<el-input type="textarea" v-model="state.previewDataSql" readonly :rows="10" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="fieldMap" :label="$t('db.insertSql')">
|
<el-form-item prop="fieldMap" :label="$t('db.insertSql')">
|
||||||
<el-input type="textarea" v-model="state.previewInsertSql" readonly :input-style="{ height: '300px' }" />
|
<el-input type="textarea" v-model="state.previewInsertSql" readonly :rows="10" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
@@ -327,9 +331,10 @@ const state = reactive({
|
|||||||
previewDataSql: '',
|
previewDataSql: '',
|
||||||
previewInsertSql: '',
|
previewInsertSql: '',
|
||||||
previewFieldArr: [] as string[],
|
previewFieldArr: [] as string[],
|
||||||
|
fieldMapTableHeight: window.innerHeight - 50,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { tabActiveName, form, submitForm } = toRefs(state);
|
const { tabActiveName, form, submitForm, fieldMapTableHeight } = toRefs(state);
|
||||||
|
|
||||||
const { isFetching: saveBtnLoading, execute: saveExec } = dbApi.saveDatasyncTask.useApi(submitForm);
|
const { isFetching: saveBtnLoading, execute: saveExec } = dbApi.saveDatasyncTask.useApi(submitForm);
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ import { computed, nextTick, ref, Ref } from 'vue';
|
|||||||
import { ElInput, ElMessage } from 'element-plus';
|
import { ElInput, ElMessage } from 'element-plus';
|
||||||
import { DataType } from '../../dialect/index';
|
import { DataType } from '../../dialect/index';
|
||||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||||
import MonacoEditorDialog from '@/components/monaco/MonacoEditorDialog';
|
import MonacoEditorBox from '@/components/monaco/MonacoEditorBox';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -123,7 +123,7 @@ const openEditor = () => {
|
|||||||
editorOpening.value = true;
|
editorOpening.value = true;
|
||||||
// 编辑器语言,如:json、html、text
|
// 编辑器语言,如:json、html、text
|
||||||
let editorLang = getEditorLangByValue(itemValue.value);
|
let editorLang = getEditorLangByValue(itemValue.value);
|
||||||
MonacoEditorDialog({
|
MonacoEditorBox({
|
||||||
content: itemValue.value,
|
content: itemValue.value,
|
||||||
title: `${t('db.editField')} [${props.columnName}]`,
|
title: `${t('db.editField')} [${props.columnName}]`,
|
||||||
language: editorLang,
|
language: editorLang,
|
||||||
@@ -131,7 +131,7 @@ const openEditor = () => {
|
|||||||
itemValue.value = newVal;
|
itemValue.value = newVal;
|
||||||
closeEditorDialog();
|
closeEditorDialog();
|
||||||
},
|
},
|
||||||
cancelFn: closeEditorDialog,
|
closeFn: closeEditorDialog,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ const columns = [
|
|||||||
TableColumn.new('name', 'common.name'),
|
TableColumn.new('name', 'common.name'),
|
||||||
TableColumn.new('ipPort', 'Ip:Port').isSlot().setAddWidth(50),
|
TableColumn.new('ipPort', 'Ip:Port').isSlot().setAddWidth(50),
|
||||||
TableColumn.new('authCerts[0].username', 'machine.acName').isSlot('authCert').setAddWidth(10),
|
TableColumn.new('authCerts[0].username', 'machine.acName').isSlot('authCert').setAddWidth(10),
|
||||||
TableColumn.new('status', 'common.status').isSlot(),
|
TableColumn.new('status', 'common.status').isSlot().setAddWidth(5),
|
||||||
TableColumn.new('stat', 'machine.runningStat').isSlot().setAddWidth(55),
|
TableColumn.new('stat', 'machine.runningStat').isSlot().setAddWidth(55),
|
||||||
TableColumn.new('fs', 'machine.fs').isSlot().setAddWidth(25),
|
TableColumn.new('fs', 'machine.fs').isSlot().setAddWidth(25),
|
||||||
TableColumn.new('remark', 'common.remark'),
|
TableColumn.new('remark', 'common.remark'),
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ require (
|
|||||||
github.com/tidwall/gjson v1.18.0
|
github.com/tidwall/gjson v1.18.0
|
||||||
github.com/veops/go-ansiterm v0.0.5
|
github.com/veops/go-ansiterm v0.0.5
|
||||||
go.mongodb.org/mongo-driver v1.16.0 // mongo
|
go.mongodb.org/mongo-driver v1.16.0 // mongo
|
||||||
golang.org/x/crypto v0.31.0 // ssh
|
golang.org/x/crypto v0.32.0 // ssh
|
||||||
golang.org/x/oauth2 v0.24.0
|
golang.org/x/oauth2 v0.25.0
|
||||||
golang.org/x/sync v0.10.0
|
golang.org/x/sync v0.10.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
@@ -93,7 +93,7 @@ require (
|
|||||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||||
golang.org/x/image v0.13.0 // indirect
|
golang.org/x/image v0.13.0 // indirect
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.28.0 // indirect
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
golang.org/x/text v0.21.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
google.golang.org/protobuf v1.34.1 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
modernc.org/libc v1.22.5 // indirect
|
modernc.org/libc v1.22.5 // indirect
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/may-fly/cast"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataSyncTask interface {
|
type DataSyncTask interface {
|
||||||
@@ -348,7 +349,7 @@ func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap [
|
|||||||
updFieldVal = srcRes[len(srcRes)-1][strings.ToLower(field)]
|
updFieldVal = srcRes[len(srcRes)-1][strings.ToLower(field)]
|
||||||
}
|
}
|
||||||
|
|
||||||
task.UpdFieldVal = updFieldType.DataType.SQLValue(updFieldVal)
|
task.UpdFieldVal = cast.ToString(updFieldVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果指定了更新字段,则以更新字段取值
|
// 如果指定了更新字段,则以更新字段取值
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ func (d *dbSqlExecAppImpl) doUpdate(ctx context.Context, sqlExecParam *sqlExecPa
|
|||||||
nowRec++
|
nowRec++
|
||||||
res = append(res, row)
|
res = append(res, row)
|
||||||
if nowRec == maxRec {
|
if nowRec == maxRec {
|
||||||
return errorx.NewBiz(fmt.Sprintf("update SQL - the maximum number of updated queries is exceeded: %d", maxRec))
|
return errorx.NewBiz("update SQL - the maximum number of updated queries is exceeded: %d", maxRec)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -535,12 +535,13 @@ func (d *dbSqlExecAppImpl) doDelete(ctx context.Context, sqlExecParam *sqlExecPa
|
|||||||
}
|
}
|
||||||
execRecord.Table = tableName
|
execRecord.Table = tableName
|
||||||
|
|
||||||
whereStr := deletestmt.Where.GetText()
|
deleteWhere := deletestmt.Where
|
||||||
if whereStr == "" {
|
if deleteWhere == nil {
|
||||||
logx.ErrorContext(ctx, "delete SQL - there is no where condition")
|
logx.ErrorContext(ctx, "delete SQL - there is no where condition")
|
||||||
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
whereStr := deleteWhere.GetText()
|
||||||
// 查询删除数据
|
// 查询删除数据
|
||||||
selectSql := fmt.Sprintf("SELECT * FROM %s where %s LIMIT 200", tableName+" "+tableAlias, whereStr)
|
selectSql := fmt.Sprintf("SELECT * FROM %s where %s LIMIT 200", tableName+" "+tableAlias, whereStr)
|
||||||
_, res, _ := dbConn.QueryContext(ctx, selectSql)
|
_, res, _ := dbConn.QueryContext(ctx, selectSql)
|
||||||
|
|||||||
@@ -67,13 +67,13 @@ func (dbInfo *DbInfo) Conn(meta Meta) (*DbConn, error) {
|
|||||||
conn, err := meta.GetSqlDb(dbInfo)
|
conn, err := meta.GetSqlDb(dbInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("db connection failed: %s:%d/%s, err:%s", dbInfo.Host, dbInfo.Port, database, err.Error())
|
logx.Errorf("db connection failed: %s:%d/%s, err:%s", dbInfo.Host, dbInfo.Port, database, err.Error())
|
||||||
return nil, errorx.NewBiz(fmt.Sprintf("db connection failed: %s", err.Error()))
|
return nil, errorx.NewBiz("db connection failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conn.Ping()
|
err = conn.Ping()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("db ping failed: %s:%d/%s, err:%s", dbInfo.Host, dbInfo.Port, database, err.Error())
|
logx.Errorf("db ping failed: %s:%d/%s, err:%s", dbInfo.Host, dbInfo.Port, database, err.Error())
|
||||||
return nil, errorx.NewBiz(fmt.Sprintf("db connection failed: %s", err.Error()))
|
return nil, errorx.NewBiz("db connection failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
dbc := &DbConn{Id: GetDbConnId(dbInfo.Id, database), Info: dbInfo}
|
dbc := &DbConn{Id: GetDbConnId(dbInfo.Id, database), Info: dbInfo}
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ func (m *machineFileAppImpl) WriteFileContent(ctx context.Context, opParam *dto.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := sftpCli.OpenFile(path, os.O_RDWR)
|
f, err := sftpCli.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_TRUNC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mi, err
|
return mi, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user