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