mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	refactor: 样式优化
This commit is contained in:
		@@ -10,9 +10,9 @@
 | 
			
		||||
        "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@element-plus/icons-vue": "^2.3.1",
 | 
			
		||||
        "@logicflow/core": "^2.0.16",
 | 
			
		||||
        "@logicflow/extension": "^2.0.21",
 | 
			
		||||
        "@element-plus/icons-vue": "^2.3.2",
 | 
			
		||||
        "@logicflow/core": "^2.1.1",
 | 
			
		||||
        "@logicflow/extension": "^2.1.2",
 | 
			
		||||
        "@vueuse/core": "^13.6.0",
 | 
			
		||||
        "@xterm/addon-fit": "^0.10.0",
 | 
			
		||||
        "@xterm/addon-search": "^0.15.0",
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
        "crypto-js": "^4.2.0",
 | 
			
		||||
        "dayjs": "^1.11.13",
 | 
			
		||||
        "echarts": "^6.0.0",
 | 
			
		||||
        "element-plus": "^2.10.5",
 | 
			
		||||
        "element-plus": "^2.10.7",
 | 
			
		||||
        "js-base64": "^3.7.7",
 | 
			
		||||
        "jsencrypt": "^3.3.2",
 | 
			
		||||
        "monaco-editor": "^0.52.2",
 | 
			
		||||
@@ -59,7 +59,7 @@
 | 
			
		||||
        "eslint-plugin-vue": "^10.4.0",
 | 
			
		||||
        "postcss": "^8.5.6",
 | 
			
		||||
        "prettier": "^3.6.1",
 | 
			
		||||
        "sass": "^1.89.2",
 | 
			
		||||
        "sass": "^1.90.0",
 | 
			
		||||
        "tailwindcss": "^4.1.11",
 | 
			
		||||
        "typescript": "^5.9.2",
 | 
			
		||||
        "vite": "npm:rolldown-vite@latest",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <el-main class="layout-main !h-full">
 | 
			
		||||
        <el-scrollbar ref="layoutScrollbarRef" view-class="!h-full">
 | 
			
		||||
    <el-main class="layout-main h-full">
 | 
			
		||||
        <el-scrollbar ref="layoutScrollbarRef" view-class="h-full">
 | 
			
		||||
            <LayoutParentView />
 | 
			
		||||
        </el-scrollbar>
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts" name="layoutMain">
 | 
			
		||||
import { getCurrentInstance, watch, defineAsyncComponent } from 'vue';
 | 
			
		||||
import { watch, defineAsyncComponent, useTemplateRef, nextTick, onMounted } from 'vue';
 | 
			
		||||
import { useRoute } from 'vue-router';
 | 
			
		||||
import { storeToRefs } from 'pinia';
 | 
			
		||||
import { useThemeConfig } from '@/store/themeConfig';
 | 
			
		||||
@@ -21,22 +21,33 @@ import { useThemeConfig } from '@/store/themeConfig';
 | 
			
		||||
const LayoutParentView = defineAsyncComponent(() => import('@/layout/routerView/parent.vue'));
 | 
			
		||||
const Footer = defineAsyncComponent(() => import('@/layout/footer/index.vue'));
 | 
			
		||||
 | 
			
		||||
const { proxy } = getCurrentInstance() as any;
 | 
			
		||||
const layoutScrollbarRef = useTemplateRef('layoutScrollbarRef');
 | 
			
		||||
const { themeConfig } = storeToRefs(useThemeConfig());
 | 
			
		||||
const route = useRoute();
 | 
			
		||||
 | 
			
		||||
// 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度
 | 
			
		||||
watch(themeConfig.value, (val) => {
 | 
			
		||||
    if (val.isFixedHeaderChange !== val.isFixedHeader) {
 | 
			
		||||
        if (!proxy.$refs.layoutScrollbarRef) return false;
 | 
			
		||||
        proxy.$refs.layoutScrollbarRef.update();
 | 
			
		||||
        if (!layoutScrollbarRef.value) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        layoutScrollbarRef.value.update();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 监听路由的变化
 | 
			
		||||
watch(
 | 
			
		||||
    () => route.path,
 | 
			
		||||
    () => {
 | 
			
		||||
        proxy.$refs.layoutScrollbarRef.wrapRef.scrollTop = 0;
 | 
			
		||||
        nextTick(() => {
 | 
			
		||||
            if (!layoutScrollbarRef.value) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            setTimeout(() => {
 | 
			
		||||
                layoutScrollbarRef.value.update();
 | 
			
		||||
            }, 500);
 | 
			
		||||
            layoutScrollbarRef.value.setScrollTop();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <el-container class="layout-container flex-center layout-backtop">
 | 
			
		||||
    <el-container class="layout-container layout-backtop !flex-col">
 | 
			
		||||
        <Header />
 | 
			
		||||
        <Main />
 | 
			
		||||
    </el-container>
 | 
			
		||||
 
 | 
			
		||||
@@ -34,13 +34,12 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup name="navMenuHorizontal">
 | 
			
		||||
import { reactive, computed, onMounted, inject, defineAsyncComponent } from 'vue';
 | 
			
		||||
import { reactive, computed, onMounted, inject } from 'vue';
 | 
			
		||||
import { useRoute, onBeforeRouteUpdate } from 'vue-router';
 | 
			
		||||
import SubItem from '@/layout/navMenu/subItem.vue';
 | 
			
		||||
import { useRoutesList } from '@/store/routesList';
 | 
			
		||||
import { useThemeConfig } from '@/store/themeConfig';
 | 
			
		||||
 | 
			
		||||
const SubItem = defineAsyncComponent(() => import('@/layout/navMenu/subItem.vue'));
 | 
			
		||||
 | 
			
		||||
// 定义父组件传过来的值
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    // 菜单列表
 | 
			
		||||
@@ -117,42 +116,29 @@ onBeforeRouteUpdate((to) => {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    margin-right: 30px;
 | 
			
		||||
 | 
			
		||||
    .horizontal-menu {
 | 
			
		||||
        border: none !important;
 | 
			
		||||
    ::v-deep(.el-scrollbar__bar.is-vertical) {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ::v-deep(a) {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .el-menu.el-menu--horizontal {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        box-sizing: border-box;
 | 
			
		||||
 | 
			
		||||
        ::v-deep(.el-menu-item) {
 | 
			
		||||
            height: 42px;
 | 
			
		||||
            line-height: 42px;
 | 
			
		||||
            padding: 0 15px !important;
 | 
			
		||||
            margin: 0 5px;
 | 
			
		||||
            border-radius: 6px;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ::v-deep(.el-sub-menu__title) {
 | 
			
		||||
            height: 42px;
 | 
			
		||||
            line-height: 42px;
 | 
			
		||||
            padding: 0 25px 0 15px !important; /* 右边留出更多空间给箭头图标 */
 | 
			
		||||
            margin: 0 5px;
 | 
			
		||||
            border-radius: 6px;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ::v-deep(.el-sub-menu__icon-arrow) {
 | 
			
		||||
            right: 5px !important;
 | 
			
		||||
            margin-top: -5px !important;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ::v-deep(.el-menu-item.is-active),
 | 
			
		||||
        ::v-deep(.el-sub-menu.is-active .el-sub-menu__title) {
 | 
			
		||||
            color: #409eff;
 | 
			
		||||
            background-color: rgba(64, 158, 255, 0.1);
 | 
			
		||||
        }
 | 
			
		||||
        border-bottom: none !important;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 菜单项基础样式
 | 
			
		||||
.horizontal-menu :deep(.el-menu-item),
 | 
			
		||||
.horizontal-menu :deep(.el-sub-menu__title) {
 | 
			
		||||
    margin: 0 5px !important;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    max-width: 160px;
 | 
			
		||||
    min-width: 100px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -131,35 +131,10 @@ $spacing: 8px;
 | 
			
		||||
 | 
			
		||||
    // 横向菜单
 | 
			
		||||
    .el-menu--horizontal {
 | 
			
		||||
        background: var(--bg-topBar);
 | 
			
		||||
 | 
			
		||||
        .el-menu-item,
 | 
			
		||||
        .el-sub-menu {
 | 
			
		||||
            height: $menuHeight;
 | 
			
		||||
            line-height: $menuHeight;
 | 
			
		||||
            color: var(--bg-topBarColor);
 | 
			
		||||
            border-radius: $radius;
 | 
			
		||||
            padding: 0 10px !important; // 减小内边距
 | 
			
		||||
 | 
			
		||||
            .el-sub-menu__title {
 | 
			
		||||
                height: $menuHeight;
 | 
			
		||||
                line-height: $menuHeight;
 | 
			
		||||
                color: var(--bg-topBarColor);
 | 
			
		||||
                border-radius: $radius;
 | 
			
		||||
                padding: 0 10px !important; // 减小内边距
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .el-menu-item.is-active,
 | 
			
		||||
        .el-sub-menu.is-active .el-sub-menu__title {
 | 
			
		||||
            color: #409eff;
 | 
			
		||||
            background-color: rgba(64, 158, 255, 0.1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .el-menu-item:hover,
 | 
			
		||||
        .el-sub-menu:not(.is-active):hover .el-sub-menu__title {
 | 
			
		||||
            background-color: rgba(64, 158, 255, 0.05);
 | 
			
		||||
            transform: translateY(-1px);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -171,33 +146,15 @@ $spacing: 8px;
 | 
			
		||||
 | 
			
		||||
    .el-menu-item,
 | 
			
		||||
    .el-sub-menu__title {
 | 
			
		||||
        height: $menuHeight;
 | 
			
		||||
        line-height: $menuHeight;
 | 
			
		||||
        color: var(--bg-topBarColor);
 | 
			
		||||
        border-radius: $radius;
 | 
			
		||||
        transition: all 0.2s ease;
 | 
			
		||||
        padding: 0 10px !important; // 减小内边距
 | 
			
		||||
        border-bottom: none !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .el-menu-item:not(.is-active):hover,
 | 
			
		||||
    .el-sub-menu:not(.is-active):hover .el-sub-menu__title {
 | 
			
		||||
        color: var(--bg-topBarColor);
 | 
			
		||||
        background-color: rgba(0, 0, 0, 0.03);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .el-menu-item.is-active,
 | 
			
		||||
    .el-sub-menu.is-active .el-sub-menu__title {
 | 
			
		||||
        background-color: rgba(64, 158, 255, 0.1);
 | 
			
		||||
        color: #409eff;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        border-bottom: none !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 为水平菜单的子菜单项正确处理箭头图标位置
 | 
			
		||||
    .el-sub-menu {
 | 
			
		||||
        .el-sub-menu__title {
 | 
			
		||||
            padding-right: 20px !important; // 调整箭头图标空间
 | 
			
		||||
            padding-right: 22px !important; // 调整箭头图标空间
 | 
			
		||||
            border-bottom: none !important;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI
 | 
			
		||||
import { tmplApi } from '../api';
 | 
			
		||||
import { TmplStatusEnum, TmplTypeEnum, ChannelTypeEnum } from '../enums';
 | 
			
		||||
import TmplEdit from './TmplEdit.vue';
 | 
			
		||||
import EnumValue from '../../../common/Enum';
 | 
			
		||||
import EnumValue from '@/common/Enum';
 | 
			
		||||
import AccountSelectFormItem from '@/views/system/account/components/AccountSelectFormItem.vue';
 | 
			
		||||
 | 
			
		||||
const perms = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,12 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <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-card class="h-full flex tag-tree-card" body-class="!p-0 flex flex-col w-full">
 | 
			
		||||
        <div class="tag-tree-header">
 | 
			
		||||
            <el-input v-model="filterText" :placeholder="$t('tag.tagFilterPlaceholder')" clearable size="small" class="tag-tree-search w-full">
 | 
			
		||||
                <template #prefix>
 | 
			
		||||
                    <SvgIcon class="tag-tree-search-icon" name="search" />
 | 
			
		||||
                </template>
 | 
			
		||||
            </el-input>
 | 
			
		||||
        </div>
 | 
			
		||||
        <el-scrollbar>
 | 
			
		||||
            <el-tree
 | 
			
		||||
                class="min-w-full inline-block"
 | 
			
		||||
@@ -30,7 +36,7 @@
 | 
			
		||||
 | 
			
		||||
                        <slot v-else :node="node" :data="data" name="prefix"></slot>
 | 
			
		||||
 | 
			
		||||
                        <span class="ml-0.5" :title="data.labelRemark">
 | 
			
		||||
                        <span class="ml-1" :title="data.labelRemark">
 | 
			
		||||
                            <slot name="label" :data="data" v-if="!data.disabled"> {{ $t(data.label) }}</slot>
 | 
			
		||||
                            <!-- 禁用状态 -->
 | 
			
		||||
                            <slot name="disabledLabel" :data="data" v-else>
 | 
			
		||||
@@ -40,7 +46,7 @@
 | 
			
		||||
                            </slot>
 | 
			
		||||
                        </span>
 | 
			
		||||
 | 
			
		||||
                        <span class="absolute right-2.5 mt-0.5 text-[10px] text-gray-400">
 | 
			
		||||
                        <span class="ml-auto pr-1.5 text-[10px] text-gray-400">
 | 
			
		||||
                            <slot :node="node" :data="data" name="suffix"></slot>
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </div>
 | 
			
		||||
@@ -59,6 +65,7 @@ import TagInfo from './TagInfo.vue';
 | 
			
		||||
import { Contextmenu } from '@/components/contextmenu';
 | 
			
		||||
import { tagApi } from '../tag/api';
 | 
			
		||||
import { isPrefixSubsequence } from '@/common/utils/string';
 | 
			
		||||
import SvgIcon from '@/components/svgIcon/index.vue';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    resourceType: {
 | 
			
		||||
@@ -248,4 +255,22 @@ defineExpose({
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped></style>
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.tag-tree-card {
 | 
			
		||||
    :deep(.el-card__body) {
 | 
			
		||||
        padding: 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-tree-header {
 | 
			
		||||
    padding: 4px 6px;
 | 
			
		||||
    border-bottom: 1px solid var(--el-border-color-light);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-tree-search {
 | 
			
		||||
    :deep(.el-input__wrapper) {
 | 
			
		||||
        border-radius: 14px;
 | 
			
		||||
        height: 24px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@
 | 
			
		||||
                                </div>
 | 
			
		||||
 | 
			
		||||
                                <!-- 字段名列 -->
 | 
			
		||||
                                <div v-else @contextmenu="headerContextmenuClick($event, column)" style="position: relative">
 | 
			
		||||
                                <div v-else style="position: relative" @mouseenter="showColumnAction(column)" @mouseleave="hideColumnAction">
 | 
			
		||||
                                    <!-- 字段列的数据类型 -->
 | 
			
		||||
                                    <div class="column-type">
 | 
			
		||||
                                        <span v-if="column.dataTypeSubscript === 'icon-clock'">
 | 
			
		||||
@@ -65,9 +65,56 @@
 | 
			
		||||
 | 
			
		||||
                                    <!-- 字段列右部分内容 -->
 | 
			
		||||
                                    <div class="column-right">
 | 
			
		||||
                                        <span v-if="column.title == nowSortColumn?.columnName">
 | 
			
		||||
                                            <SvgIcon color="var(--el-color-primary)" :name="nowSortColumn?.order == 'asc' ? 'top' : 'bottom'"></SvgIcon>
 | 
			
		||||
                                        <el-dropdown
 | 
			
		||||
                                            @command="handleColumnCommand(column, $event)"
 | 
			
		||||
                                            @visibleChange="onColumnActionVisibleChange(column, $event)"
 | 
			
		||||
                                            trigger="click"
 | 
			
		||||
                                            v-if="column.key !== rowNoColumn.key"
 | 
			
		||||
                                            size="small"
 | 
			
		||||
                                        >
 | 
			
		||||
                                            <span class="column-actions-trigger">
 | 
			
		||||
                                                <!-- 排序箭头图标 -->
 | 
			
		||||
                                                <SvgIcon
 | 
			
		||||
                                                    v-if="
 | 
			
		||||
                                                        column.title == nowSortColumn?.columnName &&
 | 
			
		||||
                                                        !showColumnActions[column.key] &&
 | 
			
		||||
                                                        !columnActionVisible[column.key]
 | 
			
		||||
                                                    "
 | 
			
		||||
                                                    :color="'var(--el-color-primary)'"
 | 
			
		||||
                                                    :name="nowSortColumn?.order == 'asc' ? 'top' : 'bottom'"
 | 
			
		||||
                                                    :size="14"
 | 
			
		||||
                                                />
 | 
			
		||||
                                                <!-- 更多操作图标 -->
 | 
			
		||||
                                                <SvgIcon
 | 
			
		||||
                                                    v-if="columnActionVisible[column.key] || showColumnActions[column.key]"
 | 
			
		||||
                                                    name="MoreFilled"
 | 
			
		||||
                                                    :size="14"
 | 
			
		||||
                                                    :color="'var(--el-color-primary)'"
 | 
			
		||||
                                                    class="column-more-icon"
 | 
			
		||||
                                                    :class="{ 'column-more-icon-visible': columnActionVisible[column.key] || showColumnActions[column.key] }"
 | 
			
		||||
                                                />
 | 
			
		||||
                                            </span>
 | 
			
		||||
                                            <template #dropdown>
 | 
			
		||||
                                                <el-dropdown-menu>
 | 
			
		||||
                                                    <el-dropdown-item command="sort-asc">
 | 
			
		||||
                                                        <SvgIcon name="top" class="mr-1" />
 | 
			
		||||
                                                        {{ $t('db.asc') }}
 | 
			
		||||
                                                    </el-dropdown-item>
 | 
			
		||||
                                                    <el-dropdown-item command="sort-desc">
 | 
			
		||||
                                                        <SvgIcon name="bottom" class="mr-1" />
 | 
			
		||||
                                                        {{ $t('db.desc') }}
 | 
			
		||||
                                                    </el-dropdown-item>
 | 
			
		||||
                                                    <el-dropdown-item v-if="!column.fixed" command="fix">
 | 
			
		||||
                                                        <SvgIcon name="Paperclip" class="mr-1" />
 | 
			
		||||
                                                        {{ $t('db.fixed') }}
 | 
			
		||||
                                                    </el-dropdown-item>
 | 
			
		||||
                                                    <el-dropdown-item v-else command="unfix">
 | 
			
		||||
                                                        <SvgIcon name="Minus" class="mr-1" />
 | 
			
		||||
                                                        {{ $t('db.cancelFiexd') }}
 | 
			
		||||
                                                    </el-dropdown-item>
 | 
			
		||||
                                                </el-dropdown-menu>
 | 
			
		||||
                                            </template>
 | 
			
		||||
                                        </el-dropdown>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
@@ -214,43 +261,9 @@ const props = defineProps({
 | 
			
		||||
const contextmenuRef = ref();
 | 
			
		||||
const tableRef = ref();
 | 
			
		||||
 | 
			
		||||
/**  表头 menu items  **/
 | 
			
		||||
 | 
			
		||||
const cmHeaderAsc = new ContextmenuItem('asc', 'db.asc')
 | 
			
		||||
    .withIcon('top')
 | 
			
		||||
    .withOnClick((data: any) => {
 | 
			
		||||
        onTableSortChange({ columnName: data.dataKey, order: 'asc' });
 | 
			
		||||
    })
 | 
			
		||||
    .withHideFunc(() => !props.showColumnTip);
 | 
			
		||||
 | 
			
		||||
const cmHeaderDesc = new ContextmenuItem('desc', 'db.desc')
 | 
			
		||||
    .withIcon('bottom')
 | 
			
		||||
    .withOnClick((data: any) => {
 | 
			
		||||
        onTableSortChange({ columnName: data.dataKey, order: 'desc' });
 | 
			
		||||
    })
 | 
			
		||||
    .withHideFunc(() => !props.showColumnTip);
 | 
			
		||||
 | 
			
		||||
const cmHeaderFixed = new ContextmenuItem('fixed', 'db.fixed')
 | 
			
		||||
    .withIcon('Paperclip')
 | 
			
		||||
    .withOnClick((data: any) => {
 | 
			
		||||
        state.columns.forEach((column: any) => {
 | 
			
		||||
            if (column.dataKey == data.dataKey) {
 | 
			
		||||
                column.fixed = true;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    })
 | 
			
		||||
    .withHideFunc((data: any) => data.fixed);
 | 
			
		||||
 | 
			
		||||
const cmHeaderCancelFixed = new ContextmenuItem('cancelFixed', 'db.cancelFiexd')
 | 
			
		||||
    .withIcon('Minus')
 | 
			
		||||
    .withOnClick((data: any) => {
 | 
			
		||||
        state.columns.forEach((column: any) => {
 | 
			
		||||
            if (column.dataKey == data.dataKey) {
 | 
			
		||||
                column.fixed = false;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    })
 | 
			
		||||
    .withHideFunc((data: any) => !data.fixed);
 | 
			
		||||
// 用于控制列操作按钮的显示
 | 
			
		||||
const showColumnActions = ref({} as any);
 | 
			
		||||
const columnActionVisible = ref({} as any);
 | 
			
		||||
 | 
			
		||||
/**  表数据 contextmenu items  **/
 | 
			
		||||
 | 
			
		||||
@@ -508,6 +521,55 @@ const cancelLoading = async () => {
 | 
			
		||||
    endLoading();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 显示列操作按钮
 | 
			
		||||
 */
 | 
			
		||||
const showColumnAction = (column: any) => {
 | 
			
		||||
    showColumnActions.value[column.key] = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 隐藏列操作按钮
 | 
			
		||||
 */
 | 
			
		||||
const hideColumnAction = () => {
 | 
			
		||||
    showColumnActions.value = {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 处理列操作命令
 | 
			
		||||
 */
 | 
			
		||||
const handleColumnCommand = (column: any, command: string) => {
 | 
			
		||||
    switch (command) {
 | 
			
		||||
        case 'sort-asc':
 | 
			
		||||
            onTableSortChange({ columnName: column.dataKey, order: 'asc' });
 | 
			
		||||
            break;
 | 
			
		||||
        case 'sort-desc':
 | 
			
		||||
            onTableSortChange({ columnName: column.dataKey, order: 'desc' });
 | 
			
		||||
            break;
 | 
			
		||||
        case 'fix':
 | 
			
		||||
            state.columns.forEach((col: any) => {
 | 
			
		||||
                if (col.dataKey == column.dataKey) {
 | 
			
		||||
                    col.fixed = true;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            break;
 | 
			
		||||
        case 'unfix':
 | 
			
		||||
            state.columns.forEach((col: any) => {
 | 
			
		||||
                if (col.dataKey == column.dataKey) {
 | 
			
		||||
                    col.fixed = false;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    // 点击了取消固定等操作后,可能更多的icon还是显示在列上,所以需要重新置为空对象。暂时不懂是组件bug还是啥
 | 
			
		||||
    columnActionVisible.value = {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onColumnActionVisibleChange = (column: any, visible: boolean) => {
 | 
			
		||||
    columnActionVisible.value = {}; // 只显示一个列的更多icon
 | 
			
		||||
    columnActionVisible.value[column.key] = visible;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 当前单元格是否允许编辑
 | 
			
		||||
 * @param rowIndex ri
 | 
			
		||||
@@ -570,16 +632,6 @@ const rowEventHandlers = {
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const headerContextmenuClick = (event: any, data: any) => {
 | 
			
		||||
    event.preventDefault(); // 阻止默认的右击菜单行为
 | 
			
		||||
 | 
			
		||||
    const { clientX, clientY } = event;
 | 
			
		||||
    state.contextmenu.dropdown.x = clientX;
 | 
			
		||||
    state.contextmenu.dropdown.y = clientY;
 | 
			
		||||
    state.contextmenu.items = [cmHeaderAsc, cmHeaderDesc, cmHeaderFixed, cmHeaderCancelFixed];
 | 
			
		||||
    contextmenuRef.value.openContextmenu(data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const dataContextmenuClick = (event: any, rowIndex: number, column: any, data: any) => {
 | 
			
		||||
    event.preventDefault(); // 阻止默认的右击菜单行为
 | 
			
		||||
 | 
			
		||||
@@ -851,6 +903,31 @@ defineExpose({
 | 
			
		||||
        top: 2px;
 | 
			
		||||
        right: 0;
 | 
			
		||||
        padding: 2px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .column-actions-trigger {
 | 
			
		||||
        display: inline-flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        width: 16px;
 | 
			
		||||
        height: 16px;
 | 
			
		||||
        border-radius: 50%;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            background-color: var(--el-fill-color-light);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .column-more-icon {
 | 
			
		||||
        opacity: 0;
 | 
			
		||||
        transition: opacity 0.2s;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .column-more-icon-visible {
 | 
			
		||||
        opacity: 1 !important;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -497,8 +497,8 @@ export class DbInst {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 获取列名称的长度 加上排序图标长度、abc为字段类型简称占位符、排序图标等
 | 
			
		||||
        const columnWidth: number = getTextWidth(prop + 'abc') + 10;
 | 
			
		||||
        // 获取列名称的长度 加上排序图标长度、abc为字段类型简称占位符、更多/排序图标等
 | 
			
		||||
        const columnWidth: number = getTextWidth(prop + 'abc') + 25;
 | 
			
		||||
        // prop为该列的字段名(传字符串);tableData为该表格的数据源(传变量);
 | 
			
		||||
        if (!tableData || !tableData.length || tableData.length === 0 || tableData === undefined) {
 | 
			
		||||
            return columnWidth;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
module mayfly-go
 | 
			
		||||
 | 
			
		||||
go 1.24
 | 
			
		||||
go 1.25
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	gitee.com/chunanyong/dm v1.8.20
 | 
			
		||||
@@ -23,7 +23,7 @@ require (
 | 
			
		||||
	github.com/pkg/errors v0.9.1
 | 
			
		||||
	github.com/pkg/sftp v1.13.9
 | 
			
		||||
	github.com/pquerna/otp v1.5.0
 | 
			
		||||
	github.com/redis/go-redis/v9 v9.11.0
 | 
			
		||||
	github.com/redis/go-redis/v9 v9.12.1
 | 
			
		||||
	github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
			
		||||
	github.com/sijms/go-ora/v2 v2.9.0
 | 
			
		||||
	github.com/spf13/cast v1.9.2
 | 
			
		||||
@@ -31,7 +31,7 @@ require (
 | 
			
		||||
	github.com/tidwall/gjson v1.18.0
 | 
			
		||||
	github.com/veops/go-ansiterm v0.0.5
 | 
			
		||||
	go.mongodb.org/mongo-driver/v2 v2.2.2 // mongo
 | 
			
		||||
	golang.org/x/crypto v0.40.0 // ssh
 | 
			
		||||
	golang.org/x/crypto v0.41.0 // ssh
 | 
			
		||||
	golang.org/x/oauth2 v0.30.0
 | 
			
		||||
	golang.org/x/sync v0.16.0
 | 
			
		||||
	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 | 
			
		||||
@@ -91,8 +91,8 @@ require (
 | 
			
		||||
	golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect
 | 
			
		||||
	golang.org/x/image v0.29.0 // indirect
 | 
			
		||||
	golang.org/x/net v0.42.0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.34.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.27.0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.35.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.28.0 // indirect
 | 
			
		||||
	google.golang.org/protobuf v1.36.6 // indirect
 | 
			
		||||
	modernc.org/libc v1.66.4 // indirect
 | 
			
		||||
	modernc.org/mathutil v1.7.1 // indirect
 | 
			
		||||
 
 | 
			
		||||
@@ -379,7 +379,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
	isSuccess := true
 | 
			
		||||
	for _, chunk := range chunks {
 | 
			
		||||
		go func(files []FolderFile, wg *sync.WaitGroup) {
 | 
			
		||||
		wg.Go(func() {
 | 
			
		||||
			defer func() {
 | 
			
		||||
				// 协程执行完成后调用Done方法
 | 
			
		||||
				wg.Done()
 | 
			
		||||
@@ -397,7 +397,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
 | 
			
		||||
				}
 | 
			
		||||
			}()
 | 
			
		||||
 | 
			
		||||
			for _, file := range files {
 | 
			
		||||
			for _, file := range chunk {
 | 
			
		||||
				fileHeader := file.Fileheader
 | 
			
		||||
				dir := file.Dir
 | 
			
		||||
				file, _ := fileHeader.Open()
 | 
			
		||||
@@ -410,7 +410,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
 | 
			
		||||
				defer createfile.Close()
 | 
			
		||||
				io.Copy(createfile, file)
 | 
			
		||||
			}
 | 
			
		||||
		}(chunk, &wg)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 等待所有协程执行完成
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user