mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	feat: mongo优化
This commit is contained in:
		@@ -10,7 +10,7 @@ RUN yarn
 | 
				
			|||||||
RUN yarn build
 | 
					RUN yarn build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 构建后端资源
 | 
					# 构建后端资源
 | 
				
			||||||
FROM golang:1.20-alpine3.16 as be-builder
 | 
					FROM golang:1.21.0 as be-builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENV GOPROXY https://goproxy.cn
 | 
					ENV GOPROXY https://goproxy.cn
 | 
				
			||||||
WORKDIR /mayfly
 | 
					WORKDIR /mayfly
 | 
				
			||||||
@@ -31,6 +31,9 @@ FROM alpine:3.16
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
RUN apk add --no-cache ca-certificates bash expat
 | 
					RUN apk add --no-cache ca-certificates bash expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENV TZ=Asia/Shanghai
 | 
				
			||||||
 | 
					RUN ln -snf /usr/share/zoneinfo/\$TZ /etc/localtime && echo \$TZ > /etc/timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /mayfly
 | 
					WORKDIR /mayfly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY --from=be-builder /mayfly/mayfly-go /usr/local/bin/mayfly-go
 | 
					COPY --from=be-builder /mayfly/mayfly-go /usr/local/bin/mayfly-go
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +0,0 @@
 | 
				
			|||||||
export enum ResultEnum {
 | 
					 | 
				
			||||||
    SUCCESS = 200,
 | 
					 | 
				
			||||||
    ERROR = 400,
 | 
					 | 
				
			||||||
    PARAM_ERROR = 405,
 | 
					 | 
				
			||||||
    SERVER_ERROR = 500,
 | 
					 | 
				
			||||||
    NO_PERMISSION = 501,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -28,7 +28,7 @@ export function exportCsv(filename: string, columns: string[], datas: []) {
 | 
				
			|||||||
    let link = document.createElement('a');
 | 
					    let link = document.createElement('a');
 | 
				
			||||||
    let exportContent = '\uFEFF';
 | 
					    let exportContent = '\uFEFF';
 | 
				
			||||||
    let blob = new Blob([exportContent + csvString], {
 | 
					    let blob = new Blob([exportContent + csvString], {
 | 
				
			||||||
        type: 'text/plain;charset=utrf-8',
 | 
					        type: 'text/plain;charset=utf-8',
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    link.id = 'download-csv';
 | 
					    link.id = 'download-csv';
 | 
				
			||||||
    link.setAttribute('href', URL.createObjectURL(blob));
 | 
					    link.setAttribute('href', URL.createObjectURL(blob));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,14 +35,44 @@
 | 
				
			|||||||
            </el-col>
 | 
					            </el-col>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <el-col :span="20">
 | 
					            <el-col :span="20">
 | 
				
			||||||
                <el-container id="mongo-tab" style="border: 1px solid #eee; margin-top: 1px">
 | 
					                <div id="mongo-tab" style="border: 1px solid #eee; margin-top: 1px">
 | 
				
			||||||
 | 
					                    <el-row v-if="nowColl">
 | 
				
			||||||
 | 
					                        <el-descriptions :column="10" size="small" border>
 | 
				
			||||||
 | 
					                            <!-- <el-descriptions-item label-align="right" label="tag">xxx</el-descriptions-item> -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="ns" label-align="right">
 | 
				
			||||||
 | 
					                                {{ nowColl.stats.ns }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="count" label-align="right">
 | 
				
			||||||
 | 
					                                {{ nowColl.stats.count }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="avgObjSize" label-align="right">
 | 
				
			||||||
 | 
					                                {{ formatByteSize(nowColl.stats.avgObjSize) }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="size" label-align="right">
 | 
				
			||||||
 | 
					                                {{ formatByteSize(nowColl.stats.size) }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="totalSize" label-align="right">
 | 
				
			||||||
 | 
					                                {{ formatByteSize(nowColl.stats.totalSize) }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="storageSize" label-align="right">
 | 
				
			||||||
 | 
					                                {{ formatByteSize(nowColl.stats.storageSize) }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                            <el-descriptions-item label="freeStorageSize" label-align="right">
 | 
				
			||||||
 | 
					                                {{ formatByteSize(nowColl.stats.freeStorageSize) }}
 | 
				
			||||||
 | 
					                            </el-descriptions-item>
 | 
				
			||||||
 | 
					                        </el-descriptions>
 | 
				
			||||||
 | 
					                    </el-row>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <el-row type="flex">
 | 
				
			||||||
                        <el-tabs @tab-remove="removeDataTab" style="width: 100%; margin-left: 5px" v-model="state.activeName">
 | 
					                        <el-tabs @tab-remove="removeDataTab" style="width: 100%; margin-left: 5px" v-model="state.activeName">
 | 
				
			||||||
                            <el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
 | 
					                            <el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
 | 
				
			||||||
                                <el-row>
 | 
					                                <el-row>
 | 
				
			||||||
                                    <el-col :span="2">
 | 
					                                    <el-col :span="2">
 | 
				
			||||||
                                    <div>
 | 
					                                        <div class="mt5">
 | 
				
			||||||
                                            <el-link @click="findCommand(state.activeName)" icon="refresh" :underline="false" class=""> </el-link>
 | 
					                                            <el-link @click="findCommand(state.activeName)" icon="refresh" :underline="false" class=""> </el-link>
 | 
				
			||||||
                                        <el-link @click="onEditDoc(null)" class="ml5" type="primary" icon="plus" :underline="false"> </el-link>
 | 
					                                            <el-divider direction="vertical" border-style="dashed" />
 | 
				
			||||||
 | 
					                                            <el-link v-auth="perms.saveData" @click="onEditDoc(null)" type="primary" icon="plus" :underline="false"> </el-link>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
                                    </el-col>
 | 
					                                    </el-col>
 | 
				
			||||||
                                    <el-col :span="22">
 | 
					                                    <el-col :span="22">
 | 
				
			||||||
@@ -64,16 +94,11 @@
 | 
				
			|||||||
                                                <div>
 | 
					                                                <div>
 | 
				
			||||||
                                                    <el-link @click="onEditDoc(item)" :underline="false" type="success" icon="MagicStick"></el-link>
 | 
					                                                    <el-link @click="onEditDoc(item)" :underline="false" type="success" icon="MagicStick"></el-link>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                                <!-- <el-divider direction="vertical" border-style="dashed" /> -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                                <!-- <el-link @click="onSaveDoc(item.value)" :underline="false"
 | 
					 | 
				
			||||||
                                                    type="warning" icon="DocumentChecked"></el-link> -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                                    <el-divider direction="vertical" border-style="dashed" />
 | 
					                                                    <el-divider direction="vertical" border-style="dashed" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                                <el-popconfirm @confirm="onDeleteDoc(item.value)" title="确定删除该文档?">
 | 
					                                                    <el-popconfirm @confirm="onDeleteDoc(item.value)" title="确定删除该文档?" width="160">
 | 
				
			||||||
                                                        <template #reference>
 | 
					                                                        <template #reference>
 | 
				
			||||||
                                                        <el-link :underline="false" type="danger" icon="DocumentDelete"> </el-link>
 | 
					                                                            <el-link v-auth="perms.delData" :underline="false" type="danger" icon="DocumentDelete"> </el-link>
 | 
				
			||||||
                                                        </template>
 | 
					                                                        </template>
 | 
				
			||||||
                                                    </el-popconfirm>
 | 
					                                                    </el-popconfirm>
 | 
				
			||||||
                                                </div>
 | 
					                                                </div>
 | 
				
			||||||
@@ -83,7 +108,8 @@
 | 
				
			|||||||
                                </el-row>
 | 
					                                </el-row>
 | 
				
			||||||
                            </el-tab-pane>
 | 
					                            </el-tab-pane>
 | 
				
			||||||
                        </el-tabs>
 | 
					                        </el-tabs>
 | 
				
			||||||
                </el-container>
 | 
					                    </el-row>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
            </el-col>
 | 
					            </el-col>
 | 
				
			||||||
        </el-row>
 | 
					        </el-row>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -120,7 +146,7 @@
 | 
				
			|||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
                    <el-button @click="docEditDialog.visible = false">取 消</el-button>
 | 
					                    <el-button @click="docEditDialog.visible = false">取 消</el-button>
 | 
				
			||||||
                    <el-button @click="onSaveDoc" type="primary">确 定</el-button>
 | 
					                    <el-button v-auth="perms.saveData" @click="onSaveDoc" type="primary">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -131,7 +157,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { mongoApi } from './api';
 | 
					import { mongoApi } from './api';
 | 
				
			||||||
import { defineAsyncComponent, reactive, ref, toRefs } from 'vue';
 | 
					import { computed, defineAsyncComponent, reactive, ref, toRefs } from 'vue';
 | 
				
			||||||
import { ElMessage } from 'element-plus';
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { isTrue, notBlank } from '@/common/assert';
 | 
					import { isTrue, notBlank } from '@/common/assert';
 | 
				
			||||||
@@ -141,6 +167,11 @@ import { formatByteSize } from '@/common/utils/format';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const MonacoEditor = defineAsyncComponent(() => import('@/components/monaco/MonacoEditor.vue'));
 | 
					const MonacoEditor = defineAsyncComponent(() => import('@/components/monaco/MonacoEditor.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const perms = {
 | 
				
			||||||
 | 
					    saveData: 'mongo:data:save',
 | 
				
			||||||
 | 
					    delData: 'mongo:data:del',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 树节点类型
 | 
					 * 树节点类型
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -154,7 +185,7 @@ class NodeType {
 | 
				
			|||||||
const findParamInputRef: any = ref(null);
 | 
					const findParamInputRef: any = ref(null);
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    tags: [],
 | 
					    tags: [],
 | 
				
			||||||
    dataHeight: `${window.innerHeight - 194}px`,
 | 
					    dataHeight: `${window.innerHeight - 194 - 35}px`,
 | 
				
			||||||
    mongoList: [] as any,
 | 
					    mongoList: [] as any,
 | 
				
			||||||
    activeName: '', // 当前操作的tab
 | 
					    activeName: '', // 当前操作的tab
 | 
				
			||||||
    dataTabs: {} as any, // 数据tabs
 | 
					    dataTabs: {} as any, // 数据tabs
 | 
				
			||||||
@@ -185,6 +216,10 @@ const state = reactive({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const { dataHeight, findDialog, docEditDialog } = toRefs(state);
 | 
					const { dataHeight, findDialog, docEditDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const nowColl = computed(() => {
 | 
				
			||||||
 | 
					    return getNowDataTab();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * instmap;  tagPaht -> mongo info[]
 | 
					 * instmap;  tagPaht -> mongo info[]
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -279,15 +314,15 @@ const getCollections = async (id: any, database: string) => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const nodeClick = (data: any) => {
 | 
					const nodeClick = async (data: any) => {
 | 
				
			||||||
    // 点击集合
 | 
					    // 点击集合
 | 
				
			||||||
    if (data.type === NodeType.Coll) {
 | 
					    if (data.type === NodeType.Coll) {
 | 
				
			||||||
        const { id, database, collection } = data.params;
 | 
					        const { id, database, collection } = data.params;
 | 
				
			||||||
        changeCollection(id, database, collection);
 | 
					        await changeCollection(id, database, collection);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const changeCollection = (id: any, schema: string, collection: string) => {
 | 
					const changeCollection = async (id: any, schema: string, collection: string) => {
 | 
				
			||||||
    const label = `${id}:\`${schema}\`.${collection}`;
 | 
					    const label = `${id}:\`${schema}\`.${collection}`;
 | 
				
			||||||
    let dataTab = state.dataTabs[label];
 | 
					    let dataTab = state.dataTabs[label];
 | 
				
			||||||
    if (!dataTab) {
 | 
					    if (!dataTab) {
 | 
				
			||||||
@@ -345,6 +380,7 @@ const findCommand = async (key: string) => {
 | 
				
			|||||||
        ElMessage.error('filter或sort字段json字符串值错误。注意: json key需双引号');
 | 
					        ElMessage.error('filter或sort字段json字符串值错误。注意: json key需双引号');
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const datas = await mongoApi.findCommand.request({
 | 
					    const datas = await mongoApi.findCommand.request({
 | 
				
			||||||
        id: dataTab.mongoId,
 | 
					        id: dataTab.mongoId,
 | 
				
			||||||
        database: dataTab.database,
 | 
					        database: dataTab.database,
 | 
				
			||||||
@@ -355,6 +391,17 @@ const findCommand = async (key: string) => {
 | 
				
			|||||||
        skip: findParma.skip || 0,
 | 
					        skip: findParma.skip || 0,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    state.dataTabs[key].datas = wrapDatas(datas);
 | 
					    state.dataTabs[key].datas = wrapDatas(datas);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 获取coll stats
 | 
				
			||||||
 | 
					    state.dataTabs[key].stats = await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: dataTab.mongoId,
 | 
				
			||||||
 | 
					        database: dataTab.database,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                collStats: dataTab.collection,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										352
									
								
								mayfly_go_web/src/views/ops/mongo/MongoDbs.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								mayfly_go_web/src/views/ops/mongo/MongoDbs.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,352 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					        <el-dialog width="800px" title="数据库列表" :before-close="close" v-model="databaseDialog.visible">
 | 
				
			||||||
 | 
					            <div class="mb5">
 | 
				
			||||||
 | 
					                <el-button @click="showCreateDbDialog" type="primary" icon="plus" size="small">新建</el-button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <el-table :data="databaseDialog.data" :max-height="500">
 | 
				
			||||||
 | 
					                <el-table-column min-width="130" property="Name" label="库名" />
 | 
				
			||||||
 | 
					                <el-table-column min-width="90" property="SizeOnDisk" label="size">
 | 
				
			||||||
 | 
					                    <template #default="scope">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(scope.row.SizeOnDisk) }}
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                </el-table-column>
 | 
				
			||||||
 | 
					                <el-table-column min-width="80" property="Empty" label="是否为空" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <el-table-column min-width="150" label="操作">
 | 
				
			||||||
 | 
					                    <template #default="scope">
 | 
				
			||||||
 | 
					                        <el-link type="success" @click="showDatabaseStats(scope.row.Name)" plain size="small" :underline="false">stats</el-link>
 | 
				
			||||||
 | 
					                        <el-divider direction="vertical" border-style="dashed" />
 | 
				
			||||||
 | 
					                        <el-link type="primary" @click="showCollections(scope.row.Name)" plain size="small" :underline="false">集合</el-link>
 | 
				
			||||||
 | 
					                        <el-divider direction="vertical" border-style="dashed" />
 | 
				
			||||||
 | 
					                        <el-popconfirm @confirm="onDeleteDb(scope.row.Name)" title="确定删除该库?">
 | 
				
			||||||
 | 
					                            <template #reference>
 | 
				
			||||||
 | 
					                                <el-link type="danger" plain size="small" :underline="false">删除</el-link>
 | 
				
			||||||
 | 
					                            </template>
 | 
				
			||||||
 | 
					                        </el-popconfirm>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                </el-table-column>
 | 
				
			||||||
 | 
					            </el-table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <el-dialog width="700px" :title="databaseDialog.statsDialog.title" v-model="databaseDialog.statsDialog.visible">
 | 
				
			||||||
 | 
					                <el-descriptions title="库状态信息" :column="3" border>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="db" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ databaseDialog.statsDialog.data.db }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="collections" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ databaseDialog.statsDialog.data.collections }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="objects" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ databaseDialog.statsDialog.data.objects }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="indexes" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ databaseDialog.statsDialog.data.indexes }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="avgObjSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.avgObjSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="dataSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.dataSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="totalSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.totalSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="storageSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.storageSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="fsTotalSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.fsTotalSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="fsUsedSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.fsUsedSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="indexSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(databaseDialog.statsDialog.data.indexSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                </el-descriptions>
 | 
				
			||||||
 | 
					            </el-dialog>
 | 
				
			||||||
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <el-dialog width="600px" :title="collectionsDialog.title" v-model="collectionsDialog.visible">
 | 
				
			||||||
 | 
					            <div class="mb5">
 | 
				
			||||||
 | 
					                <el-button @click="showCreateCollectionDialog" type="primary" icon="plus" size="small">新建</el-button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <el-table stripe :data="collectionsDialog.data" :max-height="500">
 | 
				
			||||||
 | 
					                <el-table-column prop="name" label="名称" show-overflow-tooltip> </el-table-column>
 | 
				
			||||||
 | 
					                <el-table-column min-width="80" label="操作">
 | 
				
			||||||
 | 
					                    <template #default="scope">
 | 
				
			||||||
 | 
					                        <el-link type="success" @click="showCollectionStats(scope.row.name)" plain size="small" :underline="false">stats</el-link>
 | 
				
			||||||
 | 
					                        <el-divider direction="vertical" border-style="dashed" />
 | 
				
			||||||
 | 
					                        <el-popconfirm @confirm="onDeleteCollection(scope.row.name)" width="160" title="确定删除该集合?">
 | 
				
			||||||
 | 
					                            <template #reference>
 | 
				
			||||||
 | 
					                                <el-link type="danger" plain size="small" :underline="false">删除</el-link>
 | 
				
			||||||
 | 
					                            </template>
 | 
				
			||||||
 | 
					                        </el-popconfirm>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                </el-table-column>
 | 
				
			||||||
 | 
					            </el-table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <el-dialog width="700px" :title="collectionsDialog.statsDialog.title" v-model="collectionsDialog.statsDialog.visible">
 | 
				
			||||||
 | 
					                <el-descriptions title="集合状态信息" :column="3" border>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="ns" label-align="right" :span="2" align="center">
 | 
				
			||||||
 | 
					                        {{ collectionsDialog.statsDialog.data.ns }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="count" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ collectionsDialog.statsDialog.data.count }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="avgObjSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(collectionsDialog.statsDialog.data.avgObjSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="nindexes" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ collectionsDialog.statsDialog.data.nindexes }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="size" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(collectionsDialog.statsDialog.data.size) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="totalSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(collectionsDialog.statsDialog.data.totalSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="storageSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(collectionsDialog.statsDialog.data.storageSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                    <el-descriptions-item label="freeStorageSize" label-align="right" align="center">
 | 
				
			||||||
 | 
					                        {{ formatByteSize(collectionsDialog.statsDialog.data.freeStorageSize) }}
 | 
				
			||||||
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					                </el-descriptions>
 | 
				
			||||||
 | 
					            </el-dialog>
 | 
				
			||||||
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <el-dialog width="400px" title="新建库&集合" v-model="createDbDialog.visible" :destroy-on-close="true">
 | 
				
			||||||
 | 
					            <el-form :model="createDbDialog.form" label-width="auto">
 | 
				
			||||||
 | 
					                <el-form-item prop="dbName" label="库名" required>
 | 
				
			||||||
 | 
					                    <el-input v-model="createDbDialog.form.dbName" clearable></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					                <el-form-item prop="collectionName" label="集合名" required>
 | 
				
			||||||
 | 
					                    <el-input v-model="createDbDialog.form.collectionName" clearable></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					            </el-form>
 | 
				
			||||||
 | 
					            <template #footer>
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    <el-button @click="createDbDialog.visible = false">取 消</el-button>
 | 
				
			||||||
 | 
					                    <el-button @click="onCreateDb" type="primary">确 定</el-button>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <el-dialog width="400px" title="新建集合" v-model="createCollectionDialog.visible" :destroy-on-close="true">
 | 
				
			||||||
 | 
					            <el-form :model="createCollectionDialog.form" label-width="auto">
 | 
				
			||||||
 | 
					                <el-form-item prop="name" label="集合名" required>
 | 
				
			||||||
 | 
					                    <el-input v-model="createCollectionDialog.form.name" clearable></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					            </el-form>
 | 
				
			||||||
 | 
					            <template #footer>
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    <el-button @click="createCollectionDialog.visible = false">取 消</el-button>
 | 
				
			||||||
 | 
					                    <el-button @click="onCreateCollection" type="primary">确 定</el-button>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import { mongoApi } from './api';
 | 
				
			||||||
 | 
					import { watch, toRefs, reactive } from 'vue';
 | 
				
			||||||
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
 | 
					import { formatByteSize } from '@/common/utils/format';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
					    visible: {
 | 
				
			||||||
 | 
					        type: Boolean,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    id: {
 | 
				
			||||||
 | 
					        type: [Number],
 | 
				
			||||||
 | 
					        required: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//定义事件
 | 
				
			||||||
 | 
					const emit = defineEmits(['update:visible']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const state = reactive({
 | 
				
			||||||
 | 
					    databaseDialog: {
 | 
				
			||||||
 | 
					        visible: false,
 | 
				
			||||||
 | 
					        data: [],
 | 
				
			||||||
 | 
					        statsDialog: {
 | 
				
			||||||
 | 
					            visible: false,
 | 
				
			||||||
 | 
					            data: {} as any,
 | 
				
			||||||
 | 
					            title: '',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    collectionsDialog: {
 | 
				
			||||||
 | 
					        database: '',
 | 
				
			||||||
 | 
					        visible: false,
 | 
				
			||||||
 | 
					        data: [],
 | 
				
			||||||
 | 
					        title: '',
 | 
				
			||||||
 | 
					        statsDialog: {
 | 
				
			||||||
 | 
					            visible: false,
 | 
				
			||||||
 | 
					            data: {} as any,
 | 
				
			||||||
 | 
					            title: '',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    createCollectionDialog: {
 | 
				
			||||||
 | 
					        visible: false,
 | 
				
			||||||
 | 
					        form: {
 | 
				
			||||||
 | 
					            name: '',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    createDbDialog: {
 | 
				
			||||||
 | 
					        visible: false,
 | 
				
			||||||
 | 
					        form: {
 | 
				
			||||||
 | 
					            dbName: '',
 | 
				
			||||||
 | 
					            collectionName: '',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { databaseDialog, collectionsDialog, createCollectionDialog, createDbDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(props, async (newValue: any) => {
 | 
				
			||||||
 | 
					    if (!newValue.visible) {
 | 
				
			||||||
 | 
					        state.databaseDialog.visible = false;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    showDatabases();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const close = () => {
 | 
				
			||||||
 | 
					    emit('update:visible', false);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const showDatabases = async () => {
 | 
				
			||||||
 | 
					    state.databaseDialog.data = (await mongoApi.databases.request({ id: props.id })).Databases;
 | 
				
			||||||
 | 
					    state.databaseDialog.visible = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const showDatabaseStats = async (dbName: string) => {
 | 
				
			||||||
 | 
					    state.databaseDialog.statsDialog.data = await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: dbName,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                dbStats: 1,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    state.databaseDialog.statsDialog.title = `'${dbName}' stats`;
 | 
				
			||||||
 | 
					    state.databaseDialog.statsDialog.visible = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const showCollections = async (database: string) => {
 | 
				
			||||||
 | 
					    state.collectionsDialog.database = database;
 | 
				
			||||||
 | 
					    state.collectionsDialog.data = [];
 | 
				
			||||||
 | 
					    setCollections(database);
 | 
				
			||||||
 | 
					    state.collectionsDialog.title = `'${database}' 集合`;
 | 
				
			||||||
 | 
					    state.collectionsDialog.visible = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const setCollections = async (database: string) => {
 | 
				
			||||||
 | 
					    const res = await mongoApi.collections.request({ id: props.id, database });
 | 
				
			||||||
 | 
					    const collections = [] as any;
 | 
				
			||||||
 | 
					    for (let r of res) {
 | 
				
			||||||
 | 
					        collections.push({ name: r });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    state.collectionsDialog.data = collections;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 显示集合状态
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const showCollectionStats = async (collection: string) => {
 | 
				
			||||||
 | 
					    state.collectionsDialog.statsDialog.data = await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: state.collectionsDialog.database,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                collStats: collection,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    state.collectionsDialog.statsDialog.title = `'${collection}' stats`;
 | 
				
			||||||
 | 
					    state.collectionsDialog.statsDialog.visible = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 删除集合
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const onDeleteCollection = async (collection: string) => {
 | 
				
			||||||
 | 
					    await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: state.collectionsDialog.database,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                drop: collection,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    ElMessage.success('集合删除成功');
 | 
				
			||||||
 | 
					    setCollections(state.collectionsDialog.database);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const showCreateCollectionDialog = () => {
 | 
				
			||||||
 | 
					    state.createCollectionDialog.visible = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onCreateCollection = async () => {
 | 
				
			||||||
 | 
					    const form = state.createCollectionDialog.form;
 | 
				
			||||||
 | 
					    await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: state.collectionsDialog.database,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                create: form.name,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    ElMessage.success('集合创建成功');
 | 
				
			||||||
 | 
					    state.createCollectionDialog.visible = false;
 | 
				
			||||||
 | 
					    state.createCollectionDialog.form = {} as any;
 | 
				
			||||||
 | 
					    setCollections(state.collectionsDialog.database);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const showCreateDbDialog = () => {
 | 
				
			||||||
 | 
					    state.createDbDialog.visible = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onCreateDb = async () => {
 | 
				
			||||||
 | 
					    const form = state.createDbDialog.form;
 | 
				
			||||||
 | 
					    await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: form.dbName,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                create: form.collectionName,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    ElMessage.success('数据库与集合创建成功');
 | 
				
			||||||
 | 
					    state.createDbDialog.visible = false;
 | 
				
			||||||
 | 
					    state.createDbDialog.form = {} as any;
 | 
				
			||||||
 | 
					    showDatabases();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onDeleteDb = async (db: string) => {
 | 
				
			||||||
 | 
					    await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: db,
 | 
				
			||||||
 | 
					        command: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                dropDatabase: 1,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    ElMessage.success('库删除成功');
 | 
				
			||||||
 | 
					    showDatabases();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style></style>
 | 
				
			||||||
@@ -34,136 +34,15 @@
 | 
				
			|||||||
            <template #action="{ data }">
 | 
					            <template #action="{ data }">
 | 
				
			||||||
                <el-button @click="showDatabases(data.id)" link>数据库</el-button>
 | 
					                <el-button @click="showDatabases(data.id)" link>数据库</el-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <el-button type="primary" @click="editMongo(data)" link>编辑</el-button>
 | 
					                <el-button @click="showUsers(data.id)" link type="success">cmd</el-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <el-button @click="editMongo(data)" link type="primary">编辑</el-button>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </page-table>
 | 
					        </page-table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <el-dialog width="800px" :title="databaseDialog.title" v-model="databaseDialog.visible">
 | 
					        <mongo-dbs v-model:visible="dbsVisible" :id="state.dbOps.dbId"></mongo-dbs>
 | 
				
			||||||
            <el-table :data="databaseDialog.data" size="small">
 | 
					 | 
				
			||||||
                <el-table-column min-width="130" property="Name" label="库名" />
 | 
					 | 
				
			||||||
                <el-table-column min-width="90" property="SizeOnDisk" label="size">
 | 
					 | 
				
			||||||
                    <template #default="scope">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(scope.row.SizeOnDisk) }}
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                </el-table-column>
 | 
					 | 
				
			||||||
                <el-table-column min-width="80" property="Empty" label="是否为空" />
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <el-table-column min-width="150" label="操作">
 | 
					        <mongo-run-command v-model:visible="usersVisible" :id="state.dbOps.dbId" />
 | 
				
			||||||
                    <template #default="scope">
 | 
					 | 
				
			||||||
                        <el-link type="success" @click="showDatabaseStats(scope.row.Name)" plain size="small" :underline="false">stats</el-link>
 | 
					 | 
				
			||||||
                        <el-divider direction="vertical" border-style="dashed" />
 | 
					 | 
				
			||||||
                        <el-link type="primary" @click="showCollections(scope.row.Name)" plain size="small" :underline="false">集合</el-link>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                </el-table-column>
 | 
					 | 
				
			||||||
            </el-table>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <el-dialog width="700px" :title="databaseDialog.statsDialog.title" v-model="databaseDialog.statsDialog.visible">
 | 
					 | 
				
			||||||
                <el-descriptions title="库状态信息" :column="3" border size="small">
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="db" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ databaseDialog.statsDialog.data.db }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="collections" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ databaseDialog.statsDialog.data.collections }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="objects" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ databaseDialog.statsDialog.data.objects }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="indexes" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ databaseDialog.statsDialog.data.indexes }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="avgObjSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.avgObjSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="dataSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.dataSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="totalSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.totalSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="storageSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.storageSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="fsTotalSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.fsTotalSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="fsUsedSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.fsUsedSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="indexSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(databaseDialog.statsDialog.data.indexSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                </el-descriptions>
 | 
					 | 
				
			||||||
            </el-dialog>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <el-dialog width="600px" :title="collectionsDialog.title" v-model="collectionsDialog.visible">
 | 
					 | 
				
			||||||
            <div>
 | 
					 | 
				
			||||||
                <el-button @click="showCreateCollectionDialog" type="primary" icon="plus" size="small">新建</el-button>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <el-table border stripe :data="collectionsDialog.data" size="small">
 | 
					 | 
				
			||||||
                <el-table-column prop="name" label="名称" show-overflow-tooltip> </el-table-column>
 | 
					 | 
				
			||||||
                <el-table-column min-width="80" label="操作">
 | 
					 | 
				
			||||||
                    <template #default="scope">
 | 
					 | 
				
			||||||
                        <el-link type="success" @click="showCollectionStats(scope.row.name)" plain size="small" :underline="false">stats</el-link>
 | 
					 | 
				
			||||||
                        <el-divider direction="vertical" border-style="dashed" />
 | 
					 | 
				
			||||||
                        <el-popconfirm @confirm="onDeleteCollection(scope.row.name)" title="确定删除该集合?">
 | 
					 | 
				
			||||||
                            <template #reference>
 | 
					 | 
				
			||||||
                                <el-link type="danger" plain size="small" :underline="false">删除</el-link>
 | 
					 | 
				
			||||||
                            </template>
 | 
					 | 
				
			||||||
                        </el-popconfirm>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                </el-table-column>
 | 
					 | 
				
			||||||
            </el-table>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <el-dialog width="700px" :title="collectionsDialog.statsDialog.title" v-model="collectionsDialog.statsDialog.visible">
 | 
					 | 
				
			||||||
                <el-descriptions title="集合状态信息" :column="3" border size="small">
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="ns" label-align="right" :span="2" align="center">
 | 
					 | 
				
			||||||
                        {{ collectionsDialog.statsDialog.data.ns }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="count" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ collectionsDialog.statsDialog.data.count }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="avgObjSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(collectionsDialog.statsDialog.data.avgObjSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="nindexes" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ collectionsDialog.statsDialog.data.nindexes }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="size" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(collectionsDialog.statsDialog.data.size) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="totalSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(collectionsDialog.statsDialog.data.totalSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="storageSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(collectionsDialog.statsDialog.data.storageSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                    <el-descriptions-item label="freeStorageSize" label-align="right" align="center">
 | 
					 | 
				
			||||||
                        {{ formatByteSize(collectionsDialog.statsDialog.data.freeStorageSize) }}
 | 
					 | 
				
			||||||
                    </el-descriptions-item>
 | 
					 | 
				
			||||||
                </el-descriptions>
 | 
					 | 
				
			||||||
            </el-dialog>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <el-dialog width="400px" title="新建集合" v-model="createCollectionDialog.visible" :destroy-on-close="true">
 | 
					 | 
				
			||||||
            <el-form :model="createCollectionDialog.form" label-width="auto">
 | 
					 | 
				
			||||||
                <el-form-item prop="name" label="集合名" required>
 | 
					 | 
				
			||||||
                    <el-input v-model="createCollectionDialog.form.name" clearable></el-input>
 | 
					 | 
				
			||||||
                </el-form-item>
 | 
					 | 
				
			||||||
                <!-- <el-form-item label="描述:">
 | 
					 | 
				
			||||||
                    <el-input v-model="showEnvDialog.envForm.remark" auto-complete="off"></el-input>
 | 
					 | 
				
			||||||
                </el-form-item> -->
 | 
					 | 
				
			||||||
            </el-form>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-button @click="createCollectionDialog.visible = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button @click="onCreateCollection" type="primary">确 定</el-button>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <mongo-edit
 | 
					        <mongo-edit
 | 
				
			||||||
            @val-change="valChange"
 | 
					            @val-change="valChange"
 | 
				
			||||||
@@ -176,14 +55,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { mongoApi } from './api';
 | 
					import { mongoApi } from './api';
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { defineAsyncComponent, ref, toRefs, reactive, onMounted } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import MongoEdit from './MongoEdit.vue';
 | 
					 | 
				
			||||||
import { formatByteSize } from '@/common/utils/format';
 | 
					 | 
				
			||||||
import TagInfo from '../component/TagInfo.vue';
 | 
					import TagInfo from '../component/TagInfo.vue';
 | 
				
			||||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
					import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			||||||
import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
					import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MongoEdit = defineAsyncComponent(() => import('./MongoEdit.vue'));
 | 
				
			||||||
 | 
					const MongoDbs = defineAsyncComponent(() => import('./MongoDbs.vue'));
 | 
				
			||||||
 | 
					const MongoRunCommand = defineAsyncComponent(() => import('./MongoRunCommand.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					const pageTableRef: any = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect')];
 | 
					const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect')];
 | 
				
			||||||
@@ -193,7 +74,7 @@ const columns = ref([
 | 
				
			|||||||
    TableColumn.new('uri', '连接uri'),
 | 
					    TableColumn.new('uri', '连接uri'),
 | 
				
			||||||
    TableColumn.new('createTime', '创建时间').isTime(),
 | 
					    TableColumn.new('createTime', '创建时间').isTime(),
 | 
				
			||||||
    TableColumn.new('creator', '创建人'),
 | 
					    TableColumn.new('creator', '创建人'),
 | 
				
			||||||
    TableColumn.new('action', '操作').isSlot().setMinWidth(100).fixedRight().alignCenter(),
 | 
					    TableColumn.new('action', '操作').isSlot().setMinWidth(145).fixedRight().alignCenter(),
 | 
				
			||||||
]);
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
@@ -215,126 +96,24 @@ const state = reactive({
 | 
				
			|||||||
        data: null as any,
 | 
					        data: null as any,
 | 
				
			||||||
        title: '新增mongo',
 | 
					        title: '新增mongo',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    databaseDialog: {
 | 
					    dbsVisible: false,
 | 
				
			||||||
        visible: false,
 | 
					    usersVisible: false,
 | 
				
			||||||
        data: [],
 | 
					 | 
				
			||||||
        title: '',
 | 
					 | 
				
			||||||
        statsDialog: {
 | 
					 | 
				
			||||||
            visible: false,
 | 
					 | 
				
			||||||
            data: {} as any,
 | 
					 | 
				
			||||||
            title: '',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    collectionsDialog: {
 | 
					 | 
				
			||||||
        database: '',
 | 
					 | 
				
			||||||
        visible: false,
 | 
					 | 
				
			||||||
        data: [],
 | 
					 | 
				
			||||||
        title: '',
 | 
					 | 
				
			||||||
        statsDialog: {
 | 
					 | 
				
			||||||
            visible: false,
 | 
					 | 
				
			||||||
            data: {} as any,
 | 
					 | 
				
			||||||
            title: '',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    createCollectionDialog: {
 | 
					 | 
				
			||||||
        visible: false,
 | 
					 | 
				
			||||||
        form: {
 | 
					 | 
				
			||||||
            name: '',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { tags, list, total, selectionData, query, mongoEditDialog, databaseDialog, collectionsDialog, createCollectionDialog } = toRefs(state);
 | 
					const { tags, list, total, selectionData, query, mongoEditDialog, dbsVisible, usersVisible } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    search();
 | 
					    search();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showDatabases = async (id: number) => {
 | 
					const showDatabases = async (id: number) => {
 | 
				
			||||||
    // state.query.tagPath = row.tagPath
 | 
					 | 
				
			||||||
    state.dbOps.dbId = id;
 | 
					    state.dbOps.dbId = id;
 | 
				
			||||||
 | 
					    state.dbsVisible = true;
 | 
				
			||||||
    state.databaseDialog.data = (await mongoApi.databases.request({ id })).Databases;
 | 
					 | 
				
			||||||
    state.databaseDialog.title = `数据库列表`;
 | 
					 | 
				
			||||||
    state.databaseDialog.visible = true;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showDatabaseStats = async (dbName: string) => {
 | 
					const showUsers = async (id: number) => {
 | 
				
			||||||
    state.databaseDialog.statsDialog.data = await mongoApi.runCommand.request({
 | 
					    state.dbOps.dbId = id;
 | 
				
			||||||
        id: state.dbOps.dbId,
 | 
					    state.usersVisible = true;
 | 
				
			||||||
        database: dbName,
 | 
					 | 
				
			||||||
        command: {
 | 
					 | 
				
			||||||
            dbStats: 1,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    state.databaseDialog.statsDialog.title = `'${dbName}' stats`;
 | 
					 | 
				
			||||||
    state.databaseDialog.statsDialog.visible = true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const showCollections = async (database: string) => {
 | 
					 | 
				
			||||||
    state.collectionsDialog.database = database;
 | 
					 | 
				
			||||||
    state.collectionsDialog.data = [];
 | 
					 | 
				
			||||||
    setCollections(database);
 | 
					 | 
				
			||||||
    state.collectionsDialog.title = `'${database}' 集合`;
 | 
					 | 
				
			||||||
    state.collectionsDialog.visible = true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const setCollections = async (database: string) => {
 | 
					 | 
				
			||||||
    const res = await mongoApi.collections.request({ id: state.dbOps.dbId, database });
 | 
					 | 
				
			||||||
    const collections = [] as any;
 | 
					 | 
				
			||||||
    for (let r of res) {
 | 
					 | 
				
			||||||
        collections.push({ name: r });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    state.collectionsDialog.data = collections;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 显示集合状态
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const showCollectionStats = async (collection: string) => {
 | 
					 | 
				
			||||||
    state.collectionsDialog.statsDialog.data = await mongoApi.runCommand.request({
 | 
					 | 
				
			||||||
        id: state.dbOps.dbId,
 | 
					 | 
				
			||||||
        database: state.collectionsDialog.database,
 | 
					 | 
				
			||||||
        command: {
 | 
					 | 
				
			||||||
            collStats: collection,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    state.collectionsDialog.statsDialog.title = `'${collection}' stats`;
 | 
					 | 
				
			||||||
    state.collectionsDialog.statsDialog.visible = true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 删除集合
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const onDeleteCollection = async (collection: string) => {
 | 
					 | 
				
			||||||
    await mongoApi.runCommand.request({
 | 
					 | 
				
			||||||
        id: state.dbOps.dbId,
 | 
					 | 
				
			||||||
        database: state.collectionsDialog.database,
 | 
					 | 
				
			||||||
        command: {
 | 
					 | 
				
			||||||
            drop: collection,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    ElMessage.success('集合删除成功');
 | 
					 | 
				
			||||||
    setCollections(state.collectionsDialog.database);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const showCreateCollectionDialog = () => {
 | 
					 | 
				
			||||||
    state.createCollectionDialog.visible = true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const onCreateCollection = async () => {
 | 
					 | 
				
			||||||
    const form = state.createCollectionDialog.form;
 | 
					 | 
				
			||||||
    await mongoApi.runCommand.request({
 | 
					 | 
				
			||||||
        id: state.dbOps.dbId,
 | 
					 | 
				
			||||||
        database: state.collectionsDialog.database,
 | 
					 | 
				
			||||||
        command: {
 | 
					 | 
				
			||||||
            create: form.name,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    ElMessage.success('集合创建成功');
 | 
					 | 
				
			||||||
    state.createCollectionDialog.visible = false;
 | 
					 | 
				
			||||||
    state.createCollectionDialog.form = {} as any;
 | 
					 | 
				
			||||||
    setCollections(state.collectionsDialog.database);
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const deleteMongo = async () => {
 | 
					const deleteMongo = async () => {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										196
									
								
								mayfly_go_web/src/views/ops/mongo/MongoRunCommand.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								mayfly_go_web/src/views/ops/mongo/MongoRunCommand.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,196 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					        <el-dialog width="700px" title="runCommand" v-model="runCmdDialog.visible" :before-close="close" :destroy-on-close="true">
 | 
				
			||||||
 | 
					            <el-form label-width="auto">
 | 
				
			||||||
 | 
					                <el-row class="mb10">
 | 
				
			||||||
 | 
					                    <el-col :span="12">
 | 
				
			||||||
 | 
					                        <el-form-item label="模板">
 | 
				
			||||||
 | 
					                            <el-select class="w100" @change="changeCmd" filterable v-model="runCmdDialog.cmdName" placeholder="选择命令模板">
 | 
				
			||||||
 | 
					                                <el-option v-for="item in mongoCmds" :key="item.name" :label="`${item.name} | ${item.description}`" :value="item.name" />
 | 
				
			||||||
 | 
					                            </el-select>
 | 
				
			||||||
 | 
					                        </el-form-item>
 | 
				
			||||||
 | 
					                    </el-col>
 | 
				
			||||||
 | 
					                    <el-col :span="8">
 | 
				
			||||||
 | 
					                        <el-form-item label="库">
 | 
				
			||||||
 | 
					                            <el-select v-model="runCmdDialog.db" filterable placeholder="选择库">
 | 
				
			||||||
 | 
					                                <el-option v-for="item in dbs" :key="item.Name" :label="item.Name" :value="item.Name" />
 | 
				
			||||||
 | 
					                            </el-select>
 | 
				
			||||||
 | 
					                        </el-form-item>
 | 
				
			||||||
 | 
					                    </el-col>
 | 
				
			||||||
 | 
					                    <el-col :span="4">
 | 
				
			||||||
 | 
					                        <el-form-item class="ml10">
 | 
				
			||||||
 | 
					                            <el-button @click="onRunCommand" type="primary">Run</el-button>
 | 
				
			||||||
 | 
					                            <el-tooltip effect="dark" placement="top">
 | 
				
			||||||
 | 
					                                <template #content> 更多命令查看-> https://www.mongodb.com/docs/manual/reference/command/ </template>
 | 
				
			||||||
 | 
					                                <span class="ml10">
 | 
				
			||||||
 | 
					                                    <el-icon><InfoFilled /></el-icon>
 | 
				
			||||||
 | 
					                                </span>
 | 
				
			||||||
 | 
					                            </el-tooltip>
 | 
				
			||||||
 | 
					                        </el-form-item>
 | 
				
			||||||
 | 
					                    </el-col>
 | 
				
			||||||
 | 
					                </el-row>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <el-form-item label="cmd">
 | 
				
			||||||
 | 
					                    <monaco-editor style="width: 100%" height="235px" v-model="runCmdDialog.cmd" language="json" />
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <el-form-item label="res">
 | 
				
			||||||
 | 
					                    <monaco-editor style="width: 100%" height="235px" v-model="runCmdDialog.cmdRes" language="json" />
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					            </el-form>
 | 
				
			||||||
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import { mongoApi } from './api';
 | 
				
			||||||
 | 
					import { watch, defineAsyncComponent, toRefs, reactive } from 'vue';
 | 
				
			||||||
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MonacoEditor = defineAsyncComponent(() => import('@/components/monaco/MonacoEditor.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
					    visible: {
 | 
				
			||||||
 | 
					        type: Boolean,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    id: {
 | 
				
			||||||
 | 
					        type: [Number],
 | 
				
			||||||
 | 
					        required: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//定义事件
 | 
				
			||||||
 | 
					const emit = defineEmits(['update:visible']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mongoCmds = {
 | 
				
			||||||
 | 
					    usersInfo: {
 | 
				
			||||||
 | 
					        name: 'usersInfo',
 | 
				
			||||||
 | 
					        description: '获取用户信息',
 | 
				
			||||||
 | 
					        cmd: {
 | 
				
			||||||
 | 
					            usersInfo: 1,
 | 
				
			||||||
 | 
					            showCredentials: false,
 | 
				
			||||||
 | 
					            showCustomData: false,
 | 
				
			||||||
 | 
					            showPrivileges: false,
 | 
				
			||||||
 | 
					            showAuthenticationRestrictions: false,
 | 
				
			||||||
 | 
					            filter: {},
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    createUser: {
 | 
				
			||||||
 | 
					        name: 'createUser',
 | 
				
			||||||
 | 
					        description: '创建新用户',
 | 
				
			||||||
 | 
					        cmd: {
 | 
				
			||||||
 | 
					            createUser: '<username>',
 | 
				
			||||||
 | 
					            pwd: '<cleartext password>',
 | 
				
			||||||
 | 
					            roles: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    role: '<role>',
 | 
				
			||||||
 | 
					                    db: '<database>',
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    grantRolesToUser: {
 | 
				
			||||||
 | 
					        name: 'grantRolesToUser',
 | 
				
			||||||
 | 
					        description: '授予对用户的额外角色',
 | 
				
			||||||
 | 
					        cmd: {
 | 
				
			||||||
 | 
					            grantRolesToUser: '<user>',
 | 
				
			||||||
 | 
					            roles: [''],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    dropUser: {
 | 
				
			||||||
 | 
					        name: 'dropUser',
 | 
				
			||||||
 | 
					        description: '删除用户',
 | 
				
			||||||
 | 
					        cmd: {
 | 
				
			||||||
 | 
					            dropUser: '<user>',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    roleInfo: {
 | 
				
			||||||
 | 
					        name: 'roleInfo',
 | 
				
			||||||
 | 
					        description: '获取角色信息',
 | 
				
			||||||
 | 
					        cmd: {
 | 
				
			||||||
 | 
					            rolesInfo: 1,
 | 
				
			||||||
 | 
					            showAuthenticationRestrictions: false,
 | 
				
			||||||
 | 
					            showBuiltinRoles: true,
 | 
				
			||||||
 | 
					            showPrivileges: false,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    createRole: {
 | 
				
			||||||
 | 
					        name: 'createRole',
 | 
				
			||||||
 | 
					        description: '创建角色',
 | 
				
			||||||
 | 
					        cmd: {
 | 
				
			||||||
 | 
					            createRole: '<new role>',
 | 
				
			||||||
 | 
					            privileges: [{ resource: {}, actions: ['<action>'] }],
 | 
				
			||||||
 | 
					            roles: [{ role: '<role>', db: '<database>' }],
 | 
				
			||||||
 | 
					            authenticationRestrictions: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    clientSource: ['<IP> | <CIDR range>'],
 | 
				
			||||||
 | 
					                    serverAddress: ['<IP> |<CIDR range>'],
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            writeConcern: '<write concern document>',
 | 
				
			||||||
 | 
					            comment: '<any>',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const state = reactive({
 | 
				
			||||||
 | 
					    dbs: [] as any,
 | 
				
			||||||
 | 
					    selectDbDisabled: false,
 | 
				
			||||||
 | 
					    runCmdDialog: {
 | 
				
			||||||
 | 
					        visible: false,
 | 
				
			||||||
 | 
					        cmdName: '',
 | 
				
			||||||
 | 
					        db: '',
 | 
				
			||||||
 | 
					        cmd: '',
 | 
				
			||||||
 | 
					        cmdRes: '',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { dbs, runCmdDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(props, async (newValue: any) => {
 | 
				
			||||||
 | 
					    if (!newValue.visible) {
 | 
				
			||||||
 | 
					        state.runCmdDialog.visible = false;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    state.runCmdDialog.visible = newValue.visible;
 | 
				
			||||||
 | 
					    state.dbs = (await mongoApi.databases.request({ id: props.id })).Databases;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const close = () => {
 | 
				
			||||||
 | 
					    emit('update:visible', false);
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmd = '';
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmdRes = '';
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmdName = '';
 | 
				
			||||||
 | 
					    state.runCmdDialog.db = '';
 | 
				
			||||||
 | 
					    state.dbs = [];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const changeCmd = (val: any) => {
 | 
				
			||||||
 | 
					    const mongoCmd = mongoCmds[val];
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmd = JSON.stringify(mongoCmd.cmd, null, 4);
 | 
				
			||||||
 | 
					    state.runCmdDialog.db = state?.dbs[0]?.Name;
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmdRes = '';
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onRunCommand = async () => {
 | 
				
			||||||
 | 
					    const orderCmds = [] as any;
 | 
				
			||||||
 | 
					    const cmdObj = JSON.parse(state.runCmdDialog.cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (let item of Object.keys(cmdObj)) {
 | 
				
			||||||
 | 
					        let obj = {};
 | 
				
			||||||
 | 
					        obj[item] = cmdObj[item];
 | 
				
			||||||
 | 
					        orderCmds.push(obj);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmdRes = '';
 | 
				
			||||||
 | 
					    const res = await mongoApi.runCommand.request({
 | 
				
			||||||
 | 
					        id: props.id,
 | 
				
			||||||
 | 
					        database: state.runCmdDialog.db,
 | 
				
			||||||
 | 
					        command: orderCmds,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    state.runCmdDialog.cmdRes = JSON.stringify(res, null, 4);
 | 
				
			||||||
 | 
					    ElMessage.success('执行成功');
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style></style>
 | 
				
			||||||
@@ -701,10 +701,10 @@ concat-map@0.0.1:
 | 
				
			|||||||
  resolved "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz"
 | 
					  resolved "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz"
 | 
				
			||||||
  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 | 
					  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
countup.js@^2.0.7:
 | 
					countup.js@^2.7.0:
 | 
				
			||||||
  version "2.0.8"
 | 
					  version "2.7.0"
 | 
				
			||||||
  resolved "https://registry.nlark.com/countup.js/download/countup.js-2.0.8.tgz"
 | 
					  resolved "https://registry.npmmirror.com/countup.js/-/countup.js-2.7.0.tgz#a5521bd935f0ae83417d0128e73f2a2d2543c9c7"
 | 
				
			||||||
  integrity sha1-7KDDHJ2z93acuklNkxXNUtuq8bk=
 | 
					  integrity sha512-IP9nYLGgW//0If73eXQdFlReGhpFGHaStqB1v82FknxnUWueF6HFuuOXySW4sEDMc88PsZL1EOn/NPkfTZalmQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cropperjs@^1.5.11:
 | 
					cropperjs@^1.5.11:
 | 
				
			||||||
  version "1.5.12"
 | 
					  version "1.5.12"
 | 
				
			||||||
@@ -1414,10 +1414,10 @@ mitt@^3.0.1:
 | 
				
			|||||||
  resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
 | 
					  resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
 | 
				
			||||||
  integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
 | 
					  integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
monaco-editor@^0.40.0:
 | 
					monaco-editor@^0.41.0:
 | 
				
			||||||
  version "0.40.0"
 | 
					  version "0.41.0"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.40.0.tgz#d10834e15ad50a15ec61fd01892e508464ebe2fe"
 | 
					  resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.41.0.tgz#2ba31e5af7e3ae93ac5d7467ec2772ef9b3d967f"
 | 
				
			||||||
  integrity sha512-1wymccLEuFSMBvCk/jT1YDW/GuxMLYwnFwF9CDyYCxoTw2Pt379J3FUhwy9c43j51JdcxVPjwk0jm0EVDsBS2g==
 | 
					  integrity sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
monaco-sql-languages@^0.11.0:
 | 
					monaco-sql-languages@^0.11.0:
 | 
				
			||||||
  version "0.11.0"
 | 
					  version "0.11.0"
 | 
				
			||||||
@@ -1575,7 +1575,7 @@ postcss@^8.1.10:
 | 
				
			|||||||
    picocolors "^1.0.0"
 | 
					    picocolors "^1.0.0"
 | 
				
			||||||
    source-map-js "^1.0.1"
 | 
					    source-map-js "^1.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
postcss@^8.4.26:
 | 
					postcss@^8.4.27:
 | 
				
			||||||
  version "8.4.27"
 | 
					  version "8.4.27"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
 | 
					  resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
 | 
				
			||||||
  integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
 | 
					  integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
 | 
				
			||||||
@@ -1666,10 +1666,10 @@ rimraf@^3.0.2:
 | 
				
			|||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    glob "^7.1.3"
 | 
					    glob "^7.1.3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rollup@^3.25.2:
 | 
					rollup@^3.27.1:
 | 
				
			||||||
  version "3.26.2"
 | 
					  version "3.28.0"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/rollup/-/rollup-3.26.2.tgz#2e76a37606cb523fc9fef43e6f59c93f86d95e7c"
 | 
					  resolved "https://registry.npmmirror.com/rollup/-/rollup-3.28.0.tgz#a3c70004b01934760c0cb8df717c7a1d932389a2"
 | 
				
			||||||
  integrity sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==
 | 
					  integrity sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==
 | 
				
			||||||
  optionalDependencies:
 | 
					  optionalDependencies:
 | 
				
			||||||
    fsevents "~2.3.2"
 | 
					    fsevents "~2.3.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1855,14 +1855,14 @@ uri-js@^4.2.2:
 | 
				
			|||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    punycode "^2.1.0"
 | 
					    punycode "^2.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vite@^4.4.7:
 | 
					vite@^4.4.9:
 | 
				
			||||||
  version "4.4.7"
 | 
					  version "4.4.9"
 | 
				
			||||||
  resolved "https://registry.npmmirror.com/vite/-/vite-4.4.7.tgz#71b8a37abaf8d50561aca084dbb77fa342824154"
 | 
					  resolved "https://registry.npmmirror.com/vite/-/vite-4.4.9.tgz#1402423f1a2f8d66fd8d15e351127c7236d29d3d"
 | 
				
			||||||
  integrity sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==
 | 
					  integrity sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    esbuild "^0.18.10"
 | 
					    esbuild "^0.18.10"
 | 
				
			||||||
    postcss "^8.4.26"
 | 
					    postcss "^8.4.27"
 | 
				
			||||||
    rollup "^3.25.2"
 | 
					    rollup "^3.27.1"
 | 
				
			||||||
  optionalDependencies:
 | 
					  optionalDependencies:
 | 
				
			||||||
    fsevents "~2.3.2"
 | 
					    fsevents "~2.3.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,30 +1,33 @@
 | 
				
			|||||||
module mayfly-go
 | 
					module mayfly-go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.20
 | 
					go 1.21
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/buger/jsonparser v1.1.1
 | 
						github.com/buger/jsonparser v1.1.1
 | 
				
			||||||
	github.com/gin-gonic/gin v1.9.1
 | 
						github.com/gin-gonic/gin v1.9.1
 | 
				
			||||||
	github.com/go-gormigrate/gormigrate/v2 v2.1.0
 | 
						github.com/go-gormigrate/gormigrate/v2 v2.1.0
 | 
				
			||||||
 | 
						github.com/go-playground/locales v0.14.1
 | 
				
			||||||
 | 
						github.com/go-playground/universal-translator v0.18.1
 | 
				
			||||||
 | 
						github.com/go-playground/validator/v10 v10.14.0
 | 
				
			||||||
	github.com/go-sql-driver/mysql v1.7.1
 | 
						github.com/go-sql-driver/mysql v1.7.1
 | 
				
			||||||
	github.com/golang-jwt/jwt/v5 v5.0.0
 | 
						github.com/golang-jwt/jwt/v5 v5.0.0
 | 
				
			||||||
	github.com/gorilla/websocket v1.5.0
 | 
						github.com/gorilla/websocket v1.5.0
 | 
				
			||||||
	github.com/lib/pq v1.10.7
 | 
						github.com/lib/pq v1.10.9
 | 
				
			||||||
	github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d
 | 
						github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d
 | 
				
			||||||
	github.com/mojocn/base64Captcha v1.3.5 // 验证码
 | 
						github.com/mojocn/base64Captcha v1.3.5 // 验证码
 | 
				
			||||||
	github.com/pkg/sftp v1.13.5
 | 
						github.com/pkg/sftp v1.13.6
 | 
				
			||||||
	github.com/pquerna/otp v1.4.0
 | 
						github.com/pquerna/otp v1.4.0
 | 
				
			||||||
	github.com/redis/go-redis/v9 v9.0.5
 | 
						github.com/redis/go-redis/v9 v9.1.0
 | 
				
			||||||
	github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
						github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
				
			||||||
	github.com/sirupsen/logrus v1.9.3
 | 
						github.com/sirupsen/logrus v1.9.3
 | 
				
			||||||
	github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
 | 
						github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
 | 
				
			||||||
	go.mongodb.org/mongo-driver v1.11.4 // mongo
 | 
						go.mongodb.org/mongo-driver v1.12.1 // mongo
 | 
				
			||||||
	golang.org/x/crypto v0.11.0 // ssh
 | 
						golang.org/x/crypto v0.12.0 // ssh
 | 
				
			||||||
	golang.org/x/oauth2 v0.10.0
 | 
						golang.org/x/oauth2 v0.11.0
 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1
 | 
						gopkg.in/yaml.v3 v3.0.1
 | 
				
			||||||
	// gorm
 | 
						// gorm
 | 
				
			||||||
	gorm.io/driver/mysql v1.5.1
 | 
						gorm.io/driver/mysql v1.5.1
 | 
				
			||||||
	gorm.io/gorm v1.25.2
 | 
						gorm.io/gorm v1.25.4
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
@@ -35,9 +38,6 @@ require (
 | 
				
			|||||||
	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
						github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
				
			||||||
	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 | 
						github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 | 
				
			||||||
	github.com/gin-contrib/sse v0.1.0 // indirect
 | 
						github.com/gin-contrib/sse v0.1.0 // indirect
 | 
				
			||||||
	github.com/go-playground/locales v0.14.1 // indirect
 | 
					 | 
				
			||||||
	github.com/go-playground/universal-translator v0.18.1 // indirect
 | 
					 | 
				
			||||||
	github.com/go-playground/validator/v10 v10.14.0 // indirect
 | 
					 | 
				
			||||||
	github.com/goccy/go-json v0.10.2 // indirect
 | 
						github.com/goccy/go-json v0.10.2 // indirect
 | 
				
			||||||
	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 | 
						github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 | 
				
			||||||
	github.com/golang/protobuf v1.5.3 // indirect
 | 
						github.com/golang/protobuf v1.5.3 // indirect
 | 
				
			||||||
@@ -48,25 +48,26 @@ require (
 | 
				
			|||||||
	github.com/klauspost/compress v1.13.6 // indirect
 | 
						github.com/klauspost/compress v1.13.6 // indirect
 | 
				
			||||||
	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
 | 
						github.com/klauspost/cpuid/v2 v2.2.4 // indirect
 | 
				
			||||||
	github.com/kr/fs v0.1.0 // indirect
 | 
						github.com/kr/fs v0.1.0 // indirect
 | 
				
			||||||
 | 
						github.com/kr/pretty v0.3.0 // indirect
 | 
				
			||||||
	github.com/leodido/go-urn v1.2.4 // indirect
 | 
						github.com/leodido/go-urn v1.2.4 // indirect
 | 
				
			||||||
	github.com/mattn/go-isatty v0.0.19 // indirect
 | 
						github.com/mattn/go-isatty v0.0.19 // indirect
 | 
				
			||||||
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 | 
						github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 | 
				
			||||||
	github.com/modern-go/reflect2 v1.0.2 // indirect
 | 
						github.com/modern-go/reflect2 v1.0.2 // indirect
 | 
				
			||||||
	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 | 
						github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 | 
				
			||||||
	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
 | 
						github.com/pelletier/go-toml/v2 v2.0.8 // indirect
 | 
				
			||||||
	github.com/pkg/errors v0.9.1 // indirect
 | 
					 | 
				
			||||||
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 | 
						github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 | 
				
			||||||
	github.com/ugorji/go/codec v1.2.11 // indirect
 | 
						github.com/ugorji/go/codec v1.2.11 // indirect
 | 
				
			||||||
	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 | 
						github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 | 
				
			||||||
	github.com/xdg-go/scram v1.1.1 // indirect
 | 
						github.com/xdg-go/scram v1.1.2 // indirect
 | 
				
			||||||
	github.com/xdg-go/stringprep v1.0.3 // indirect
 | 
						github.com/xdg-go/stringprep v1.0.4 // indirect
 | 
				
			||||||
	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
 | 
						github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
 | 
				
			||||||
	golang.org/x/arch v0.3.0 // indirect
 | 
						golang.org/x/arch v0.3.0 // indirect
 | 
				
			||||||
	golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
 | 
						golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
 | 
				
			||||||
	golang.org/x/net v0.12.0 // indirect
 | 
						golang.org/x/net v0.14.0 // indirect
 | 
				
			||||||
	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
 | 
						golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
 | 
				
			||||||
	golang.org/x/sys v0.10.0 // indirect
 | 
						golang.org/x/sys v0.11.0 // indirect
 | 
				
			||||||
	golang.org/x/text v0.11.0 // indirect
 | 
						golang.org/x/text v0.12.0 // indirect
 | 
				
			||||||
	google.golang.org/appengine v1.6.7 // indirect
 | 
						google.golang.org/appengine v1.6.7 // indirect
 | 
				
			||||||
	google.golang.org/protobuf v1.31.0 // indirect
 | 
						google.golang.org/protobuf v1.31.0 // indirect
 | 
				
			||||||
 | 
						gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ type MongoCommand struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type MongoRunCommand struct {
 | 
					type MongoRunCommand struct {
 | 
				
			||||||
	Database string           `binding:"required" json:"database"`
 | 
						Database string           `binding:"required" json:"database"`
 | 
				
			||||||
	Command  map[string]any `json:"command"`
 | 
						Command  []map[string]any `json:"command"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MongoFindCommand struct {
 | 
					type MongoFindCommand struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,12 +91,24 @@ func (m *Mongo) RunCommand(rc *req.Ctx) {
 | 
				
			|||||||
	commandForm := new(form.MongoRunCommand)
 | 
						commandForm := new(form.MongoRunCommand)
 | 
				
			||||||
	ginx.BindJsonAndValid(rc.GinCtx, commandForm)
 | 
						ginx.BindJsonAndValid(rc.GinCtx, commandForm)
 | 
				
			||||||
	cli := m.MongoApp.GetMongoCli(m.GetMongoId(rc.GinCtx))
 | 
						cli := m.MongoApp.GetMongoCli(m.GetMongoId(rc.GinCtx))
 | 
				
			||||||
 | 
						rc.ReqParam = commandForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 顺序执行
 | 
				
			||||||
 | 
						commands := bson.D{}
 | 
				
			||||||
 | 
						for _, cmd := range commandForm.Command {
 | 
				
			||||||
 | 
							e := bson.E{}
 | 
				
			||||||
 | 
							for k, v := range cmd {
 | 
				
			||||||
 | 
								e.Key = k
 | 
				
			||||||
 | 
								e.Value = v
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							commands = append(commands, e)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx := context.TODO()
 | 
						ctx := context.TODO()
 | 
				
			||||||
	var bm bson.M
 | 
						var bm bson.M
 | 
				
			||||||
	err := cli.Database(commandForm.Database).RunCommand(
 | 
						err := cli.Database(commandForm.Database).RunCommand(
 | 
				
			||||||
		ctx,
 | 
							ctx,
 | 
				
			||||||
		commandForm.Command,
 | 
							commands,
 | 
				
			||||||
	).Decode(&bm)
 | 
						).Decode(&bm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "执行命令失败: %s")
 | 
						biz.ErrIsNilAppendErr(err, "执行命令失败: %s")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,8 @@ func InitMongoRouter(router *gin.RouterGroup) {
 | 
				
			|||||||
		TagApp:   tagapp.GetTagTreeApp(),
 | 
							TagApp:   tagapp.GetTagTreeApp(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						saveDataPerm := req.NewPermission("mongo:data:save")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reqs := [...]*req.Conf{
 | 
						reqs := [...]*req.Conf{
 | 
				
			||||||
		// 获取所有mongo列表
 | 
							// 获取所有mongo列表
 | 
				
			||||||
		req.NewGet("", ma.Mongos),
 | 
							req.NewGet("", ma.Mongos),
 | 
				
			||||||
@@ -39,13 +41,13 @@ func InitMongoRouter(router *gin.RouterGroup) {
 | 
				
			|||||||
		// 执行mongo find命令
 | 
							// 执行mongo find命令
 | 
				
			||||||
		req.NewPost(":id/command/find", ma.FindCommand),
 | 
							req.NewPost(":id/command/find", ma.FindCommand),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewPost(":id/command/update-by-id", ma.UpdateByIdCommand).Log(req.NewLogSave("mongo-更新文档")),
 | 
							req.NewPost(":id/command/update-by-id", ma.UpdateByIdCommand).RequiredPermission(saveDataPerm).Log(req.NewLogSave("mongo-更新文档")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 执行mongo delete by id命令
 | 
							// 执行mongo delete by id命令
 | 
				
			||||||
		req.NewPost(":id/command/delete-by-id", ma.DeleteByIdCommand).Log(req.NewLogSave("mongo-删除文档")),
 | 
							req.NewPost(":id/command/delete-by-id", ma.DeleteByIdCommand).RequiredPermission(req.NewPermission("mongo:data:del")).Log(req.NewLogSave("mongo-删除文档")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 执行mongo insert 命令
 | 
							// 执行mongo insert 命令
 | 
				
			||||||
		req.NewPost(":id/command/insert", ma.InsertOneCommand).Log(req.NewLogSave("mogno-插入文档")),
 | 
							req.NewPost(":id/command/insert", ma.InsertOneCommand).RequiredPermission(saveDataPerm).Log(req.NewLogSave("mogno-插入文档")),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req.BatchSetGroup(m, reqs[:])
 | 
						req.BatchSetGroup(m, reqs[:])
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user