mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	otp: 样式优化
This commit is contained in:
		@@ -63,7 +63,7 @@
 | 
			
		||||
        "sass": "^1.87.0",
 | 
			
		||||
        "tailwindcss": "^4.1.4",
 | 
			
		||||
        "typescript": "^5.8.2",
 | 
			
		||||
        "vite": "^6.3.2",
 | 
			
		||||
        "vite": "^6.3.3",
 | 
			
		||||
        "vite-plugin-progress": "0.0.7",
 | 
			
		||||
        "vue-eslint-parser": "^10.1.3"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="monaco-editor-custom h-full" style="border: 1px solid var(--el-border-color-light, #ebeef5)">
 | 
			
		||||
    <div class="monaco-editor-custom relative h-full" style="border: 1px solid var(--el-border-color-light, #ebeef5)">
 | 
			
		||||
        <div class="monaco-editor-content" ref="monacoTextareaRef" :style="{ height: height }"></div>
 | 
			
		||||
        <el-select v-if="canChangeMode" class="code-mode-select" v-model="languageMode" @change="changeLanguage" filterable>
 | 
			
		||||
            <el-option v-for="mode in languageArr" :key="mode.value" :label="mode.label" :value="mode.value"> </el-option>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
            </SearchForm>
 | 
			
		||||
        </transition>
 | 
			
		||||
 | 
			
		||||
        <el-card class="h-full" body-class="h-full">
 | 
			
		||||
        <el-card class="h-full" body-class="h-full flex flex-col">
 | 
			
		||||
            <!-- 表格头部 操作按钮 -->
 | 
			
		||||
            <div class="flex justify-between">
 | 
			
		||||
                <div>
 | 
			
		||||
@@ -79,8 +79,9 @@
 | 
			
		||||
                </slot>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="h-[calc(100%-90px)]">
 | 
			
		||||
            <div class="flex-1 overflow-auto">
 | 
			
		||||
                <el-table
 | 
			
		||||
                    v-show="showTable"
 | 
			
		||||
                    ref="tableRef"
 | 
			
		||||
                    v-bind="$attrs"
 | 
			
		||||
                    height="100%"
 | 
			
		||||
@@ -152,7 +153,6 @@
 | 
			
		||||
                    :small="props.size == 'small'"
 | 
			
		||||
                    @current-change="pageNumChange"
 | 
			
		||||
                    @size-change="pageSizeChange"
 | 
			
		||||
                    style="text-align: right"
 | 
			
		||||
                    layout="prev, pager, next, total, sizes"
 | 
			
		||||
                    :total="total"
 | 
			
		||||
                    v-model:current-page="queryForm.pageNum"
 | 
			
		||||
@@ -165,7 +165,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { toRefs, watch, reactive, onMounted, Ref, ref, useSlots, toValue } from 'vue';
 | 
			
		||||
import { toRefs, watch, reactive, onMounted, Ref, ref, useSlots, toValue, h } from 'vue';
 | 
			
		||||
import { TableColumn } from './index';
 | 
			
		||||
import EnumTag from '@/components/enumtag/EnumTag.vue';
 | 
			
		||||
import { useThemeConfig } from '@/store/themeConfig';
 | 
			
		||||
@@ -176,7 +176,7 @@ import { SearchItem } from '../SearchForm/index';
 | 
			
		||||
import SearchFormItem from '../SearchForm/components/SearchFormItem.vue';
 | 
			
		||||
import SvgIcon from '@/components/svgIcon/index.vue';
 | 
			
		||||
import { usePageTable } from '@/hooks/usePageTable';
 | 
			
		||||
import { ElTable } from 'element-plus';
 | 
			
		||||
import { ElInput, ElTable } from 'element-plus';
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:selectionData', 'pageSizeChange', 'pageNumChange']);
 | 
			
		||||
 | 
			
		||||
@@ -240,6 +240,10 @@ const showToolButton = (key: 'setting' | 'search') => {
 | 
			
		||||
 | 
			
		||||
const nowSearchItem: Ref<SearchItem> = ref(null) as any;
 | 
			
		||||
 | 
			
		||||
// 是否已经计算列宽度
 | 
			
		||||
const isCalculatedWidth: Ref<boolean> = ref(false);
 | 
			
		||||
const showTable: Ref<boolean> = ref(false);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 改变当前的搜索项
 | 
			
		||||
 * @param searchItem 当前点击的搜索项
 | 
			
		||||
@@ -276,14 +280,30 @@ const state = reactive({
 | 
			
		||||
const { pageSizes, formatVal } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(tableData, (newValue: any) => {
 | 
			
		||||
    if (newValue && newValue.length > 0) {
 | 
			
		||||
    calculateTableColumnMinWidth();
 | 
			
		||||
    // 需要计算完才能显示表格,否则会有表格闪烁的问题
 | 
			
		||||
    if (!showTable.value) {
 | 
			
		||||
        showTable.value = true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 计算表格列宽
 | 
			
		||||
 */
 | 
			
		||||
const calculateTableColumnMinWidth = () => {
 | 
			
		||||
    if (isCalculatedWidth.value || !tableData.value || tableData.value.length === 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 计算表格列宽
 | 
			
		||||
    props.columns.forEach((item) => {
 | 
			
		||||
        if (item.autoWidth && item.show) {
 | 
			
		||||
            item.autoCalculateMinWidth(tableData.value);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
    isCalculatedWidth.value = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
    () => props.data,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div id="terminal-body" :style="{ height }">
 | 
			
		||||
        <div ref="terminalRef" class="terminal" />
 | 
			
		||||
    <div class="h-full w-full flex">
 | 
			
		||||
        <div ref="terminalRef" class="h-full w-full" :style="{ background: getTerminalTheme().background }" />
 | 
			
		||||
 | 
			
		||||
        <TerminalSearch ref="terminalSearchRef" :search-addon="state.addon.search" @close="focus" />
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -18,7 +18,7 @@ import { useThemeConfig } from '@/store/themeConfig';
 | 
			
		||||
import { ref, nextTick, reactive, onMounted, onBeforeUnmount, watch } from 'vue';
 | 
			
		||||
import TerminalSearch from './TerminalSearch.vue';
 | 
			
		||||
import { TerminalStatus } from './common';
 | 
			
		||||
import { useDebounceFn, useEventListener } from '@vueuse/core';
 | 
			
		||||
import { useDebounceFn, useEventListener, useIntervalFn } from '@vueuse/core';
 | 
			
		||||
import themes from './themes';
 | 
			
		||||
import { TrzszFilter } from 'trzsz';
 | 
			
		||||
import { useI18n } from 'vue-i18n';
 | 
			
		||||
@@ -41,13 +41,6 @@ const props = defineProps({
 | 
			
		||||
    socketUrl: {
 | 
			
		||||
        type: String,
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 高度
 | 
			
		||||
     */
 | 
			
		||||
    height: {
 | 
			
		||||
        type: [String, Number],
 | 
			
		||||
        default: '100%',
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['statusChange']);
 | 
			
		||||
@@ -60,7 +53,6 @@ const { themeConfig } = storeToRefs(useThemeConfig());
 | 
			
		||||
// 终端实例
 | 
			
		||||
let term: Terminal;
 | 
			
		||||
let socket: WebSocket;
 | 
			
		||||
let pingInterval: any;
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    // 插件
 | 
			
		||||
@@ -89,8 +81,10 @@ watch(
 | 
			
		||||
watch(
 | 
			
		||||
    () => themeConfig.value.terminalTheme,
 | 
			
		||||
    () => {
 | 
			
		||||
        if (term) {
 | 
			
		||||
            term.options.theme = getTerminalTheme();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
onBeforeUnmount(() => {
 | 
			
		||||
@@ -154,7 +148,8 @@ function initSocket() {
 | 
			
		||||
    // 监听socket连接
 | 
			
		||||
    socket.onopen = () => {
 | 
			
		||||
        // 注册心跳
 | 
			
		||||
        pingInterval = setInterval(sendPing, 15000);
 | 
			
		||||
        useIntervalFn(sendPing, 15000);
 | 
			
		||||
 | 
			
		||||
        state.status = TerminalStatus.Connected;
 | 
			
		||||
 | 
			
		||||
        focus();
 | 
			
		||||
@@ -289,8 +284,6 @@ function sendCmd(key: any) {
 | 
			
		||||
function closeSocket() {
 | 
			
		||||
    // 关闭 websocket
 | 
			
		||||
    socket && socket.readyState === 1 && socket.close();
 | 
			
		||||
    // 清除 ping
 | 
			
		||||
    pingInterval && clearInterval(pingInterval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function close() {
 | 
			
		||||
@@ -310,17 +303,4 @@ const getStatus = (): TerminalStatus => {
 | 
			
		||||
 | 
			
		||||
defineExpose({ init, fitTerminal, focus, clear, close, getStatus, sendResize, write2Term, writeln2Term });
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
#terminal-body {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
 | 
			
		||||
    .terminal {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
 | 
			
		||||
        // .xterm .xterm-viewport {
 | 
			
		||||
        //     overflow-y: hidden;
 | 
			
		||||
        // }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<style lang="scss"></style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-drawer v-model="visible" :before-close="cancel" size="50%">
 | 
			
		||||
        <el-drawer v-model="visible" :before-close="cancel" size="50%" body-class="flex flex-col">
 | 
			
		||||
            <template #header>
 | 
			
		||||
                <DrawerHeader :header="props.title" :back="cancel">
 | 
			
		||||
                    <template #extra>
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
                <el-descriptions-item v-for="(value, key) in extra" :key="key" :span="1" :label="key">{{ value }}</el-descriptions-item>
 | 
			
		||||
            </el-descriptions>
 | 
			
		||||
 | 
			
		||||
            <TerminalBody class="mb-2" ref="terminalRef" height="calc(100vh - 220px)" />
 | 
			
		||||
            <TerminalBody class="mb-2 flex-1" ref="terminalRef" />
 | 
			
		||||
        </el-drawer>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ export const usePageTable = (
 | 
			
		||||
) => {
 | 
			
		||||
    const state = reactive({
 | 
			
		||||
        // 表格数据
 | 
			
		||||
        tableData: [],
 | 
			
		||||
        tableData: [{}],
 | 
			
		||||
        // 总数量
 | 
			
		||||
        total: 0,
 | 
			
		||||
        // 查询参数,包含分页参数
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,11 @@ import router from '@/router';
 | 
			
		||||
import { clearUser, getClientId, getRefreshToken, getToken, saveRefreshToken, saveToken } from '@/common/utils/storage';
 | 
			
		||||
import { templateResolve } from '@/common/utils/string';
 | 
			
		||||
import { ElMessage } from 'element-plus';
 | 
			
		||||
import { createFetch } from '@vueuse/core';
 | 
			
		||||
import { createFetch, UseFetchReturn } from '@vueuse/core';
 | 
			
		||||
import Api from '@/common/Api';
 | 
			
		||||
import { Result, ResultEnum } from '@/common/request';
 | 
			
		||||
import config from '@/common/config';
 | 
			
		||||
import { unref } from 'vue';
 | 
			
		||||
import { ref, unref } from 'vue';
 | 
			
		||||
import { URL_401 } from '@/router/staticRouter';
 | 
			
		||||
import openApi from '@/common/openApi';
 | 
			
		||||
import { useThemeConfig } from '@/store/themeConfig';
 | 
			
		||||
@@ -92,12 +92,15 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // 统一处理后的返回结果,如果直接使用uaf.data,则数据会出现由{code: x, data: {}} -> data 的变化导致某些结果绑定报错
 | 
			
		||||
    const data = ref<T | null>(null);
 | 
			
		||||
    return {
 | 
			
		||||
        execute: async function () {
 | 
			
		||||
            return execCustomFetch(uaf);
 | 
			
		||||
            await execCustomFetch(uaf);
 | 
			
		||||
            data.value = uaf.data.value;
 | 
			
		||||
        },
 | 
			
		||||
        isFetching: uaf.isFetching,
 | 
			
		||||
        data: uaf.data,
 | 
			
		||||
        data: data,
 | 
			
		||||
        abort: uaf.abort,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -105,7 +108,7 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
 | 
			
		||||
let refreshingToken = false;
 | 
			
		||||
let queue: any[] = [];
 | 
			
		||||
 | 
			
		||||
async function execCustomFetch(uaf: any) {
 | 
			
		||||
async function execCustomFetch(uaf: UseFetchReturn<any>) {
 | 
			
		||||
    try {
 | 
			
		||||
        await uaf.execute(true);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
@@ -118,22 +121,22 @@ async function execCustomFetch(uaf: any) {
 | 
			
		||||
 | 
			
		||||
        const respStatus = uaf.response.value?.status;
 | 
			
		||||
        if (respStatus == 404) {
 | 
			
		||||
            ElMessage.error('请求接口不存在');
 | 
			
		||||
            ElMessage.error('url not found');
 | 
			
		||||
            return rejectPromise;
 | 
			
		||||
        }
 | 
			
		||||
        if (respStatus == 500) {
 | 
			
		||||
            ElMessage.error('服务器响应异常');
 | 
			
		||||
            ElMessage.error('server error');
 | 
			
		||||
            return rejectPromise;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        console.error(e);
 | 
			
		||||
        ElMessage.error('网络请求错误');
 | 
			
		||||
        ElMessage.error('network error');
 | 
			
		||||
        return rejectPromise;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const result: Result = uaf.data.value as any;
 | 
			
		||||
    if (!result) {
 | 
			
		||||
        ElMessage.error('网络请求失败');
 | 
			
		||||
        ElMessage.error('network request failed');
 | 
			
		||||
        return Promise.reject(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <el-container class="layout-container flex-center">
 | 
			
		||||
        <Header />
 | 
			
		||||
        <el-container class="h-[calc(100vh-50px)]">
 | 
			
		||||
        <el-container class="flex-1 overflow-auto">
 | 
			
		||||
            <Aside />
 | 
			
		||||
            <div class="flex-center layout-backtop">
 | 
			
		||||
                <TagsView v-if="themeConfig.isTagsview" />
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,6 @@ body,
 | 
			
		||||
    -webkit-tap-highlight-color: transparent;
 | 
			
		||||
    background-color: var(--bg-main-color);
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    // overflow: hidden;
 | 
			
		||||
    // position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 主布局样式
 | 
			
		||||
 
 | 
			
		||||
@@ -22,14 +22,21 @@
 | 
			
		||||
 | 
			
		||||
                <el-table-column prop="res" :label="$t('flow.runResult')" :min-width="30" show-overflow-tooltip>
 | 
			
		||||
                    <template #default="scope">
 | 
			
		||||
                        <el-popover placement="top" :width="400" trigger="hover">
 | 
			
		||||
                        <el-popover placement="top" width="50%" trigger="hover">
 | 
			
		||||
                            <template #reference>
 | 
			
		||||
                                <el-link icon="view" :type="scope.row.errorMsg ? 'danger' : 'success'" :underline="false"> </el-link>
 | 
			
		||||
                            </template>
 | 
			
		||||
 | 
			
		||||
                            <el-text v-if="scope.row.errorMsg">{{ scope.row.errorMsg }}</el-text>
 | 
			
		||||
                            <el-table v-else :data="scope.row.res" size="small">
 | 
			
		||||
                                <el-table-column v-for="col in scope.row.columns" :key="col.name" :label="col.name" :prop="col.name" />
 | 
			
		||||
                            <el-table max-height="600px" v-else :data="scope.row.res" size="small">
 | 
			
		||||
                                <el-table-column
 | 
			
		||||
                                    :width="DbInst.flexColumnWidth(col.name, scope.row.res)"
 | 
			
		||||
                                    v-for="col in scope.row.columns"
 | 
			
		||||
                                    :key="col.name"
 | 
			
		||||
                                    :label="col.name"
 | 
			
		||||
                                    :prop="col.name"
 | 
			
		||||
                                    show-overflow-tooltip
 | 
			
		||||
                                />
 | 
			
		||||
                            </el-table>
 | 
			
		||||
                        </el-popover>
 | 
			
		||||
                    </template>
 | 
			
		||||
@@ -50,6 +57,7 @@ import { tagApi } from '@/views/ops/tag/api';
 | 
			
		||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
 | 
			
		||||
import TagCodePath from '@/views/ops/component/TagCodePath.vue';
 | 
			
		||||
import SvgIcon from '@/components/svgIcon/index.vue';
 | 
			
		||||
import { DbInst } from '@/views/ops/db/db';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    procinst: {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <el-card class="h-full flex" body-class="!p-1 flex flex-col flex-1 overflow-auto">
 | 
			
		||||
    <el-card class="h-full flex" body-class="!p-1 flex flex-col w-full">
 | 
			
		||||
        <el-input v-model="filterText" :placeholder="$t('tag.tagFilterPlaceholder')" clearable size="small" class="!mb-1 w-full" />
 | 
			
		||||
        <el-scrollbar>
 | 
			
		||||
            <el-tree
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
                    <span
 | 
			
		||||
                        :id="node.key"
 | 
			
		||||
                        @dblclick="treeNodeDblclick(data, node)"
 | 
			
		||||
                        class="node-container flex items-center w-full cursor-pointer select-none"
 | 
			
		||||
                        class="node-container flex items-center cursor-pointer select-none"
 | 
			
		||||
                        :class="data.type.nodeDblclickFunc ? 'select-none' : ''"
 | 
			
		||||
                    >
 | 
			
		||||
                        <span v-if="data.type.value == TagTreeNode.TagPath">
 | 
			
		||||
 
 | 
			
		||||
@@ -65,10 +65,8 @@
 | 
			
		||||
            </el-form>
 | 
			
		||||
 | 
			
		||||
            <template #footer>
 | 
			
		||||
                <div class="dialog-footer">
 | 
			
		||||
                <el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
 | 
			
		||||
                <el-button type="primary" @click="btnOk">{{ $t('common.confirm') }}</el-button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </template>
 | 
			
		||||
        </el-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -90,9 +88,6 @@ import { useI18nFormValidate } from '@/hooks/useI18n';
 | 
			
		||||
import { Rules } from '@/common/rule';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    instance: {
 | 
			
		||||
        type: [Boolean, Object],
 | 
			
		||||
    },
 | 
			
		||||
@@ -104,8 +99,10 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change', 'confirm']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change', 'confirm']);
 | 
			
		||||
 | 
			
		||||
const rules = {
 | 
			
		||||
    instanceId: [Rules.requiredSelect('db.dbInst')],
 | 
			
		||||
@@ -121,7 +118,6 @@ const dbForm: any = ref(null);
 | 
			
		||||
// const tagSelectRef: any = ref(null);
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    allDatabases: [] as any,
 | 
			
		||||
    dbNamesSelected: [] as any,
 | 
			
		||||
    dbNamesFiltered: [] as any,
 | 
			
		||||
@@ -142,13 +138,10 @@ const state = reactive({
 | 
			
		||||
    loadingDbNames: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, allDatabases, form, dbNamesSelected } = toRefs(state);
 | 
			
		||||
const { allDatabases, form, dbNamesSelected } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
    () => props.visible,
 | 
			
		||||
    () => {
 | 
			
		||||
        state.dialogVisible = props.visible;
 | 
			
		||||
        if (!state.dialogVisible) {
 | 
			
		||||
watch(dialogVisible, () => {
 | 
			
		||||
    if (!dialogVisible.value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    const db: any = props.db;
 | 
			
		||||
@@ -162,8 +155,7 @@ watch(
 | 
			
		||||
        state.form = { getDatabaseMode: DbGetDbNamesMode.Auto.value } as any;
 | 
			
		||||
        state.dbNamesSelected = [];
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const onChangeGetDatabaseMode = (val: any) => {
 | 
			
		||||
    if (val == DbGetDbNamesMode.Auto.value) {
 | 
			
		||||
@@ -218,7 +210,7 @@ const resetInputDb = () => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    dialogVisible.value = false;
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
        resetInputDb();
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
                <DrawerHeader :header="title" :back="cancel" />
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
 | 
			
		||||
            <el-form :model="form" ref="dbFormRef" :rules="rules" label-width="auto">
 | 
			
		||||
                <el-divider content-position="left">{{ $t('common.basic') }}</el-divider>
 | 
			
		||||
 | 
			
		||||
                <el-form-item ref="tagSelectRef" prop="tagCodePaths" :label="$t('tag.relateTag')">
 | 
			
		||||
@@ -72,7 +72,7 @@
 | 
			
		||||
                            <el-option label="SID" :value="2" />
 | 
			
		||||
                        </el-select>
 | 
			
		||||
                    </el-col>
 | 
			
		||||
                    <el-col style="text-align: center" :span="1">:</el-col>
 | 
			
		||||
                    <el-col class="text-center" :span="1">:</el-col>
 | 
			
		||||
                    <el-col :span="18">
 | 
			
		||||
                        <el-input v-if="state.extra.stype == 1" v-model="state.extra.serviceName" placeholder="Service Name"> </el-input>
 | 
			
		||||
                        <el-input v-else v-model="state.extra.sid" placeholder="SID"> </el-input>
 | 
			
		||||
@@ -114,7 +114,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { reactive, ref, toRefs, watchEffect } from 'vue';
 | 
			
		||||
import { computed, reactive, ref, toRefs, watchEffect } from 'vue';
 | 
			
		||||
import { dbApi } from './api';
 | 
			
		||||
import { ElMessage } from 'element-plus';
 | 
			
		||||
import SshTunnelSelect from '../component/SshTunnelSelect.vue';
 | 
			
		||||
@@ -133,9 +133,6 @@ import { Rules } from '@/common/rule';
 | 
			
		||||
const { t } = useI18n();
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    data: {
 | 
			
		||||
        type: [Boolean, Object],
 | 
			
		||||
    },
 | 
			
		||||
@@ -144,8 +141,10 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change']);
 | 
			
		||||
 | 
			
		||||
const rules = {
 | 
			
		||||
    tagCodePaths: [Rules.requiredSelect('tag.relateTag')],
 | 
			
		||||
@@ -154,7 +153,7 @@ const rules = {
 | 
			
		||||
    host: [Rules.requiredInput('Host:Port')],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const dbForm: any = ref(null);
 | 
			
		||||
const dbFormRef: any = ref(null);
 | 
			
		||||
const tagSelectRef: any = ref(null);
 | 
			
		||||
 | 
			
		||||
const DefaultForm = {
 | 
			
		||||
@@ -173,20 +172,30 @@ const DefaultForm = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    extra: {} as any, // 连接需要的额外参数(json)
 | 
			
		||||
    form: DefaultForm,
 | 
			
		||||
    submitForm: {} as any,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, form, submitForm } = toRefs(state);
 | 
			
		||||
const { form } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
const submitForm = computed(() => {
 | 
			
		||||
    const reqForm: any = { ...state.form };
 | 
			
		||||
    reqForm.selectAuthCert = null;
 | 
			
		||||
    reqForm.tags = null;
 | 
			
		||||
    if (!state.form.sshTunnelMachineId) {
 | 
			
		||||
        reqForm.sshTunnelMachineId = -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (Object.keys(state.extra).length > 0) {
 | 
			
		||||
        reqForm.extra = state.extra;
 | 
			
		||||
    }
 | 
			
		||||
    return reqForm;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { isFetching: saveBtnLoading, execute: saveInstanceExec, data: saveInstanceRes } = dbApi.saveInstance.useApi(submitForm);
 | 
			
		||||
const { isFetching: testConnBtnLoading, execute: testConnExec } = dbApi.testConn.useApi(submitForm);
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
    state.dialogVisible = props.visible;
 | 
			
		||||
    if (!state.dialogVisible) {
 | 
			
		||||
    if (!dialogVisible.value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    const dbInst: any = props.data;
 | 
			
		||||
@@ -200,31 +209,16 @@ watchEffect(() => {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const getReqForm = async () => {
 | 
			
		||||
    const reqForm: any = { ...state.form };
 | 
			
		||||
    reqForm.selectAuthCert = null;
 | 
			
		||||
    reqForm.tags = null;
 | 
			
		||||
    if (!state.form.sshTunnelMachineId) {
 | 
			
		||||
        reqForm.sshTunnelMachineId = -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (Object.keys(state.extra).length > 0) {
 | 
			
		||||
        reqForm.extra = state.extra;
 | 
			
		||||
    }
 | 
			
		||||
    return reqForm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const testConn = async (authCert: any) => {
 | 
			
		||||
    await useI18nFormValidate(dbForm);
 | 
			
		||||
    state.submitForm = await getReqForm();
 | 
			
		||||
    state.submitForm.authCerts = [authCert];
 | 
			
		||||
    await useI18nFormValidate(dbFormRef);
 | 
			
		||||
    submitForm.value.authCerts = [authCert];
 | 
			
		||||
    await testConnExec();
 | 
			
		||||
    ElMessage.success(t('db.connSuccess'));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const btnOk = async () => {
 | 
			
		||||
    await useI18nFormValidate(dbForm);
 | 
			
		||||
    state.submitForm = await getReqForm();
 | 
			
		||||
    notBlankI18n(state.submitForm.authCerts, 'db.acName');
 | 
			
		||||
    await useI18nFormValidate(dbFormRef);
 | 
			
		||||
    notBlankI18n(submitForm.value.authCerts, 'db.acName');
 | 
			
		||||
    await saveInstanceExec();
 | 
			
		||||
    useI18nSaveSuccessMsg();
 | 
			
		||||
    state.form.id = saveInstanceRes as any;
 | 
			
		||||
@@ -233,7 +227,7 @@ const btnOk = async () => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    dialogVisible.value = false;
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
    state.extra = {};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -4,23 +4,23 @@
 | 
			
		||||
            <DrawerHeader :header="title" :back="cancel" />
 | 
			
		||||
        </template>
 | 
			
		||||
 | 
			
		||||
        <el-form label-position="left" ref="formRef" :model="tableData" label-width="80px">
 | 
			
		||||
            <el-row>
 | 
			
		||||
        <el-form label-position="left" ref="formRef" :model="tableData" label-width="auto">
 | 
			
		||||
            <el-row :gutter="20">
 | 
			
		||||
                <el-col :span="12">
 | 
			
		||||
                    <el-form-item prop="tableName" :label="$t('db.tableName')">
 | 
			
		||||
                        <el-input style="width: 80%" v-model="tableData.tableName" size="small"></el-input>
 | 
			
		||||
                        <el-input v-model="tableData.tableName" size="small"></el-input>
 | 
			
		||||
                    </el-form-item>
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="12">
 | 
			
		||||
                    <el-form-item prop="tableComment" :label="$t('db.comment')">
 | 
			
		||||
                        <el-input style="width: 80%" v-model="tableData.tableComment" size="small"></el-input>
 | 
			
		||||
                        <el-input v-model="tableData.tableComment" size="small"></el-input>
 | 
			
		||||
                    </el-form-item>
 | 
			
		||||
                </el-col>
 | 
			
		||||
            </el-row>
 | 
			
		||||
 | 
			
		||||
            <el-tabs v-model="activeName">
 | 
			
		||||
                <el-tab-pane :label="$t('db.column')" name="1">
 | 
			
		||||
                    <el-table ref="tableRef" :data="tableData.fields.res" :max-height="tableData.height">
 | 
			
		||||
                    <el-table ref="tableRef" :data="tableData.fields.res" :height="tableHeight">
 | 
			
		||||
                        <el-table-column
 | 
			
		||||
                            :prop="item.prop"
 | 
			
		||||
                            :label="$t(item.label)"
 | 
			
		||||
@@ -72,13 +72,13 @@
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                    </el-table>
 | 
			
		||||
                    <el-row style="margin-top: 20px">
 | 
			
		||||
                    <el-row class="mt-4">
 | 
			
		||||
                        <el-button @click="addDefaultRows()" link type="warning" icon="plus">{{ $t('db.addDefaultColumn') }}</el-button>
 | 
			
		||||
                        <el-button @click="addRow()" link type="primary" icon="plus">{{ $t('db.addColumn') }}</el-button>
 | 
			
		||||
                    </el-row>
 | 
			
		||||
                </el-tab-pane>
 | 
			
		||||
                <el-tab-pane :label="$t('db.index')" name="2">
 | 
			
		||||
                    <el-table :data="tableData.indexs.res" :max-height="tableData.height">
 | 
			
		||||
                    <el-table :data="tableData.indexs.res" :height="tableHeight">
 | 
			
		||||
                        <el-table-column :prop="item.prop" :label="$t(item.label)" v-for="item in tableData.indexs.colNames" :key="item.prop">
 | 
			
		||||
                            <template #default="scope">
 | 
			
		||||
                                <el-input v-if="item.prop === 'indexName'" size="small" disabled v-model="scope.row.indexName"></el-input>
 | 
			
		||||
@@ -90,8 +90,8 @@
 | 
			
		||||
                                    collapse-tags
 | 
			
		||||
                                    collapse-tags-tooltip
 | 
			
		||||
                                    filterable
 | 
			
		||||
                                    size="small"
 | 
			
		||||
                                    @change="indexChanges(scope.row)"
 | 
			
		||||
                                    style="width: 100%"
 | 
			
		||||
                                >
 | 
			
		||||
                                    <el-option v-for="cl in tableData.indexs.columns" :key="cl.name" :label="cl.name" :value="cl.name">
 | 
			
		||||
                                        {{ cl.name + ' - ' + (cl.remark || '') }}
 | 
			
		||||
@@ -114,7 +114,7 @@
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                    </el-table>
 | 
			
		||||
 | 
			
		||||
                    <el-row style="margin-top: 20px">
 | 
			
		||||
                    <el-row class="mt-4">
 | 
			
		||||
                        <el-button @click="addIndex()" link type="primary" icon="plus">{{ $t('db.addIndex') }}</el-button>
 | 
			
		||||
                    </el-row>
 | 
			
		||||
                </el-tab-pane>
 | 
			
		||||
@@ -173,6 +173,8 @@ type ColName = {
 | 
			
		||||
    width?: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const tableHeight = 'calc(100vh - 320px)';
 | 
			
		||||
 | 
			
		||||
const formRef: any = ref();
 | 
			
		||||
const tableRef: any = useTemplateRef('tableRef');
 | 
			
		||||
 | 
			
		||||
@@ -272,7 +274,6 @@ const state = reactive({
 | 
			
		||||
        tableComment: '',
 | 
			
		||||
        oldTableName: '',
 | 
			
		||||
        oldTableComment: '',
 | 
			
		||||
        height: 'calc(100vh - 310px)',
 | 
			
		||||
        db: '',
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="flex-all-center h-full">
 | 
			
		||||
    <div class="h-full">
 | 
			
		||||
        <ResourceOpPanel @resized="onResizeTagTree">
 | 
			
		||||
            <template #left>
 | 
			
		||||
                <tag-tree
 | 
			
		||||
                    class="machine-terminal-tree"
 | 
			
		||||
                    ref="tagTreeRef"
 | 
			
		||||
                    :resource-type="TagResourceTypePath.MachineAuthCert"
 | 
			
		||||
                    :tag-path-node-type="NodeTypeTagPath"
 | 
			
		||||
@@ -34,7 +33,7 @@
 | 
			
		||||
            <template #right>
 | 
			
		||||
                <el-card class="h-full" body-class="machine-terminal-tabs h-full !p-1 flex flex-col flex-1">
 | 
			
		||||
                    <el-tabs v-if="state.tabs.size > 0" type="card" @tab-remove="onRemoveTab" v-model="state.activeTermName" class="!h-full w-full">
 | 
			
		||||
                        <el-tab-pane class="!h-full" closable v-for="dt in state.tabs.values()" :label="dt.label" :name="dt.key" :key="dt.key">
 | 
			
		||||
                        <el-tab-pane class="!h-full flex flex-col" closable v-for="dt in state.tabs.values()" :label="dt.label" :name="dt.key" :key="dt.key">
 | 
			
		||||
                            <template #label>
 | 
			
		||||
                                <el-popconfirm @confirm="handleReconnect(dt, true)" :title="$t('machine.reConnTips')">
 | 
			
		||||
                                    <template #reference>
 | 
			
		||||
@@ -63,7 +62,7 @@
 | 
			
		||||
                                </el-popover>
 | 
			
		||||
                            </template>
 | 
			
		||||
 | 
			
		||||
                            <div :ref="(el: any) => setTerminalWrapperRef(el, dt.key)" class="terminal-wrapper" style="height: calc(100vh - 155px)">
 | 
			
		||||
                            <div :ref="(el: any) => setTerminalWrapperRef(el, dt.key)" class="terminal-wrapper flex-1 h-[calc(100vh-155px)]">
 | 
			
		||||
                                <TerminalBody
 | 
			
		||||
                                    v-if="dt.params.protocol == MachineProtocolEnum.Ssh.value"
 | 
			
		||||
                                    :mount-init="false"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="mock-data-dialog">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :title="title"
 | 
			
		||||
            v-model="dialogVisible"
 | 
			
		||||
@@ -35,8 +35,8 @@
 | 
			
		||||
                    <dynamic-form-edit v-model="params" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
 | 
			
		||||
                <el-form-item required prop="script" class="100w">
 | 
			
		||||
                    <div style="width: 100%">
 | 
			
		||||
                <el-form-item required prop="script">
 | 
			
		||||
                    <div class="w-full">
 | 
			
		||||
                        <monaco-editor v-model="form.script" language="shell" height="300px" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
@@ -66,9 +66,6 @@ import { useI18nFormValidate, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
 | 
			
		||||
import { Rules } from '@/common/rule';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    data: {
 | 
			
		||||
        type: Object,
 | 
			
		||||
    },
 | 
			
		||||
@@ -83,7 +80,9 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'submitSuccess']);
 | 
			
		||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['cancel', 'submitSuccess']);
 | 
			
		||||
 | 
			
		||||
const rules = {
 | 
			
		||||
    name: [Rules.requiredInput('common.name')],
 | 
			
		||||
@@ -96,7 +95,6 @@ const { isCommon, machineId } = toRefs(props);
 | 
			
		||||
const scriptForm: any = ref(null);
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    params: [] as any,
 | 
			
		||||
    form: {
 | 
			
		||||
        id: null,
 | 
			
		||||
@@ -110,11 +108,10 @@ const state = reactive({
 | 
			
		||||
    btnLoading: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, params, form, btnLoading } = toRefs(state);
 | 
			
		||||
const { params, form, btnLoading } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(props, (newValue: any) => {
 | 
			
		||||
    state.dialogVisible = newValue.visible;
 | 
			
		||||
    if (!newValue.visible) {
 | 
			
		||||
    if (!dialogVisible.value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (newValue.data) {
 | 
			
		||||
@@ -142,7 +139,7 @@ const btnOk = async () => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    dialogVisible.value = false;
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
    state.params = [];
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="file-manage">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            @open="getScripts()"
 | 
			
		||||
            :title="title"
 | 
			
		||||
@@ -68,10 +68,11 @@
 | 
			
		||||
            :close-on-click-modal="false"
 | 
			
		||||
            :modal="false"
 | 
			
		||||
            @close="closeTermnial"
 | 
			
		||||
            body-class="h-[560px]"
 | 
			
		||||
            draggable
 | 
			
		||||
            append-to-body
 | 
			
		||||
        >
 | 
			
		||||
            <TerminalBody ref="terminal" :cmd="terminalDialog.cmd" :socket-url="getMachineTerminalSocketUrl(props.authCertName)" height="560px" />
 | 
			
		||||
            <TerminalBody ref="terminal" :cmd="terminalDialog.cmd" :socket-url="getMachineTerminalSocketUrl(props.authCertName)" />
 | 
			
		||||
        </el-dialog>
 | 
			
		||||
 | 
			
		||||
        <script-edit
 | 
			
		||||
@@ -86,7 +87,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { ref, toRefs, reactive, watch, Ref } from 'vue';
 | 
			
		||||
import { ref, toRefs, reactive, Ref } from 'vue';
 | 
			
		||||
import { ElMessage } from 'element-plus';
 | 
			
		||||
import TerminalBody from '@/components/terminal/TerminalBody.vue';
 | 
			
		||||
import { getMachineTerminalSocketUrl, machineApi } from './api';
 | 
			
		||||
@@ -102,19 +103,19 @@ import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI
 | 
			
		||||
const { t } = useI18n();
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: { type: Boolean },
 | 
			
		||||
    machineId: { type: Number },
 | 
			
		||||
    authCertName: { type: String },
 | 
			
		||||
    title: { type: String },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
 | 
			
		||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['cancel', 'update:machineId']);
 | 
			
		||||
 | 
			
		||||
const paramsForm: any = ref(null);
 | 
			
		||||
const pageTableRef: Ref<any> = ref(null);
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    selectionData: [],
 | 
			
		||||
    searchItems: [SearchItem.select('type', 'common.type').withEnum(ScriptTypeEnum)],
 | 
			
		||||
    columns: [
 | 
			
		||||
@@ -151,11 +152,7 @@ const state = reactive({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, columns, selectionData, query, editDialog, scriptParamsDialog, resultDialog, terminalDialog } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(props, async (newValue) => {
 | 
			
		||||
    state.dialogVisible = newValue.visible;
 | 
			
		||||
});
 | 
			
		||||
const { columns, selectionData, query, editDialog, scriptParamsDialog, resultDialog, terminalDialog } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
const getScripts = async () => {
 | 
			
		||||
    pageTableRef.value.search();
 | 
			
		||||
@@ -271,7 +268,7 @@ const deleteRow = async (rows: any) => {
 | 
			
		||||
 * 关闭取消按钮触发的事件
 | 
			
		||||
 */
 | 
			
		||||
const handleClose = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    dialogVisible.value = false;
 | 
			
		||||
    emit('update:machineId', null);
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
    state.query.type = ScriptTypeEnum.Private.value;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="file-manage">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog v-if="dialogVisible" :title="title" v-model="dialogVisible" :show-close="true" :before-close="handleClose" width="50%">
 | 
			
		||||
            <el-table :data="fileTable" stripe style="width: 100%" v-loading="loading">
 | 
			
		||||
            <el-table :data="fileTable" stripe v-loading="loading">
 | 
			
		||||
                <el-table-column prop="name" :label="$t('common.name')" min-width="100px">
 | 
			
		||||
                    <template #header>
 | 
			
		||||
                        <el-button class="ml0" type="primary" circle size="small" icon="Plus" @click="add()"> </el-button>
 | 
			
		||||
@@ -29,9 +29,8 @@
 | 
			
		||||
                    </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
            </el-table>
 | 
			
		||||
            <el-row style="margin-top: 10px" type="flex" justify="end">
 | 
			
		||||
            <el-row class="mt-2" type="flex" justify="end">
 | 
			
		||||
                <el-pagination
 | 
			
		||||
                    style="text-align: center"
 | 
			
		||||
                    :total="total"
 | 
			
		||||
                    layout="prev, pager, next, total, jumper"
 | 
			
		||||
                    v-model:current-page="query.pageNum"
 | 
			
		||||
@@ -41,7 +40,7 @@
 | 
			
		||||
                </el-pagination>
 | 
			
		||||
            </el-row>
 | 
			
		||||
 | 
			
		||||
            <el-dialog destroy-on-close :title="fileDialog.title" v-model="fileDialog.visible" :close-on-click-modal="false" width="70%">
 | 
			
		||||
            <el-drawer destroy-on-close :title="fileDialog.title" v-model="fileDialog.visible" :close-on-click-modal="false" size="70%" header-class="!mb-0">
 | 
			
		||||
                <machine-file
 | 
			
		||||
                    :title="fileDialog.title"
 | 
			
		||||
                    :machine-id="machineId"
 | 
			
		||||
@@ -50,7 +49,7 @@
 | 
			
		||||
                    :path="fileDialog.path"
 | 
			
		||||
                    :protocol="protocol"
 | 
			
		||||
                />
 | 
			
		||||
            </el-dialog>
 | 
			
		||||
            </el-drawer>
 | 
			
		||||
 | 
			
		||||
            <machine-file-content
 | 
			
		||||
                :title="fileContent.title"
 | 
			
		||||
@@ -66,33 +65,29 @@
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { reactive, toRefs, watch } from 'vue';
 | 
			
		||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
			
		||||
import { machineApi } from '../api';
 | 
			
		||||
import { FileTypeEnum } from '../enums';
 | 
			
		||||
import MachineFile from './MachineFile.vue';
 | 
			
		||||
import MachineFileContent from './MachineFileContent.vue';
 | 
			
		||||
import { useI18n } from 'vue-i18n';
 | 
			
		||||
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
 | 
			
		||||
import { useI18nDeleteConfirm, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n();
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: { type: Boolean },
 | 
			
		||||
    protocol: { type: Number, default: 1 },
 | 
			
		||||
    machineId: { type: Number },
 | 
			
		||||
    authCertName: { type: String },
 | 
			
		||||
    title: { type: String },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
 | 
			
		||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['cancel', 'update:machineId']);
 | 
			
		||||
 | 
			
		||||
const addFile = machineApi.addConf;
 | 
			
		||||
const delFile = machineApi.delConf;
 | 
			
		||||
const files = machineApi.files;
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    query: {
 | 
			
		||||
        id: 0,
 | 
			
		||||
        pageNum: 1,
 | 
			
		||||
@@ -122,11 +117,10 @@ const state = reactive({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, loading, query, total, fileTable, fileDialog, fileContent } = toRefs(state);
 | 
			
		||||
const { loading, query, total, fileTable, fileDialog, fileContent } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(props, async (newValue) => {
 | 
			
		||||
    state.dialogVisible = newValue.visible;
 | 
			
		||||
    if (newValue.machineId && newValue.visible) {
 | 
			
		||||
    if (newValue.machineId && dialogVisible.value) {
 | 
			
		||||
        await getFiles();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -198,28 +192,10 @@ const showFileContent = async (fileId: number, path: string) => {
 | 
			
		||||
 * 关闭取消按钮触发的事件
 | 
			
		||||
 */
 | 
			
		||||
const handleClose = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    dialogVisible.value = false;
 | 
			
		||||
    emit('update:machineId', null);
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
    state.fileTable = [];
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.machine-file-upload-exec {
 | 
			
		||||
    display: inline-flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
.inline-block {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
.margin-change {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<style lang="scss"></style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="machine-file">
 | 
			
		||||
        <div>
 | 
			
		||||
            <el-progress v-if="uploadProgressShow" style="width: 90%; margin-left: 20px" :text-inside="true" :stroke-width="20" :percentage="progressNum" />
 | 
			
		||||
    <div class="machine-file h-full">
 | 
			
		||||
        <div class="h-full flex flex-col">
 | 
			
		||||
            <!-- 文件上传进度条 -->
 | 
			
		||||
            <el-progress v-if="uploadProgressShow" class="ml-4 w-[90%]" :text-inside="true" :stroke-width="20" :percentage="progressNum" />
 | 
			
		||||
 | 
			
		||||
            <el-row class="mb-2">
 | 
			
		||||
            <!-- 文件路径 -->
 | 
			
		||||
            <el-row class="mb-2 ml-4">
 | 
			
		||||
                <el-breadcrumb separator-icon="ArrowRight">
 | 
			
		||||
                    <el-breadcrumb-item v-for="path in filePathNav" :key="path">
 | 
			
		||||
                        <el-link @click="setFiles(path.path)" style="font-weight: bold">{{ path.name }}</el-link>
 | 
			
		||||
@@ -11,17 +13,20 @@
 | 
			
		||||
                </el-breadcrumb>
 | 
			
		||||
            </el-row>
 | 
			
		||||
 | 
			
		||||
            <!-- 文件列表 -->
 | 
			
		||||
            <div class="flex-1 overflow-auto">
 | 
			
		||||
                <el-table
 | 
			
		||||
                    ref="fileTableRef"
 | 
			
		||||
                    @cell-dblclick="cellDbclick"
 | 
			
		||||
                    @selection-change="handleSelectionChange"
 | 
			
		||||
                height="65vh"
 | 
			
		||||
                    height="100%"
 | 
			
		||||
                    :data="filterFiles"
 | 
			
		||||
                    highlight-current-row
 | 
			
		||||
                    v-loading="loading"
 | 
			
		||||
                >
 | 
			
		||||
                    <el-table-column type="selection" width="30" />
 | 
			
		||||
 | 
			
		||||
                    <!-- 文件名 -->
 | 
			
		||||
                    <el-table-column prop="name" :label="$t('common.name')" min-width="380">
 | 
			
		||||
                        <template #header>
 | 
			
		||||
                            <div class="machine-file-table-header">
 | 
			
		||||
@@ -144,7 +149,7 @@
 | 
			
		||||
                                    </el-button-group>
 | 
			
		||||
                                </div>
 | 
			
		||||
 | 
			
		||||
                            <div style="width: 150px">
 | 
			
		||||
                                <div class="w-[150px]">
 | 
			
		||||
                                    <el-input v-model="fileNameFilter" size="small" :placeholder="$t('machine.fileNameFilterPlaceholder')" clearable />
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
@@ -158,7 +163,7 @@
 | 
			
		||||
                                <SvgIcon :size="15" :name="scope.row.icon" />
 | 
			
		||||
                            </span>
 | 
			
		||||
 | 
			
		||||
                        <span class="!ml-1" style="display: inline-block; width: 90%">
 | 
			
		||||
                            <span class="!ml-1 inline-block w-[90%]">
 | 
			
		||||
                                <div v-if="scope.row.nameEdit">
 | 
			
		||||
                                    <el-input
 | 
			
		||||
                                        @keyup.enter="fileRename(scope.row)"
 | 
			
		||||
@@ -200,7 +205,7 @@
 | 
			
		||||
 | 
			
		||||
                    <el-table-column prop="modTime" :label="$t('machine.modificationTime')" width="160" sortable> </el-table-column>
 | 
			
		||||
 | 
			
		||||
                <el-table-column :width="130">
 | 
			
		||||
                    <el-table-column :width="100">
 | 
			
		||||
                        <template #header>
 | 
			
		||||
                            <el-popover placement="top" :width="270" trigger="hover">
 | 
			
		||||
                                <template #reference>
 | 
			
		||||
@@ -210,28 +215,10 @@
 | 
			
		||||
                            </el-popover>
 | 
			
		||||
                            {{ $t('common.operation') }}
 | 
			
		||||
                        </template>
 | 
			
		||||
 | 
			
		||||
                        <template #default="scope">
 | 
			
		||||
                        <el-link
 | 
			
		||||
                            @click="deleteFile([scope.row])"
 | 
			
		||||
                            v-if="!dontOperate(scope.row)"
 | 
			
		||||
                            v-auth="'machine:file:rm'"
 | 
			
		||||
                            type="danger"
 | 
			
		||||
                            icon="delete"
 | 
			
		||||
                            :underline="false"
 | 
			
		||||
                            :title="$t('common.delete')"
 | 
			
		||||
                        ></el-link>
 | 
			
		||||
 | 
			
		||||
                        <el-link
 | 
			
		||||
                            @click="downloadFile(scope.row)"
 | 
			
		||||
                            v-if="scope.row.type == '-'"
 | 
			
		||||
                            v-auth="'machine:file:write'"
 | 
			
		||||
                            type="primary"
 | 
			
		||||
                            icon="download"
 | 
			
		||||
                            :underline="false"
 | 
			
		||||
                            class="ml-2"
 | 
			
		||||
                            :title="$t('machine.download')"
 | 
			
		||||
                        ></el-link>
 | 
			
		||||
 | 
			
		||||
                            <div class="flex gap-1.5">
 | 
			
		||||
                                <!-- 基础信息 -->
 | 
			
		||||
                                <el-popover
 | 
			
		||||
                                    placement="top-start"
 | 
			
		||||
                                    :title="`${scope.row.path} - ${$t('machine.fileDetail')}`"
 | 
			
		||||
@@ -246,17 +233,40 @@
 | 
			
		||||
                                                icon="InfoFilled"
 | 
			
		||||
                                                :underline="false"
 | 
			
		||||
                                                link
 | 
			
		||||
                                        class="ml-2"
 | 
			
		||||
                                                :loading="scope.row.loadingStat"
 | 
			
		||||
                                            ></el-link>
 | 
			
		||||
                                        </span>
 | 
			
		||||
                                    </template>
 | 
			
		||||
                                    <el-input disabled autosize v-model="scope.row.stat" type="textarea" />
 | 
			
		||||
                                </el-popover>
 | 
			
		||||
 | 
			
		||||
                                <!-- 下载文件 -->
 | 
			
		||||
                                <el-link
 | 
			
		||||
                                    @click="downloadFile(scope.row)"
 | 
			
		||||
                                    v-if="scope.row.type == '-'"
 | 
			
		||||
                                    v-auth="'machine:file:write'"
 | 
			
		||||
                                    type="primary"
 | 
			
		||||
                                    icon="download"
 | 
			
		||||
                                    :underline="false"
 | 
			
		||||
                                    :title="$t('machine.download')"
 | 
			
		||||
                                ></el-link>
 | 
			
		||||
 | 
			
		||||
                                <!-- 删除文件 -->
 | 
			
		||||
                                <el-link
 | 
			
		||||
                                    @click="deleteFile([scope.row])"
 | 
			
		||||
                                    v-if="!dontOperate(scope.row)"
 | 
			
		||||
                                    v-auth="'machine:file:rm'"
 | 
			
		||||
                                    type="danger"
 | 
			
		||||
                                    icon="delete"
 | 
			
		||||
                                    :underline="false"
 | 
			
		||||
                                    :title="$t('common.delete')"
 | 
			
		||||
                                ></el-link>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </template>
 | 
			
		||||
                    </el-table-column>
 | 
			
		||||
                </el-table>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :destroy-on-close="true"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="machine-file-content">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            destroy-on-close
 | 
			
		||||
            :before-close="handleClose"
 | 
			
		||||
@@ -9,28 +9,25 @@
 | 
			
		||||
            top="5vh"
 | 
			
		||||
            width="65%"
 | 
			
		||||
        >
 | 
			
		||||
            <div>
 | 
			
		||||
                <monaco-editor :can-change-mode="true" v-model="content" :language="fileType" />
 | 
			
		||||
            <div v-loading="loadingContent">
 | 
			
		||||
                <monaco-editor :can-change-mode="true" v-model="fileContent" :language="fileType" />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <template #footer>
 | 
			
		||||
                <div class="dialog-footer">
 | 
			
		||||
                <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
 | 
			
		||||
                <el-button v-auth="'machine:file:write'" type="primary" @click="updateContent">{{ $t('common.save') }}</el-button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </template>
 | 
			
		||||
        </el-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { reactive, toRefs, watch } from 'vue';
 | 
			
		||||
import { computed, reactive, toRefs, watch } from 'vue';
 | 
			
		||||
import { machineApi } from '../api';
 | 
			
		||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
 | 
			
		||||
import { useI18nSaveSuccessMsg } from '@/hooks/useI18n';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: { type: Boolean, default: false },
 | 
			
		||||
    protocol: { type: Number, default: 1 },
 | 
			
		||||
    title: { type: String, default: '' },
 | 
			
		||||
    machineId: { type: Number },
 | 
			
		||||
@@ -39,41 +36,50 @@ const props = defineProps({
 | 
			
		||||
    path: { type: String, default: '' },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
 | 
			
		||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['cancel', 'update:machineId']);
 | 
			
		||||
 | 
			
		||||
const updateFileContent = machineApi.updateFileContent;
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    loadingContent: false,
 | 
			
		||||
    content: '',
 | 
			
		||||
    fileType: '',
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, content, fileType } = toRefs(state);
 | 
			
		||||
const { fileType } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(props, async (newValue) => {
 | 
			
		||||
    if (newValue.visible) {
 | 
			
		||||
        await getFileContent();
 | 
			
		||||
    }
 | 
			
		||||
    state.dialogVisible = newValue.visible;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const getFileContent = async () => {
 | 
			
		||||
    const path = props.path;
 | 
			
		||||
    const res = await machineApi.fileContent.request({
 | 
			
		||||
const {
 | 
			
		||||
    isFetching: loadingContent,
 | 
			
		||||
    execute: getFileContentExec,
 | 
			
		||||
    data: fileContent,
 | 
			
		||||
} = machineApi.fileContent.useApi(
 | 
			
		||||
    computed(() => {
 | 
			
		||||
        return {
 | 
			
		||||
            fileId: props.fileId,
 | 
			
		||||
        path,
 | 
			
		||||
            path: props.path,
 | 
			
		||||
            machineId: props.machineId,
 | 
			
		||||
            authCertName: props.authCertName,
 | 
			
		||||
            protocol: props.protocol,
 | 
			
		||||
        };
 | 
			
		||||
    })
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
watch(props, async (newValue) => {
 | 
			
		||||
    if (dialogVisible.value) {
 | 
			
		||||
        await getFileContent();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
    state.fileType = getFileType(path);
 | 
			
		||||
    state.content = res;
 | 
			
		||||
 | 
			
		||||
const getFileContent = async () => {
 | 
			
		||||
    fileContent.value = '';
 | 
			
		||||
    state.fileType = getFileType(props.path);
 | 
			
		||||
    await getFileContentExec();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleClose = () => {
 | 
			
		||||
    state.dialogVisible = false;
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    dialogVisible.value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const updateContent = async () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="redis-data-op flex-all-center h-full">
 | 
			
		||||
    <div class="redis-data-op h-full">
 | 
			
		||||
        <ResourceOpPanel>
 | 
			
		||||
            <template #left>
 | 
			
		||||
                <tag-tree
 | 
			
		||||
@@ -144,9 +144,9 @@
 | 
			
		||||
                    </Pane>
 | 
			
		||||
 | 
			
		||||
                    <Pane>
 | 
			
		||||
                        <div class="h-full card !p-1">
 | 
			
		||||
                            <el-tabs @tab-remove="removeDataTab" v-model="state.activeName">
 | 
			
		||||
                                <el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
 | 
			
		||||
                        <div class="h-full card !p-1 key-deatil">
 | 
			
		||||
                            <el-tabs class="h-full" @tab-remove="removeDataTab" v-model="state.activeName">
 | 
			
		||||
                                <el-tab-pane class="h-full" closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
 | 
			
		||||
                                    <key-detail :redis="redisInst" :key-info="dt.keyInfo" @change-key="searchKey()" @del-key="delKey" />
 | 
			
		||||
                                </el-tab-pane>
 | 
			
		||||
                            </el-tabs>
 | 
			
		||||
@@ -614,6 +614,18 @@ const delKey = async (key: string) => {
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.key-deatil {
 | 
			
		||||
    .el-tabs__header {
 | 
			
		||||
        background-color: var(--el-color-white);
 | 
			
		||||
        border-bottom: 1px solid var(--el-border-color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ::v-deep(.el-tabs__item) {
 | 
			
		||||
        padding: 0 10px;
 | 
			
		||||
        height: 29px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.redis-data-op {
 | 
			
		||||
    .key-list-vtree .folder-label {
 | 
			
		||||
        font-weight: bold;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="format-viewer-container">
 | 
			
		||||
        <div class="mb-1 float-right">
 | 
			
		||||
        <div class="mb-1 flex justify-end">
 | 
			
		||||
            <el-select v-model="selectedView" class="format-selector" size="small" placeholder="Text">
 | 
			
		||||
                <template #prefix>
 | 
			
		||||
                    <SvgIcon name="view" />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,10 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-container direction="vertical" class="key-tab-container">
 | 
			
		||||
    <div class="flex flex-col h-full">
 | 
			
		||||
        <!-- key info -->
 | 
			
		||||
            <key-header
 | 
			
		||||
                ref="keyHeader"
 | 
			
		||||
                :redis="props.redis"
 | 
			
		||||
                :key-info="state.keyInfo"
 | 
			
		||||
                @refresh-content="refreshContent"
 | 
			
		||||
                @del-key="delKey"
 | 
			
		||||
                @change-key="changeKey"
 | 
			
		||||
                class="key-header-info"
 | 
			
		||||
            >
 | 
			
		||||
            </key-header>
 | 
			
		||||
        <key-header :redis="props.redis" :key-info="state.keyInfo" @refresh-content="refreshContent" @del-key="delKey" @change-key="changeKey"> </key-header>
 | 
			
		||||
 | 
			
		||||
            <!-- key content -->
 | 
			
		||||
            <component ref="keyValueRef" :is="components[componentName]" :redis="props.redis" :key-info="keyInfo"> </component>
 | 
			
		||||
        </el-container>
 | 
			
		||||
        <!-- key content , 暂不懂为啥要用h-0或者其他随便设个高度?,h-full就是不行会导致loadMore按钮不显示 -->
 | 
			
		||||
        <component class="h-0 flex-1" ref="keyValueRef" :is="components[componentName]" :redis="props.redis" :key-info="keyInfo"> </component>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
@@ -106,24 +95,10 @@ onMounted(() => {
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.key-tab-container {
 | 
			
		||||
    /*padding-left: 5px;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.key-header-info {
 | 
			
		||||
    // margin-top: 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.key-content-container {
 | 
			
		||||
    margin-top: 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// .key-detail-filter-value {
 | 
			
		||||
//     width: 90%;
 | 
			
		||||
//     height: 24px;
 | 
			
		||||
//     padding: 0 5px;
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
/*tooltip in table width limit*/
 | 
			
		||||
.el-tooltip__popper {
 | 
			
		||||
    max-width: 50%;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
    <div class="flex">
 | 
			
		||||
        <!-- key name -->
 | 
			
		||||
        <div class="key-header-item key-name-input">
 | 
			
		||||
            <el-input ref="keyNameInput" v-model="ki.key" :title="$t('redis.renameTips')" placeholder="KeyName">
 | 
			
		||||
@@ -180,12 +180,6 @@ const ttlConveter = (ttl: any) => {
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.key-header-item {
 | 
			
		||||
    /*padding-right: 15px;*/
 | 
			
		||||
    /*margin-bottom: 10px;*/
 | 
			
		||||
    float: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.key-header-item.key-name-input {
 | 
			
		||||
    width: calc(100% - 322px);
 | 
			
		||||
    min-width: 230px;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,16 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="flex flex-col">
 | 
			
		||||
        <div>
 | 
			
		||||
            <el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
 | 
			
		||||
        <el-table size="small" border :data="hashValues" height="500" min-height="300" stripe>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="flex-1 overflow-auto">
 | 
			
		||||
            <el-table size="small" border :data="hashValues" height="100%" stripe>
 | 
			
		||||
                <el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
 | 
			
		||||
                <el-table-column resizable sortable prop="field" label="field" show-overflow-tooltip min-width="100"> </el-table-column>
 | 
			
		||||
                <el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
 | 
			
		||||
                <el-table-column :label="$t('common.operation')">
 | 
			
		||||
                    <template #header>
 | 
			
		||||
                        <el-input
 | 
			
		||||
                        class="key-detail-filter-value"
 | 
			
		||||
                            v-model="state.filterValue"
 | 
			
		||||
                            @keyup.enter="hscan(true, true)"
 | 
			
		||||
                            :placeholder="$t('redis.filterPlaceholder')"
 | 
			
		||||
@@ -26,12 +28,20 @@
 | 
			
		||||
                    </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
            </el-table>
 | 
			
		||||
        </div>
 | 
			
		||||
        <!-- load more content -->
 | 
			
		||||
        <div class="content-more-container">
 | 
			
		||||
            <el-button size="small" @click="hscan()" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :title="$t('redis.addNewLine')"
 | 
			
		||||
            v-model="editDialog.visible"
 | 
			
		||||
            width="600px"
 | 
			
		||||
            :destroy-on-close="true"
 | 
			
		||||
            :close-on-click-modal="false"
 | 
			
		||||
            body-class="p-1"
 | 
			
		||||
        >
 | 
			
		||||
            <el-form>
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                    <el-input v-model="editDialog.field" placeholder="field" />
 | 
			
		||||
@@ -42,7 +52,7 @@
 | 
			
		||||
            </el-form>
 | 
			
		||||
 | 
			
		||||
            <template #footer>
 | 
			
		||||
                <div class="dialog-footer">
 | 
			
		||||
                <div>
 | 
			
		||||
                    <el-button @click="editDialog.visible = false">{{ $t('common.cancel') }}</el-button>
 | 
			
		||||
                    <el-button v-auth="'redis:data:save'" type="primary" @click="confirmEditData">{{ $t('common.confirm') }}</el-button>
 | 
			
		||||
                </div>
 | 
			
		||||
@@ -168,18 +178,4 @@ const confirmEditData = async () => {
 | 
			
		||||
 | 
			
		||||
defineExpose({ initData });
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
#string-value-text {
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    position: relative;
 | 
			
		||||
 | 
			
		||||
    .text-type-select {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        z-index: 2;
 | 
			
		||||
        right: 10px;
 | 
			
		||||
        top: 10px;
 | 
			
		||||
        max-width: 70px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<style lang="scss"></style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,10 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="flex flex-col">
 | 
			
		||||
        <div>
 | 
			
		||||
            <el-button @click="showEditDialog(null, -1)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
 | 
			
		||||
        <el-table size="small" border :data="values" height="450" min-height="300" stripe>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="flex-1 overflow-auto">
 | 
			
		||||
            <el-table size="small" border :data="values" height="100%" stripe>
 | 
			
		||||
                <el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
 | 
			
		||||
                <el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
 | 
			
		||||
                <el-table-column :label="$t('common.operation')">
 | 
			
		||||
@@ -15,12 +18,20 @@
 | 
			
		||||
                    </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
            </el-table>
 | 
			
		||||
        </div>
 | 
			
		||||
        <!-- load more content -->
 | 
			
		||||
        <div class="content-more-container">
 | 
			
		||||
            <el-button size="small" @click="getListValue(false)" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :title="$t('redis.addNewLine')"
 | 
			
		||||
            v-model="editDialog.visible"
 | 
			
		||||
            width="600px"
 | 
			
		||||
            :destroy-on-close="true"
 | 
			
		||||
            :close-on-click-modal="false"
 | 
			
		||||
            body-class="p-1"
 | 
			
		||||
        >
 | 
			
		||||
            <el-form>
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                    <format-viewer class="!w-full" ref="formatViewerRef" :content="editDialog.content"></format-viewer>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="flex flex-col">
 | 
			
		||||
        <div>
 | 
			
		||||
            <el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
 | 
			
		||||
        <el-table size="small" border :data="setDatas" height="450" min-height="300" stripe>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="flex-1 overflow-auto">
 | 
			
		||||
            <el-table size="small" border :data="setDatas" height="100%" stripe>
 | 
			
		||||
                <el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
 | 
			
		||||
                <el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
 | 
			
		||||
                <el-table-column :label="$t('common.operation')">
 | 
			
		||||
                    <template #header>
 | 
			
		||||
                        <el-input
 | 
			
		||||
                        class="key-detail-filter-value"
 | 
			
		||||
                            v-model="state.filterValue"
 | 
			
		||||
                            @keyup.enter="sscanData(true, true)"
 | 
			
		||||
                            :placeholder="$t('redis.filterPlaceholder')"
 | 
			
		||||
@@ -25,12 +27,20 @@
 | 
			
		||||
                    </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
            </el-table>
 | 
			
		||||
        </div>
 | 
			
		||||
        <!-- load more content -->
 | 
			
		||||
        <div class="content-more-container">
 | 
			
		||||
            <el-button size="small" @click="sscanData(false)" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :title="$t('redis.addNewLine')"
 | 
			
		||||
            v-model="editDialog.visible"
 | 
			
		||||
            width="600px"
 | 
			
		||||
            :destroy-on-close="true"
 | 
			
		||||
            :close-on-click-modal="false"
 | 
			
		||||
            body-class="p-1"
 | 
			
		||||
        >
 | 
			
		||||
            <el-form>
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                    <format-viewer class="!w-full" ref="formatViewerRef" :content="editDialog.content"></format-viewer>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-form class="key-content-string" label-width="auto">
 | 
			
		||||
            <div>
 | 
			
		||||
                <format-viewer ref="formatViewerRef" height="250px" :content="string.value"></format-viewer>
 | 
			
		||||
            </div>
 | 
			
		||||
    <div class="flex flex-col h-full">
 | 
			
		||||
        <el-form label-width="auto">
 | 
			
		||||
            <format-viewer ref="formatViewerRef" height="280px" :content="string.value"></format-viewer>
 | 
			
		||||
        </el-form>
 | 
			
		||||
        <div class="!mt-2 float-right">
 | 
			
		||||
        <div class="mt-2 flex justify-end">
 | 
			
		||||
            <el-button @click="saveValue" type="primary" v-auth="'redis:data:save'">{{ $t('common.save') }}</el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -89,19 +87,4 @@ const saveValue = async () => {
 | 
			
		||||
 | 
			
		||||
defineExpose({ initData });
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
// .key-content-string .format-viewer-container {
 | 
			
		||||
//     min-height: calc(100vh - 253px);
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// /*text viewer box*/
 | 
			
		||||
// .key-content-string .el-textarea textarea {
 | 
			
		||||
//     font-size: 14px;
 | 
			
		||||
//     height: calc(100vh - 436px);
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// /*json in monaco editor*/
 | 
			
		||||
// .key-content-string .monaco-editor-content {
 | 
			
		||||
//     height: calc(100vh - 450px) !important;
 | 
			
		||||
// }
 | 
			
		||||
</style>
 | 
			
		||||
<style lang="scss"></style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,17 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="flex flex-col">
 | 
			
		||||
        <div>
 | 
			
		||||
            <el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
 | 
			
		||||
        <el-table size="small" border :data="values" height="450" min-height="300" stripe>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="flex-1 overflow-auto">
 | 
			
		||||
            <el-table size="small" border :data="values" height="100%" stripe>
 | 
			
		||||
                <el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
 | 
			
		||||
                <el-table-column resizable sortable prop="score" label="score" show-overflow-tooltip min-width="100"> </el-table-column>
 | 
			
		||||
                <el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
 | 
			
		||||
                <el-table-column :label="$t('common.operation')">
 | 
			
		||||
                    <template #header>
 | 
			
		||||
                        <el-input
 | 
			
		||||
                        class="key-detail-filter-value"
 | 
			
		||||
                            v-model="state.filterValue"
 | 
			
		||||
                            @keyup.enter="zscanData(true)"
 | 
			
		||||
                            :placeholder="$t('redis.filterPlaceholder')"
 | 
			
		||||
@@ -26,12 +29,20 @@
 | 
			
		||||
                    </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
            </el-table>
 | 
			
		||||
        </div>
 | 
			
		||||
        <!-- load more content -->
 | 
			
		||||
        <div class="content-more-container">
 | 
			
		||||
            <el-button size="small" @click="loadDatas()" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :title="$t('redis.addNewLine')"
 | 
			
		||||
            v-model="editDialog.visible"
 | 
			
		||||
            width="600px"
 | 
			
		||||
            :destroy-on-close="true"
 | 
			
		||||
            :close-on-click-modal="false"
 | 
			
		||||
            body-class="p-1"
 | 
			
		||||
        >
 | 
			
		||||
            <el-form>
 | 
			
		||||
                <el-form-item>
 | 
			
		||||
                    <el-input type="number" v-model.number="editDialog.score" placeholder="score" />
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
                </div>
 | 
			
		||||
                <el-scrollbar class="tag-tree-data">
 | 
			
		||||
                    <el-tree
 | 
			
		||||
                        class="min-w-full inline-block"
 | 
			
		||||
                        ref="tagTreeRef"
 | 
			
		||||
                        node-key="id"
 | 
			
		||||
                        highlight-current
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="account-dialog">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog :title="title" v-model="visible" :before-close="cancel" :show-close="false" width="600px" :destroy-on-close="true">
 | 
			
		||||
            <el-form :model="form" ref="accountForm" :rules="rules" label-width="auto">
 | 
			
		||||
                <el-form-item prop="name" :label="$t('system.account.name')">
 | 
			
		||||
@@ -73,7 +73,7 @@ const props = defineProps({
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change']);
 | 
			
		||||
 | 
			
		||||
const visible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-drawer :title="title" v-model="dvisible" :show-close="false" :before-close="cancel" size="1000px" :destroy-on-close="true">
 | 
			
		||||
        <el-drawer :title="title" v-model="visible" :show-close="false" :before-close="cancel" size="1000px" :destroy-on-close="true">
 | 
			
		||||
            <template #header>
 | 
			
		||||
                <DrawerHeader :header="title" :back="cancel" />
 | 
			
		||||
            </template>
 | 
			
		||||
@@ -14,7 +14,6 @@
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item prop="permission" :label="$t('system.sysconf.permission')">
 | 
			
		||||
                    <el-select
 | 
			
		||||
                        style="width: 100%"
 | 
			
		||||
                        remote
 | 
			
		||||
                        :remote-method="getAccount"
 | 
			
		||||
                        v-model="state.permissionAccount"
 | 
			
		||||
@@ -58,9 +57,6 @@ const rules = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    data: {
 | 
			
		||||
        type: [Boolean, Object],
 | 
			
		||||
    },
 | 
			
		||||
@@ -69,13 +65,14 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const visible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change']);
 | 
			
		||||
 | 
			
		||||
const configForm: any = ref(null);
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dvisible: false,
 | 
			
		||||
    params: [] as any,
 | 
			
		||||
    accounts: [] as any,
 | 
			
		||||
    permissionAccount: [] as any,
 | 
			
		||||
@@ -90,15 +87,12 @@ const state = reactive({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dvisible, params, form } = toRefs(state);
 | 
			
		||||
const { params, form } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
const { isFetching: saveBtnLoading, execute: saveConfigExec } = configApi.save.useApi(form);
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
    () => props.visible,
 | 
			
		||||
    () => {
 | 
			
		||||
        state.dvisible = props.visible;
 | 
			
		||||
        if (!state.dvisible) {
 | 
			
		||||
watch(visible, () => {
 | 
			
		||||
    if (!visible.value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -120,12 +114,10 @@ watch(
 | 
			
		||||
    } else {
 | 
			
		||||
        state.permissionAccount = [];
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    // 更新父组件visible prop对应的值为false
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    visible.value = false;
 | 
			
		||||
    // 若父组件有取消事件,则调用
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
    state.permissionAccount = [];
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,6 @@
 | 
			
		||||
import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
			
		||||
import ConfigEdit from './ConfigEdit.vue';
 | 
			
		||||
import { configApi } from '../api';
 | 
			
		||||
import { ElMessage } from 'element-plus';
 | 
			
		||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
			
		||||
import { TableColumn } from '@/components/pagetable';
 | 
			
		||||
import { hasPerms } from '@/components/auth/auth';
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="system-menu-dialog-container layout-pd">
 | 
			
		||||
        <el-dialog :title="title" :destroy-on-close="true" v-model="dialogVisible" width="800px">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog :title="title" :destroy-on-close="true" v-model="visible" width="800px">
 | 
			
		||||
            <el-form :model="form" :inline="true" ref="menuForm" :rules="rules" label-width="auto">
 | 
			
		||||
                <el-row :gutter="35">
 | 
			
		||||
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
 | 
			
		||||
@@ -111,9 +111,6 @@ import { Rules } from '@/common/rule';
 | 
			
		||||
const { t } = useI18n();
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    data: {
 | 
			
		||||
        type: [Boolean, Object],
 | 
			
		||||
    },
 | 
			
		||||
@@ -125,8 +122,10 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const visible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change']);
 | 
			
		||||
 | 
			
		||||
const menuForm: any = ref(null);
 | 
			
		||||
 | 
			
		||||
@@ -161,7 +160,6 @@ const trueFalseOption = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    form: {
 | 
			
		||||
        id: null,
 | 
			
		||||
        name: null,
 | 
			
		||||
@@ -183,12 +181,14 @@ const state = reactive({
 | 
			
		||||
    submitForm: {},
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, form, submitForm } = toRefs(state);
 | 
			
		||||
const { form, submitForm } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
const { isFetching: saveBtnLoading, execute: saveResouceExec } = resourceApi.save.useApi(submitForm);
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
    state.dialogVisible = props.visible;
 | 
			
		||||
    if (!visible.value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (props.data) {
 | 
			
		||||
        state.form = { ...(props.data as any) };
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -271,7 +271,7 @@ const parseMenuMeta = (meta: any) => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    visible.value = false;
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
                </div>
 | 
			
		||||
                <el-scrollbar>
 | 
			
		||||
                    <el-tree
 | 
			
		||||
                        class="inline-block min-w-full"
 | 
			
		||||
                        ref="resourceTreeRef"
 | 
			
		||||
                        :indent="24"
 | 
			
		||||
                        node-key="id"
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,6 @@
 | 
			
		||||
import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
			
		||||
import { AccountStatusEnum } from '../enums';
 | 
			
		||||
import { accountApi, roleApi } from '../api';
 | 
			
		||||
import { ElMessage } from 'element-plus';
 | 
			
		||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
			
		||||
import { TableColumn } from '@/components/pagetable';
 | 
			
		||||
import { hasPerms } from '@/components/auth/auth';
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog
 | 
			
		||||
            :title="$t('system.role.allocateMenuTitle', { roleName: roleInfo?.name })"
 | 
			
		||||
            v-model="dialogVisible"
 | 
			
		||||
            v-model="visible"
 | 
			
		||||
            :before-close="cancel"
 | 
			
		||||
            :show-close="false"
 | 
			
		||||
            width="400px"
 | 
			
		||||
@@ -46,9 +46,6 @@ import { getMenuIcon } from '../resource';
 | 
			
		||||
const { t } = useI18n();
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    title: {
 | 
			
		||||
        type: String,
 | 
			
		||||
    },
 | 
			
		||||
@@ -65,8 +62,10 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const visible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change']);
 | 
			
		||||
 | 
			
		||||
const defaultProps = {
 | 
			
		||||
    children: 'children',
 | 
			
		||||
@@ -76,17 +75,15 @@ const defaultProps = {
 | 
			
		||||
const menuTree: any = ref(null);
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
    roleInfo: null as any,
 | 
			
		||||
    submiting: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dialogVisible, roleInfo } = toRefs(state);
 | 
			
		||||
const { roleInfo } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
    () => props.visible,
 | 
			
		||||
    () => visible,
 | 
			
		||||
    (newValue) => {
 | 
			
		||||
        state.dialogVisible = newValue;
 | 
			
		||||
        state.roleInfo = props.role;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
@@ -109,8 +106,7 @@ const btnOk = async () => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    // 更新父组件visible prop对应的值为false
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    visible.value = false;
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="role-dialog">
 | 
			
		||||
        <el-dialog :title="title" v-model="dvisible" :show-close="false" :before-close="cancel" width="600px" :destroy-on-close="true">
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog :title="title" v-model="visible" :show-close="false" :before-close="cancel" width="600px" :destroy-on-close="true">
 | 
			
		||||
            <el-form ref="roleForm" :model="form" :rules="rules" label-width="auto">
 | 
			
		||||
                <el-form-item prop="name" :label="$t('system.role.roleName')" required>
 | 
			
		||||
                    <el-input v-model="form.name" auto-complete="off"></el-input>
 | 
			
		||||
@@ -45,9 +45,6 @@ const rules = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    data: {
 | 
			
		||||
        type: [Boolean, Object],
 | 
			
		||||
    },
 | 
			
		||||
@@ -56,12 +53,13 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const visible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
 | 
			
		||||
const emit = defineEmits(['cancel', 'val-change']);
 | 
			
		||||
 | 
			
		||||
const roleForm: any = ref(null);
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dvisible: false,
 | 
			
		||||
    form: {
 | 
			
		||||
        id: null,
 | 
			
		||||
        name: '',
 | 
			
		||||
@@ -71,12 +69,14 @@ const state = reactive({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { dvisible, form } = toRefs(state);
 | 
			
		||||
const { form } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
const { isFetching: saveBtnLoading, execute: saveRoleExec } = roleApi.save.useApi(form);
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
    state.dvisible = props.visible;
 | 
			
		||||
    if (!visible.value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (props.data) {
 | 
			
		||||
        state.form = { ...(props.data as any) };
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -85,8 +85,7 @@ watchEffect(() => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const cancel = () => {
 | 
			
		||||
    // 更新父组件visible prop对应的值为false
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    visible.value = false;
 | 
			
		||||
    // 若父组件有取消事件,则调用
 | 
			
		||||
    emit('cancel');
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,6 @@ import RoleEdit from './RoleEdit.vue';
 | 
			
		||||
import ResourceEdit from './ResourceEdit.vue';
 | 
			
		||||
import ShowResource from './ShowResource.vue';
 | 
			
		||||
import { roleApi, resourceApi } from '../api';
 | 
			
		||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
			
		||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
			
		||||
import { TableColumn } from '@/components/pagetable';
 | 
			
		||||
import { hasPerms } from '@/components/auth/auth';
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <el-dialog @close="closeDialog" :title="title" :before-close="closeDialog" v-model="dialogVisible" width="400px">
 | 
			
		||||
            <el-tree style="height: 50vh; overflow: auto" :data="resources" node-key="id" :props="defaultProps">
 | 
			
		||||
        <el-dialog @close="closeDialog" :title="props.title" :before-close="closeDialog" v-model="visible" width="400px">
 | 
			
		||||
            <el-tree style="height: 50vh; overflow: auto" :data="props.resources" node-key="id" :props="defaultProps">
 | 
			
		||||
                <template #default="{ node, data }">
 | 
			
		||||
                    <span class="custom-tree-node">
 | 
			
		||||
                        <SvgIcon :name="getMenuIcon(data)" class="mb-0.5 mr-0.5" />
 | 
			
		||||
@@ -35,15 +35,11 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { toRefs, reactive, watch } from 'vue';
 | 
			
		||||
import { ResourceTypeEnum } from '../enums';
 | 
			
		||||
import { formatDate } from '@/common/utils/format';
 | 
			
		||||
import { getMenuIcon } from '../resource/index';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    visible: {
 | 
			
		||||
        type: Boolean,
 | 
			
		||||
    },
 | 
			
		||||
    resources: {
 | 
			
		||||
        type: Array,
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,29 +48,15 @@ const props = defineProps({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
//定义事件
 | 
			
		||||
const emit = defineEmits(['update:visible', 'update:resources']);
 | 
			
		||||
const visible = defineModel<boolean>('visible', { default: false });
 | 
			
		||||
 | 
			
		||||
const defaultProps = {
 | 
			
		||||
    children: 'children',
 | 
			
		||||
    label: 'name',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const state = reactive({
 | 
			
		||||
    dialogVisible: false,
 | 
			
		||||
});
 | 
			
		||||
const { dialogVisible } = toRefs(state);
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
    () => props.visible,
 | 
			
		||||
    (newValue) => {
 | 
			
		||||
        state.dialogVisible = newValue;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const closeDialog = () => {
 | 
			
		||||
    emit('update:visible', false);
 | 
			
		||||
    emit('update:resources', []);
 | 
			
		||||
    visible.value = false;
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,7 @@ func (p *procinstAppImpl) CancelProc(ctx context.Context, procinstId uint64) err
 | 
			
		||||
	if la == nil {
 | 
			
		||||
		return errorx.NewBiz("no login")
 | 
			
		||||
	}
 | 
			
		||||
	if procinst.CreatorId != consts.AdminId && procinst.CreatorId != la.Id {
 | 
			
		||||
	if la.Id != consts.AdminId && procinst.CreatorId != la.Id {
 | 
			
		||||
		return errorx.NewBizI(ctx, imsg.ErrProcinstCancelSelf)
 | 
			
		||||
	}
 | 
			
		||||
	procinst.Status = entity.ProcinstStatusCancelled
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user