Skip to content

Commit 2700aa5

Browse files
JustaCattthLinx
authored andcommitted
fix(frontend): mongodb webconsole交互问题处理 #9915
1 parent 5ecd26b commit 2700aa5

File tree

4 files changed

+148
-75
lines changed

4 files changed

+148
-75
lines changed

dbm-ui/frontend/src/views/db-manage/common/webconsole/components/ClusterTabs.vue

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@
3030
class="add-icon-main">
3131
<DbIcon
3232
class="add-icon"
33-
type="increase"
34-
@click="handleClickAddIcon" />
33+
type="increase" />
3534
</div>
3635
</div>
3736
<div style="display: none">
@@ -40,24 +39,28 @@
4039
class="webconsole-select-clusters"
4140
:style="{ height: clustersPanelHeight }">
4241
<div class="title">{{ t('连接的集群') }}</div>
43-
<BkSelect
44-
ref="clutersRef"
45-
class="clusters-select"
46-
disable-focus-behavior
47-
filterable
48-
:model-value="selectedClusters"
49-
multiple
50-
:popover-options="{ disableTeleport: true }"
51-
@change="handleClusterSelectChange">
52-
<template #trigger>
53-
<span></span>
54-
</template>
55-
<BkOption
56-
v-for="item in clusterList"
57-
:key="item.id"
58-
:name="item.immute_domain"
59-
:value="item.id" />
60-
</BkSelect>
42+
<div class="clusters-select">
43+
<BkInput
44+
v-model="searchValue"
45+
behavior="simplicity"
46+
class="cluster-select-search"
47+
:placeholder="t('请输入关键字')">
48+
<template #prefix>
49+
<DbIcon
50+
class="input-icon"
51+
type="search" />
52+
</template>
53+
</BkInput>
54+
<ul class="cluster-select-warpper">
55+
<li
56+
v-for="item in renderOptions"
57+
:key="item.id"
58+
class="cluster-select-option"
59+
@click="handleClusterSelectChange([item.id])">
60+
{{ item.immute_domain }}
61+
</li>
62+
</ul>
63+
</div>
6164
</div>
6265
</div>
6366
</template>
@@ -93,23 +96,23 @@
9396
const props = defineProps<Props>();
9497
const emits = defineEmits<Emits>();
9598
99+
const modelValue = defineModel<Number>({
100+
default: 0,
101+
required: true,
102+
});
103+
96104
const { t } = useI18n();
97105
const route = useRoute();
98106
99-
const modelValue = defineModel({
100-
default: 0 as number,
101-
type: Number,
102-
});
103-
104107
const routeClusterId = route.query.clusterId;
105108
let clustersRaw: ClusterItem[] = [];
106109
let tippyIns: Instance | undefined;
107110
108-
const clutersRef = ref();
109111
const addTabRef = ref();
110112
const popRef = ref();
111113
const clustersMap = ref<Record<number, ClusterItem>>({});
112114
const selectedClusters = ref<number[]>([]);
115+
const searchValue = ref('');
113116
114117
const clustersPanelHeight = computed(() => {
115118
if (!clusterList.value) {
@@ -122,6 +125,10 @@
122125
return `${height}px`;
123126
});
124127
128+
const renderOptions = computed(() =>
129+
clusterList.value?.filter((item) => item.immute_domain.indexOf(searchValue.value) !== -1),
130+
);
131+
125132
const { data: clusterList } = useRequest(queryAllTypeCluster, {
126133
defaultParams: [
127134
{
@@ -189,17 +196,11 @@
189196
emits('removeTab', currentClusterId);
190197
// 关闭当前打开tab
191198
modelValue.value = clusterCount === 0 ? 0 : selectedClusters.value[clusterCount - 1];
192-
emits('change', clustersMap.value[modelValue.value]);
199+
emits('change', clustersMap.value[modelValue.value as number]);
193200
}
194201
updateClusterSelect();
195202
};
196203
197-
const handleClickAddIcon = () => {
198-
setTimeout(() => {
199-
clutersRef.value.showPopover();
200-
});
201-
};
202-
203204
onMounted(() => {
204205
tippyIns = tippy(addTabRef.value as SingleTarget, {
205206
appendTo: () => document.body,
@@ -209,14 +210,6 @@
209210
interactive: true,
210211
maxWidth: 'none',
211212
offset: [0, 0],
212-
onHide() {
213-
clutersRef.value.hidePopover();
214-
},
215-
onShow() {
216-
setTimeout(() => {
217-
clutersRef.value.showPopover();
218-
});
219-
},
220213
placement: 'bottom-start',
221214
theme: 'light',
222215
trigger: 'mouseenter click',
@@ -245,10 +238,42 @@
245238
padding: 0 !important;
246239
247240
.clusters-select {
248-
.bk-select-popover {
249-
border: none;
250-
transform: translate3d(0, 41px, 0);
251-
box-shadow: none;
241+
margin: 8px;
242+
243+
.cluster-select-search {
244+
border-bottom: 1px solid #eaebf0;
245+
}
246+
247+
.input-icon {
248+
display: flex;
249+
padding-left: 8px;
250+
font-size: 16px;
251+
color: #c4c6cc;
252+
align-items: center;
253+
justify-content: center;
254+
}
255+
256+
.cluster-select-warpper {
257+
margin-top: 4px;
258+
}
259+
260+
.cluster-select-option {
261+
position: relative;
262+
display: flex;
263+
height: 32px;
264+
overflow: hidden;
265+
font-size: 12px;
266+
color: #63656e;
267+
text-align: left;
268+
text-overflow: ellipsis;
269+
white-space: nowrap;
270+
cursor: pointer;
271+
user-select: none;
272+
align-items: center;
273+
274+
&:hover {
275+
background-color: #f5f7fa;
276+
}
252277
}
253278
}
254279
@@ -367,14 +392,6 @@
367392
font-size: 15px;
368393
color: #c4c6cc;
369394
}
370-
371-
.clusters-select {
372-
.bk-select-popover {
373-
border: none;
374-
transform: translate3d(0, 41px, 0);
375-
box-shadow: none;
376-
}
377-
}
378395
}
379396
}
380397
</style>

dbm-ui/frontend/src/views/db-manage/common/webconsole/components/console-panel/components/ConsoleInput.vue

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,23 @@
1818
</template>
1919
</div>
2020
<div v-show="loading">Waiting...</div>
21-
<div class="input-line">
21+
<div
22+
v-show="!loading"
23+
class="input-line">
2224
<textarea
2325
ref="inputRef"
2426
class="input-main"
25-
:disabled="loading"
27+
:disabled="isMouseMoving"
2628
:style="{ height: realHeight }"
2729
:value="command"
2830
@blur="handleInputBlur"
2931
@input="handleInputChange"
32+
@keydown.enter="handleClickSendCommand"
3033
@keyup.down="handleClickDownBtn"
31-
@keyup.enter.stop="handleClickSendCommand"
3234
@keyup.left="handleClickLeftBtn"
3335
@keyup.up="handleClickUpBtn" />
3436
</div>
3537
</div>
36-
<DisableTab />
3738
</template>
3839
<script lang="ts">
3940
// 未执行的命令
@@ -58,7 +59,8 @@
5859
5960
import { downloadText } from '@utils';
6061
61-
import DisableTab from './DisableTab.vue';
62+
import { useDisableTab } from './hooks/useDisableTab';
63+
import { useMouseSelect } from './hooks/useMouseSelect';
6264
6365
export interface Props {
6466
cluster: ServiceReturnType<typeof queryAllTypeCluster>[number];
@@ -91,6 +93,10 @@
9193
9294
const emits = defineEmits<Emits>();
9395
96+
useDisableTab();
97+
// 判断鼠标是否正在选中操作
98+
const { isMouseMoving } = useMouseSelect();
99+
94100
const command = ref('');
95101
const consolePanelRef = ref();
96102
const loading = ref(false);
@@ -123,7 +129,7 @@
123129
}
124130
125131
setTimeout(() => {
126-
handleInputFocus();
132+
inputRef.value.focus();
127133
});
128134
}
129135
},
@@ -133,24 +139,29 @@
133139
);
134140
135141
const handleInputFocus = () => {
136-
inputRef.value.focus();
142+
if (isMouseMoving.value) {
143+
isMouseMoving.value = false;
144+
return;
145+
}
146+
setTimeout(() => {
147+
checkCursorPosition();
148+
inputRef.value.focus();
149+
});
137150
};
138151
139152
// 回车输入指令
140153
const handleClickSendCommand = async (e: any) => {
141154
// 输入预处理
142-
const inputValue = e.target.value?.trim() as string;
155+
const inputValue = e.target.value.trim() as string;
143156
const isInputed = inputValue.length > localPlaceholder.value.length;
144157
145158
// 截取输入的命令
146159
const cmd = inputValue.substring(localPlaceholder.value.length);
147-
// 是否拦截请求
160+
161+
// 拦截
148162
if (props.intercept(cmd)) {
149163
return;
150164
}
151-
executedCommands[clusterId.value].push(cmd);
152-
commandIndex = executedCommands[clusterId.value].length;
153-
command.value = localPlaceholder.value;
154165
155166
// 命令行渲染
156167
const commandLine = {
@@ -159,7 +170,8 @@
159170
};
160171
panelInputMap[clusterId.value].push(commandLine);
161172
162-
if (!isInputed) {
173+
if (!isInputed || loading.value) {
174+
command.value = '';
163175
return;
164176
}
165177
@@ -203,6 +215,9 @@
203215
}
204216
} finally {
205217
loading.value = false;
218+
executedCommands[clusterId.value].push(cmd);
219+
commandIndex = executedCommands[clusterId.value].length;
220+
command.value = localPlaceholder.value;
206221
setTimeout(() => {
207222
inputRef.value.focus();
208223
consolePanelRef.value.scrollTop = consolePanelRef.value.scrollHeight - consolePanelRef.value.clientHeight;
@@ -254,8 +269,9 @@
254269
return;
255270
}
256271
272+
const cmd = executedCommands[clusterId.value][commandIndex];
257273
// 是否拦截
258-
if (props.intercept(executedCommands[clusterId.value][commandIndex])) {
274+
if (cmd && props.intercept(cmd)) {
259275
return;
260276
}
261277
@@ -303,6 +319,11 @@
303319
window.removeEventListener('keydown', handleKeyDownEnter);
304320
});
305321
322+
onActivated(() => {
323+
isMouseMoving.value = false;
324+
handleInputFocus();
325+
});
326+
306327
defineExpose<Expose>({
307328
clearCurrentScreen(id?: number) {
308329
const currentClusterId = id ?? clusterId.value;
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
<template>
2-
<div>
3-
<p>Tab 键已被禁用。</p>
4-
</div>
5-
</template>
6-
7-
<script setup lang="ts">
1+
export function useDisableTab() {
82
const disableTabKey = (event: any) => {
93
if (event.key === 'Tab') {
104
event.preventDefault();
@@ -18,4 +12,4 @@
1812
onBeforeUnmount(() => {
1913
window.removeEventListener('keydown', disableTabKey);
2014
});
21-
</script>
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export function useMouseSelect() {
2+
/**
3+
* 触发点击
4+
*/
5+
const isMouseClick = ref(false);
6+
/**
7+
* 是否在拖动中
8+
*/
9+
const isMouseMoving = ref(false);
10+
11+
const handleMouseDown = () => {
12+
isMouseClick.value = true;
13+
};
14+
15+
const handleMouseUp = () => {
16+
isMouseClick.value = false;
17+
};
18+
19+
const handleMouseMove = () => {
20+
if (isMouseClick.value) {
21+
isMouseMoving.value = true;
22+
}
23+
};
24+
25+
onMounted(() => {
26+
window.addEventListener('mousedown', handleMouseDown);
27+
window.addEventListener('mouseup', handleMouseUp);
28+
window.addEventListener('mousemove', handleMouseMove);
29+
});
30+
31+
onBeforeUnmount(() => {
32+
window.removeEventListener('mousedown', handleMouseDown);
33+
window.removeEventListener('mouseup', handleMouseUp);
34+
window.removeEventListener('mousemove', handleMouseMove);
35+
});
36+
37+
return {
38+
isMouseClick,
39+
isMouseMoving,
40+
};
41+
}

0 commit comments

Comments
 (0)