mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 16:00:25 +08:00
refactor: 数据库表支持editor编辑调整
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<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="monacoTextarea" :style="{ height: height }"></div>
|
||||||
<el-select v-if="canChangeMode" class="code-mode-select" v-model="languageMode" @change="changeLanguage">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
@@ -294,17 +294,19 @@ const registeShell = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const format = () => {
|
const format = () => {
|
||||||
/*
|
// 触发自动格式化;
|
||||||
触发自动格式化;
|
|
||||||
*/
|
|
||||||
monacoEditorIns.trigger('', 'editor.action.formatDocument', '');
|
monacoEditorIns.trigger('', 'editor.action.formatDocument', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const focus = () => {
|
||||||
|
monacoEditorIns.focus();
|
||||||
|
};
|
||||||
|
|
||||||
const getEditor = () => {
|
const getEditor = () => {
|
||||||
return monacoEditorIns;
|
return monacoEditorIns;
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ getEditor, format });
|
defineExpose({ getEditor, format, focus });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export type MonacoEditorDialogProps = {
|
|||||||
language: string;
|
language: string;
|
||||||
height?: string;
|
height?: string;
|
||||||
width?: string;
|
width?: string;
|
||||||
confirmFn?: Function;
|
confirmFn?: Function; // 点击确认的回调函数,入参editor value
|
||||||
cancelFn?: Function;
|
cancelFn?: Function; // 点击取消 或 关闭弹窗的回调函数
|
||||||
};
|
};
|
||||||
|
|
||||||
const boxId = 'monaco-editor-dialog-id';
|
const boxId = 'monaco-editor-dialog-id';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-dialog :title="state.title" v-model="state.dialogVisible" :width="state.width" @close="cancel">
|
<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" />
|
<monaco-editor ref="editorRef" :height="state.height" class="editor" :language="state.language" v-model="contentValue" can-change-mode />
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="cancel">取消</el-button>
|
<el-button @click="cancel">取消</el-button>
|
||||||
@@ -120,6 +120,7 @@ const open = (optionProps: MonacoEditorDialogProps) => {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
editorRef.value?.format();
|
editorRef.value?.format();
|
||||||
|
editorRef.value?.focus();
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
state.dialogVisible = true;
|
state.dialogVisible = true;
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.color-success {
|
.color-success {
|
||||||
color: var(--el-color-success);
|
color: var(--el-color-success) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-warning {
|
.color-warning {
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-input
|
<div class="string-input-container w100" v-if="dataType == DataType.String">
|
||||||
v-if="dataType == DataType.String"
|
<el-input
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
v-if="dataType == DataType.String"
|
||||||
@blur="emit('blur')"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
class="w100 mb4"
|
@blur="handlerBlur"
|
||||||
input-style="text-align: center; height: 26px;"
|
class="w100 mb4"
|
||||||
size="small"
|
input-style="text-align: center; height: 26px;"
|
||||||
v-model="itemValue"
|
size="small"
|
||||||
:placeholder="placeholder"
|
v-model="itemValue"
|
||||||
/>
|
:placeholder="placeholder"
|
||||||
|
/>
|
||||||
|
<SvgIcon v-if="showEditorIcon" @mousedown="openEditor" class="string-input-container-icon color-success" name="FullScreen" :size="10" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-input
|
<el-input
|
||||||
v-else-if="dataType == DataType.Number"
|
v-else-if="dataType == DataType.Number"
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
@blur="emit('blur')"
|
@blur="handlerBlur"
|
||||||
class="w100 mb4"
|
class="w100 mb4"
|
||||||
input-style="text-align: center; height: 26px;"
|
input-style="text-align: center; height: 26px;"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -26,7 +29,7 @@
|
|||||||
v-else-if="dataType == DataType.Date"
|
v-else-if="dataType == DataType.Date"
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
@change="emit('blur')"
|
@change="emit('blur')"
|
||||||
@blur="emit('blur')"
|
@blur="handlerBlur"
|
||||||
class="edit-time-picker mb4"
|
class="edit-time-picker mb4"
|
||||||
popper-class="edit-time-picker-popper"
|
popper-class="edit-time-picker-popper"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -41,7 +44,7 @@
|
|||||||
v-else-if="dataType == DataType.DateTime"
|
v-else-if="dataType == DataType.DateTime"
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
@change="emit('blur')"
|
@change="emit('blur')"
|
||||||
@blur="emit('blur')"
|
@blur="handlerBlur"
|
||||||
class="edit-time-picker mb4"
|
class="edit-time-picker mb4"
|
||||||
popper-class="edit-time-picker-popper"
|
popper-class="edit-time-picker-popper"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -56,7 +59,7 @@
|
|||||||
v-else-if="dataType == DataType.Time"
|
v-else-if="dataType == DataType.Time"
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
@change="emit('blur')"
|
@change="emit('blur')"
|
||||||
@blur="emit('blur')"
|
@blur="handlerBlur"
|
||||||
class="edit-time-picker mb4"
|
class="edit-time-picker mb4"
|
||||||
popper-class="edit-time-picker-popper"
|
popper-class="edit-time-picker-popper"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -68,16 +71,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Ref } from 'vue';
|
import { Ref, ref, computed } from 'vue';
|
||||||
import { ElInput } from 'element-plus';
|
import { ElInput } from 'element-plus';
|
||||||
import { DataType } from '../../dialect/index';
|
import { DataType } from '../../dialect/index';
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||||
|
import MonacoEditorDialog from '@/components/monaco/MonacoEditorDialog';
|
||||||
|
|
||||||
export interface ColumnFormItemProps {
|
export interface ColumnFormItemProps {
|
||||||
modelValue: string | number; // 绑定的值
|
modelValue: string | number; // 绑定的值
|
||||||
dataType: DataType; // 数据类型
|
dataType: DataType; // 数据类型
|
||||||
focus?: boolean; // 是否获取焦点
|
focus?: boolean; // 是否获取焦点
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
columnName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<ColumnFormItemProps>(), {
|
const props = withDefaults(defineProps<ColumnFormItemProps>(), {
|
||||||
@@ -88,9 +94,75 @@ const props = withDefaults(defineProps<ColumnFormItemProps>(), {
|
|||||||
const emit = defineEmits(['update:modelValue', 'blur']);
|
const emit = defineEmits(['update:modelValue', 'blur']);
|
||||||
|
|
||||||
const itemValue: Ref<any> = useVModel(props, 'modelValue', emit);
|
const itemValue: Ref<any> = useVModel(props, 'modelValue', emit);
|
||||||
|
|
||||||
|
const showEditorIcon = computed(() => {
|
||||||
|
return typeof itemValue.value === 'string' && itemValue.value.length > 50;
|
||||||
|
});
|
||||||
|
|
||||||
|
const editorOpening = ref(false);
|
||||||
|
|
||||||
|
const openEditor = () => {
|
||||||
|
editorOpening.value = true;
|
||||||
|
// 编辑器语言,如:json、html、text
|
||||||
|
let editorLang = getEditorLangByValue(itemValue.value);
|
||||||
|
MonacoEditorDialog({
|
||||||
|
content: itemValue.value,
|
||||||
|
title: `编辑字段 [${props.columnName}]`,
|
||||||
|
language: editorLang,
|
||||||
|
confirmFn: (newVal: any) => {
|
||||||
|
itemValue.value = newVal;
|
||||||
|
closeEditorDialog();
|
||||||
|
},
|
||||||
|
cancelFn: closeEditorDialog,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeEditorDialog = () => {
|
||||||
|
editorOpening.value = false;
|
||||||
|
handlerBlur();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerBlur = () => {
|
||||||
|
if (editorOpening.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('blur');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEditorLangByValue = (value: any) => {
|
||||||
|
// 判断是否是json
|
||||||
|
try {
|
||||||
|
if (typeof JSON.parse(value) === 'object') {
|
||||||
|
return 'json';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否是html
|
||||||
|
try {
|
||||||
|
const doc = new DOMParser().parseFromString(value, 'text/html');
|
||||||
|
if (Array.from(doc.body.childNodes).some((node) => node.nodeType === 1)) {
|
||||||
|
return 'html';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'text';
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.string-input-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.string-input-container-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px; /* 调整图标的垂直位置 */
|
||||||
|
right: 5px; /* 调整图标的水平位置 */
|
||||||
|
}
|
||||||
|
|
||||||
.edit-time-picker {
|
.edit-time-picker {
|
||||||
height: 26px;
|
height: 26px;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
|
|||||||
@@ -79,8 +79,9 @@
|
|||||||
<div v-if="canEdit(rowIndex, columnIndex)">
|
<div v-if="canEdit(rowIndex, columnIndex)">
|
||||||
<ColumnFormItem
|
<ColumnFormItem
|
||||||
v-model="rowData[column.dataKey!]"
|
v-model="rowData[column.dataKey!]"
|
||||||
:data-type="nowUpdateCell.dataType"
|
:data-type="column.dataType"
|
||||||
@blur="onExitEditMode(rowData, column, rowIndex)"
|
@blur="onExitEditMode(rowData, column, rowIndex)"
|
||||||
|
:column-name="column.columnName"
|
||||||
focus
|
focus
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,7 +145,6 @@ import { dateStrFormat } from '@/common/utils/date';
|
|||||||
import { useIntervalFn } from '@vueuse/core';
|
import { useIntervalFn } from '@vueuse/core';
|
||||||
import { ColumnTypeSubscript, DataType, DbDialect, DbType, getDbDialect } from '../../dialect/index';
|
import { ColumnTypeSubscript, DataType, DbDialect, DbType, getDbDialect } from '../../dialect/index';
|
||||||
import ColumnFormItem from './ColumnFormItem.vue';
|
import ColumnFormItem from './ColumnFormItem.vue';
|
||||||
import MonacoEditorDialog from '@/components/monaco/MonacoEditorDialog';
|
|
||||||
|
|
||||||
const emits = defineEmits(['dataDelete', 'sortChange', 'deleteData', 'selectionChange', 'changeUpdatedField']);
|
const emits = defineEmits(['dataDelete', 'sortChange', 'deleteData', 'selectionChange', 'changeUpdatedField']);
|
||||||
|
|
||||||
@@ -315,7 +315,6 @@ const state = reactive({
|
|||||||
loading: false,
|
loading: false,
|
||||||
tableHeight: '600px',
|
tableHeight: '600px',
|
||||||
emptyText: '',
|
emptyText: '',
|
||||||
editorLang: 'string',
|
|
||||||
|
|
||||||
execTime: 0,
|
execTime: 0,
|
||||||
contextmenu: {
|
contextmenu: {
|
||||||
@@ -488,7 +487,7 @@ const cancelLoading = async () => {
|
|||||||
* @param colIndex ci
|
* @param colIndex ci
|
||||||
*/
|
*/
|
||||||
const canEdit = (rowIndex: number, colIndex: number) => {
|
const canEdit = (rowIndex: number, colIndex: number) => {
|
||||||
return state.table && nowUpdateCell?.rowIndex == rowIndex && nowUpdateCell?.colIndex == colIndex && state.editorLang === 'string';
|
return state.table && nowUpdateCell?.rowIndex == rowIndex && nowUpdateCell?.colIndex == colIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -643,29 +642,6 @@ const onExportSql = async () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getEditorLangByValue = (value: any) => {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
// 判断是否是json
|
|
||||||
try {
|
|
||||||
if (typeof JSON.parse(value) === 'object') {
|
|
||||||
return 'json';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
// 判断是否是html
|
|
||||||
try {
|
|
||||||
const doc = new DOMParser().parseFromString(value, 'text/html');
|
|
||||||
if (Array.from(doc.body.childNodes).some((node) => node.nodeType === 1)) {
|
|
||||||
return 'html';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
/* empty */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'string';
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEnterEditMode = (rowData: any, column: any, rowIndex = 0, columnIndex = 0) => {
|
const onEnterEditMode = (rowData: any, column: any, rowIndex = 0, columnIndex = 0) => {
|
||||||
if (!state.table) {
|
if (!state.table) {
|
||||||
return;
|
return;
|
||||||
@@ -678,21 +654,6 @@ const onEnterEditMode = (rowData: any, column: any, rowIndex = 0, columnIndex =
|
|||||||
oldValue: rowData[column.dataKey],
|
oldValue: rowData[column.dataKey],
|
||||||
dataType: column.dataType,
|
dataType: column.dataType,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 编辑器语言,如:json、html、string,目前支持json、html使用MonacoEditor编辑器
|
|
||||||
let editorLang = getEditorLangByValue(rowData[column.dataKey]);
|
|
||||||
state.editorLang = editorLang;
|
|
||||||
if (editorLang === 'html' || editorLang === 'json') {
|
|
||||||
MonacoEditorDialog({
|
|
||||||
content: rowData[column.dataKey],
|
|
||||||
title: `编辑字段 [${column.dataKey}]`,
|
|
||||||
language: editorLang,
|
|
||||||
confirmFn: (newVal: any) => {
|
|
||||||
rowData[column.dataKey] = newVal;
|
|
||||||
onExitEditMode(rowData, column, rowIndex);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onExitEditMode = (rowData: any, column: any, rowIndex = 0) => {
|
const onExitEditMode = (rowData: any, column: any, rowIndex = 0) => {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
@keyup.enter.native="onSelectByCondition"
|
@keyup.enter.native="onSelectByCondition"
|
||||||
@select="handlerColumnSelect"
|
@select="handlerColumnSelect"
|
||||||
popper-class="my-autocomplete"
|
popper-class="my-autocomplete"
|
||||||
placeholder="可输入SQL条件表达式后回车或点击查询图标过滤结果, 可根据备注或字段名提示"
|
placeholder="选择列 或 输入SQL条件表达式后回车或点击查询图标过滤结果, 输入时可根据字段名提示"
|
||||||
@clear="selectData"
|
@clear="selectData"
|
||||||
size="small"
|
size="small"
|
||||||
clearable
|
clearable
|
||||||
@@ -90,6 +90,38 @@
|
|||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #prepend>
|
||||||
|
<el-popover :visible="state.condPopVisible" trigger="click" :width="320" placement="right">
|
||||||
|
<template #reference>
|
||||||
|
<el-button @click.stop="chooseCondColumnName" class="color-success" text size="small">选择列</el-button>
|
||||||
|
</template>
|
||||||
|
<el-table
|
||||||
|
:data="filterCondColumns"
|
||||||
|
max-height="500"
|
||||||
|
size="small"
|
||||||
|
@row-click="
|
||||||
|
(...event: any) => {
|
||||||
|
onConditionRowClick(event);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
style="cursor: pointer"
|
||||||
|
>
|
||||||
|
<el-table-column property="columnName" label="列名" show-overflow-tooltip>
|
||||||
|
<template #header>
|
||||||
|
<el-input
|
||||||
|
ref="columnNameSearchInputRef"
|
||||||
|
v-model="state.columnNameSearch"
|
||||||
|
size="small"
|
||||||
|
placeholder="输入列名或备注过滤"
|
||||||
|
@click.stop="(e: any) => e.preventDefault()"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column property="columnComment" label="备注" show-overflow-tooltip> </el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
</el-autocomplete>
|
</el-autocomplete>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -126,6 +158,35 @@
|
|||||||
<span>{{ state.sql }}</span>
|
<span>{{ state.sql }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-dialog v-model="conditionDialog.visible" :title="conditionDialog.title" width="420px">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="5">
|
||||||
|
<el-select v-model="conditionDialog.condition">
|
||||||
|
<el-option label="=" value="="> </el-option>
|
||||||
|
<el-option label="LIKE" value="LIKE"> </el-option>
|
||||||
|
<el-option label=">" value=">"> </el-option>
|
||||||
|
<el-option label=">=" value=">="> </el-option>
|
||||||
|
<el-option label="<" value="<"> </el-option>
|
||||||
|
<el-option label="<=" value="<="> </el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="19">
|
||||||
|
<el-input
|
||||||
|
@keyup.enter.native="onConfirmCondition"
|
||||||
|
ref="condDialogInputRef"
|
||||||
|
v-model="conditionDialog.value"
|
||||||
|
:placeholder="conditionDialog.placeholder"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="onCancelCondition">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onConfirmCondition">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog v-model="addDataDialog.visible" :title="addDataDialog.title" :destroy-on-close="true" width="600px">
|
<el-dialog v-model="addDataDialog.visible" :title="addDataDialog.title" :destroy-on-close="true" width="600px">
|
||||||
<el-form ref="dataForm" :model="addDataDialog.data" label-width="auto" size="small">
|
<el-form ref="dataForm" :model="addDataDialog.data" label-width="auto" size="small">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
@@ -140,6 +201,7 @@
|
|||||||
v-model="addDataDialog.data[`${column.columnName}`]"
|
v-model="addDataDialog.data[`${column.columnName}`]"
|
||||||
:data-type="dbDialect.getDataType(column.columnType)"
|
:data-type="dbDialect.getDataType(column.columnType)"
|
||||||
:placeholder="`${column.columnType} ${column.columnComment}`"
|
:placeholder="`${column.columnType} ${column.columnComment}`"
|
||||||
|
:column-name="column.columnName"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -154,7 +216,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, reactive, Ref, ref, toRefs, watch } from 'vue';
|
import { computed, onMounted, reactive, Ref, ref, toRefs, watch } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
import { DbInst } from '@/views/ops/db/db';
|
import { DbInst } from '@/views/ops/db/db';
|
||||||
@@ -162,6 +224,7 @@ import DbTableData from './DbTableData.vue';
|
|||||||
import { DbDialect, getDbDialect } from '@/views/ops/db/dialect';
|
import { DbDialect, getDbDialect } from '@/views/ops/db/dialect';
|
||||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||||
import ColumnFormItem from './ColumnFormItem.vue';
|
import ColumnFormItem from './ColumnFormItem.vue';
|
||||||
|
import { useEventListener } from '@vueuse/core';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
dbId: {
|
dbId: {
|
||||||
@@ -185,6 +248,8 @@ const props = defineProps({
|
|||||||
const dataForm: any = ref(null);
|
const dataForm: any = ref(null);
|
||||||
const dbTableRef: Ref = ref(null);
|
const dbTableRef: Ref = ref(null);
|
||||||
const condInputRef: Ref = ref(null);
|
const condInputRef: Ref = ref(null);
|
||||||
|
const columnNameSearchInputRef: Ref = ref(null);
|
||||||
|
const condDialogInputRef: Ref = ref(null);
|
||||||
|
|
||||||
const defaultPageSize = DbInst.DefaultLimit;
|
const defaultPageSize = DbInst.DefaultLimit;
|
||||||
|
|
||||||
@@ -208,6 +273,17 @@ const state = reactive({
|
|||||||
],
|
],
|
||||||
count: 0,
|
count: 0,
|
||||||
selectionDatas: [] as any,
|
selectionDatas: [] as any,
|
||||||
|
condPopVisible: false,
|
||||||
|
columnNameSearch: '',
|
||||||
|
conditionDialog: {
|
||||||
|
title: '',
|
||||||
|
placeholder: '',
|
||||||
|
columnRow: null,
|
||||||
|
dataTab: null,
|
||||||
|
visible: false,
|
||||||
|
condition: '=',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
addDataDialog: {
|
addDataDialog: {
|
||||||
data: {},
|
data: {},
|
||||||
title: '',
|
title: '',
|
||||||
@@ -219,7 +295,7 @@ const state = reactive({
|
|||||||
dbDialect: {} as DbDialect,
|
dbDialect: {} as DbDialect,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { datas, condition, loading, columns, pageNum, pageSize, pageSizes, count, hasUpdatedFileds, addDataDialog, dbDialect } = toRefs(state);
|
const { datas, condition, loading, columns, pageNum, pageSize, pageSizes, count, hasUpdatedFileds, conditionDialog, addDataDialog, dbDialect } = toRefs(state);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.tableHeight,
|
() => props.tableHeight,
|
||||||
@@ -243,8 +319,15 @@ onMounted(async () => {
|
|||||||
await onRefresh();
|
await onRefresh();
|
||||||
|
|
||||||
state.dbDialect = getDbDialect(getNowDbInst().type);
|
state.dbDialect = getDbDialect(getNowDbInst().type);
|
||||||
|
useEventListener('click', handlerWindowClick);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handlerWindowClick = () => {
|
||||||
|
if (state.condPopVisible) {
|
||||||
|
state.condPopVisible = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onRefresh = async () => {
|
const onRefresh = async () => {
|
||||||
state.pageNum = 1;
|
state.pageNum = 1;
|
||||||
await selectData();
|
await selectData();
|
||||||
@@ -302,7 +385,7 @@ const getColumnTips = (queryString: string, callback: any) => {
|
|||||||
if (columnNameSearch) {
|
if (columnNameSearch) {
|
||||||
columnNameSearch = columnNameSearch.toLowerCase();
|
columnNameSearch = columnNameSearch.toLowerCase();
|
||||||
res = columns.filter((data: any) => {
|
res = columns.filter((data: any) => {
|
||||||
return data.columnName.toLowerCase().includes(columnNameSearch) || data.columnComment.includes(columnNameSearch);
|
return data.columnName.toLowerCase().includes(columnNameSearch);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,6 +414,69 @@ const handlerColumnSelect = (column: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择条件列
|
||||||
|
*/
|
||||||
|
const chooseCondColumnName = () => {
|
||||||
|
state.condPopVisible = !state.condPopVisible;
|
||||||
|
if (state.condPopVisible) {
|
||||||
|
columnNameSearchInputRef.value.clear();
|
||||||
|
columnNameSearchInputRef.value.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤条件列名
|
||||||
|
*/
|
||||||
|
const filterCondColumns = computed(() => {
|
||||||
|
const columns = state.columns;
|
||||||
|
let columnNameSearch = state.columnNameSearch;
|
||||||
|
if (!columnNameSearch) {
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
columnNameSearch = columnNameSearch.toLowerCase();
|
||||||
|
return columns.filter((data: any) => {
|
||||||
|
return data.columnName.toLowerCase().includes(columnNameSearch) || data.columnComment.toLowerCase().includes(columnNameSearch);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 条件查询,点击列信息后显示输入对应的值
|
||||||
|
*/
|
||||||
|
const onConditionRowClick = (event: any) => {
|
||||||
|
const row = event[0];
|
||||||
|
state.conditionDialog.title = `请输入 [${row.columnName}] 的值`;
|
||||||
|
state.conditionDialog.placeholder = `${row.columnType} ${row.columnComment}`;
|
||||||
|
state.conditionDialog.columnRow = row;
|
||||||
|
state.conditionDialog.visible = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
condDialogInputRef.value.focus();
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确认条件
|
||||||
|
const onConfirmCondition = () => {
|
||||||
|
const conditionDialog = state.conditionDialog;
|
||||||
|
let condition = state.condition;
|
||||||
|
if (condition) {
|
||||||
|
condition += ` AND `;
|
||||||
|
}
|
||||||
|
const row = conditionDialog.columnRow as any;
|
||||||
|
condition += `${row.columnName} ${conditionDialog.condition} `;
|
||||||
|
state.condition = condition + DbInst.wrapColumnValue(row.columnType, conditionDialog.value);
|
||||||
|
onCancelCondition();
|
||||||
|
condInputRef.value.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCancelCondition = () => {
|
||||||
|
state.conditionDialog.visible = false;
|
||||||
|
state.conditionDialog.title = ``;
|
||||||
|
state.conditionDialog.placeholder = ``;
|
||||||
|
state.conditionDialog.value = null;
|
||||||
|
state.conditionDialog.columnRow = null;
|
||||||
|
state.conditionDialog.dataTab = null;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交事务,用于没有开启自动提交事务
|
* 提交事务,用于没有开启自动提交事务
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user