mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	feat: 机器脚本新增分配、组件属性类型不匹配警告调整
This commit is contained in:
		@@ -11,8 +11,8 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "dependencies": {
 | 
					    "dependencies": {
 | 
				
			||||||
        "@element-plus/icons-vue": "^2.3.1",
 | 
					        "@element-plus/icons-vue": "^2.3.1",
 | 
				
			||||||
        "@logicflow/core": "^2.0.15",
 | 
					        "@logicflow/core": "^2.0.16",
 | 
				
			||||||
        "@logicflow/extension": "^2.0.20",
 | 
					        "@logicflow/extension": "^2.0.21",
 | 
				
			||||||
        "@vueuse/core": "^13.3.0",
 | 
					        "@vueuse/core": "^13.3.0",
 | 
				
			||||||
        "@xterm/addon-fit": "^0.10.0",
 | 
					        "@xterm/addon-fit": "^0.10.0",
 | 
				
			||||||
        "@xterm/addon-search": "^0.15.0",
 | 
					        "@xterm/addon-search": "^0.15.0",
 | 
				
			||||||
@@ -24,7 +24,7 @@
 | 
				
			|||||||
        "crypto-js": "^4.2.0",
 | 
					        "crypto-js": "^4.2.0",
 | 
				
			||||||
        "dayjs": "^1.11.13",
 | 
					        "dayjs": "^1.11.13",
 | 
				
			||||||
        "echarts": "^5.6.0",
 | 
					        "echarts": "^5.6.0",
 | 
				
			||||||
        "element-plus": "^2.10.1",
 | 
					        "element-plus": "^2.10.2",
 | 
				
			||||||
        "js-base64": "^3.7.7",
 | 
					        "js-base64": "^3.7.7",
 | 
				
			||||||
        "jsencrypt": "^3.3.2",
 | 
					        "jsencrypt": "^3.3.2",
 | 
				
			||||||
        "mitt": "^3.0.1",
 | 
					        "mitt": "^3.0.1",
 | 
				
			||||||
@@ -45,7 +45,7 @@
 | 
				
			|||||||
        "vuedraggable": "^4.1.0"
 | 
					        "vuedraggable": "^4.1.0"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "devDependencies": {
 | 
					    "devDependencies": {
 | 
				
			||||||
        "@tailwindcss/vite": "^4.1.6",
 | 
					        "@tailwindcss/vite": "^4.1.9",
 | 
				
			||||||
        "@types/crypto-js": "^4.2.2",
 | 
					        "@types/crypto-js": "^4.2.2",
 | 
				
			||||||
        "@types/node": "^18.14.0",
 | 
					        "@types/node": "^18.14.0",
 | 
				
			||||||
        "@types/nprogress": "^0.2.0",
 | 
					        "@types/nprogress": "^0.2.0",
 | 
				
			||||||
@@ -58,13 +58,13 @@
 | 
				
			|||||||
        "code-inspector-plugin": "^0.20.9",
 | 
					        "code-inspector-plugin": "^0.20.9",
 | 
				
			||||||
        "dotenv": "^16.3.1",
 | 
					        "dotenv": "^16.3.1",
 | 
				
			||||||
        "eslint": "^9.27.0",
 | 
					        "eslint": "^9.27.0",
 | 
				
			||||||
        "eslint-plugin-vue": "^10.1.0",
 | 
					        "eslint-plugin-vue": "^10.2.0",
 | 
				
			||||||
        "postcss": "^8.5.4",
 | 
					        "postcss": "^8.5.4",
 | 
				
			||||||
        "prettier": "^3.5.3",
 | 
					        "prettier": "^3.5.3",
 | 
				
			||||||
        "sass": "^1.89.1",
 | 
					        "sass": "^1.89.2",
 | 
				
			||||||
        "tailwindcss": "^4.1.8",
 | 
					        "tailwindcss": "^4.1.9",
 | 
				
			||||||
        "typescript": "^5.8.2",
 | 
					        "typescript": "^5.8.2",
 | 
				
			||||||
        "vite": "^6.3.5",
 | 
					        "vite": "npm:rolldown-vite@latest",
 | 
				
			||||||
        "vite-plugin-progress": "0.0.7",
 | 
					        "vite-plugin-progress": "0.0.7",
 | 
				
			||||||
        "vue-eslint-parser": "^10.1.3"
 | 
					        "vue-eslint-parser": "^10.1.3"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@ const config = {
 | 
				
			|||||||
    baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
 | 
					    baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 系统版本
 | 
					    // 系统版本
 | 
				
			||||||
    version: 'v1.10.0',
 | 
					    version: 'v1.10.1',
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default config;
 | 
					export default config;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,4 +42,5 @@ export function exportFile(filename: string, content: string) {
 | 
				
			|||||||
    link.setAttribute('download', `${filename}`);
 | 
					    link.setAttribute('download', `${filename}`);
 | 
				
			||||||
    document.body.appendChild(link);
 | 
					    document.body.appendChild(link);
 | 
				
			||||||
    link.click();
 | 
					    link.click();
 | 
				
			||||||
 | 
					    document.body.removeChild(link); // 下载完成后移除元素
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,9 @@ const props = defineProps({
 | 
				
			|||||||
        required: true,
 | 
					        required: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    value: {
 | 
					    value: {
 | 
				
			||||||
        type: [Object, String, Number],
 | 
					        type: [Object, String, Number, null],
 | 
				
			||||||
        required: true,
 | 
					        required: true,
 | 
				
			||||||
 | 
					        default: () => null,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,7 +41,7 @@ onMounted(() => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const convert = (value: any) => {
 | 
					const convert = (value: any) => {
 | 
				
			||||||
    const enumValue = EnumValue.getEnumByValue(props.enums, value) as any;
 | 
					    const enumValue = EnumValue.getEnumByValue(props.enums, value);
 | 
				
			||||||
    if (!enumValue) {
 | 
					    if (!enumValue) {
 | 
				
			||||||
        state.enumLabel = '-';
 | 
					        state.enumLabel = '-';
 | 
				
			||||||
        state.type = 'danger';
 | 
					        state.type = 'danger';
 | 
				
			||||||
@@ -50,8 +51,8 @@ const convert = (value: any) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    state.enumLabel = enumValue?.label || '';
 | 
					    state.enumLabel = enumValue?.label || '';
 | 
				
			||||||
    if (enumValue.tag) {
 | 
					    if (enumValue.tag) {
 | 
				
			||||||
        state.color = enumValue.tag.color;
 | 
					        state.color = enumValue.tag.color || '';
 | 
				
			||||||
        state.type = enumValue.tag.type;
 | 
					        state.type = enumValue.tag.type || defaultType;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        state.type = defaultType;
 | 
					        state.type = defaultType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,7 @@
 | 
				
			|||||||
                                trigger="click"
 | 
					                                trigger="click"
 | 
				
			||||||
                            >
 | 
					                            >
 | 
				
			||||||
                                <div v-for="(item, index) in tableColumns" :key="index">
 | 
					                                <div v-for="(item, index) in tableColumns" :key="index">
 | 
				
			||||||
                                    <el-checkbox v-model="item.show" :label="$t(item.label)" :true-value="true" :false-value="false" />
 | 
					                                    <el-checkbox v-model="item.show" :label="$t(item.label)" :true-value="1" :false-value="0" />
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
                                <template #reference>
 | 
					                                <template #reference>
 | 
				
			||||||
                                    <el-button icon="Operation" circle :size="props.size"></el-button>
 | 
					                                    <el-button icon="Operation" circle :size="props.size"></el-button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,9 +71,9 @@ export class TableColumn {
 | 
				
			|||||||
    formatFunc: Function;
 | 
					    formatFunc: Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 是否显示该列
 | 
					     * 是否显示该列,1显示 0不显示
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    show: boolean = true;
 | 
					    show: number = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 是否展示美化按钮(主要用于美化json文本等)
 | 
					     * 是否展示美化按钮(主要用于美化json文本等)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,8 @@ export default {
 | 
				
			|||||||
        scriptResultEnumRealTime: 'Real-time',
 | 
					        scriptResultEnumRealTime: 'Real-time',
 | 
				
			||||||
        scriptTypeEnumPrivate: 'Private',
 | 
					        scriptTypeEnumPrivate: 'Private',
 | 
				
			||||||
        scriptTypeEnumPublic: 'Public',
 | 
					        scriptTypeEnumPublic: 'Public',
 | 
				
			||||||
 | 
					        category: 'Category',
 | 
				
			||||||
 | 
					        categoryTips: 'support input new category and selection',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // security
 | 
					        // security
 | 
				
			||||||
        cmdConfig: 'Command Config',
 | 
					        cmdConfig: 'Command Config',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,6 @@ export default {
 | 
				
			|||||||
            menuCodePlaceholder: `A menu that does not begin with '/' will automatically concatenate the parent menu path`,
 | 
					            menuCodePlaceholder: `A menu that does not begin with '/' will automatically concatenate the parent menu path`,
 | 
				
			||||||
            routerNameTips:
 | 
					            routerNameTips:
 | 
				
			||||||
                'For component caching to work, the key for route.ts in the frontend module should match the vue component name, such as ResourceList',
 | 
					                'For component caching to work, the key for route.ts in the frontend module should match the vue component name, such as ResourceList',
 | 
				
			||||||
            componentPathTips: 'Access path components, such as: ` system/resource/ResourceList `, default in ` views ` directory',
 | 
					 | 
				
			||||||
            isCacheTips: `If yes is selected, it will be 'keepalive' cached (reentering the page without refreshing the page and requesting data again), and needs the route name to match the vue component name`,
 | 
					            isCacheTips: `If yes is selected, it will be 'keepalive' cached (reentering the page without refreshing the page and requesting data again), and needs the route name to match the vue component name`,
 | 
				
			||||||
            isHideTips:
 | 
					            isHideTips:
 | 
				
			||||||
                'Select Hide and the route will not appear in the menu bar, but it will still be accessible. Disabled will not be able to access and operate',
 | 
					                'Select Hide and the route will not appear in the menu bar, but it will still be accessible. Disabled will not be able to access and operate',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,6 +88,8 @@ export default {
 | 
				
			|||||||
        scriptResultEnumRealTime: '实时交互',
 | 
					        scriptResultEnumRealTime: '实时交互',
 | 
				
			||||||
        scriptTypeEnumPrivate: '私有',
 | 
					        scriptTypeEnumPrivate: '私有',
 | 
				
			||||||
        scriptTypeEnumPublic: '公共',
 | 
					        scriptTypeEnumPublic: '公共',
 | 
				
			||||||
 | 
					        category: '分类',
 | 
				
			||||||
 | 
					        categoryTips: '支持输入新分类并选择',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // security
 | 
					        // security
 | 
				
			||||||
        cmdConfig: '命令配置',
 | 
					        cmdConfig: '命令配置',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,6 @@ export default {
 | 
				
			|||||||
            menuCodeTips: `菜单类型则为访问路径(若菜单路径不以'/'开头则访问地址会自动拼接父菜单路径)、否则为资源唯一编码`,
 | 
					            menuCodeTips: `菜单类型则为访问路径(若菜单路径不以'/'开头则访问地址会自动拼接父菜单路径)、否则为资源唯一编码`,
 | 
				
			||||||
            menuCodePlaceholder: `菜单不以'/'开头则自动拼接父菜单路径`,
 | 
					            menuCodePlaceholder: `菜单不以'/'开头则自动拼接父菜单路径`,
 | 
				
			||||||
            routerNameTips: '前端模块下route.ts中对应的key,与vue的组件名一致才可使组件缓存生效,如ResourceList',
 | 
					            routerNameTips: '前端模块下route.ts中对应的key,与vue的组件名一致才可使组件缓存生效,如ResourceList',
 | 
				
			||||||
            componentPathTips: '访问的组件路径,如:`system/resource/ResourceList`,默认在`views`目录下',
 | 
					 | 
				
			||||||
            isCacheTips: '选择是则会被`keep-alive`缓存(重新进入页面不会刷新页面及重新请求数据),需要路由名与vue的组件名一致',
 | 
					            isCacheTips: '选择是则会被`keep-alive`缓存(重新进入页面不会刷新页面及重新请求数据),需要路由名与vue的组件名一致',
 | 
				
			||||||
            isHideTips: '选择隐藏则路由将不会出现在菜单栏中,但仍然可以访问。禁用则不可访问与操作',
 | 
					            isHideTips: '选择隐藏则路由将不会出现在菜单栏中,但仍然可以访问。禁用则不可访问与操作',
 | 
				
			||||||
            externalLinkTips: '内嵌: 以iframe展示、外链: 新标签打开',
 | 
					            externalLinkTips: '内嵌: 以iframe展示、外链: 新标签打开',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
    <div class="layout-navbars-breadcrumb" v-show="themeConfig.isBreadcrumb">
 | 
					    <div class="layout-navbars-breadcrumb" v-show="themeConfig.isBreadcrumb">
 | 
				
			||||||
        <SvgIcon class="layout-navbars-breadcrumb-icon" :name="themeConfig.isCollapse ? 'expand' : 'fold'" @click="onThemeConfigChange" />
 | 
					        <SvgIcon class="layout-navbars-breadcrumb-icon" :name="themeConfig.isCollapse ? 'expand' : 'fold'" @click="onThemeConfigChange" />
 | 
				
			||||||
        <el-breadcrumb class="layout-navbars-breadcrumb-hide">
 | 
					        <el-breadcrumb class="layout-navbars-breadcrumb-hide">
 | 
				
			||||||
            <transition-group name="breadcrumb" mode="out-in">
 | 
					            <transition-group name="breadcrumb">
 | 
				
			||||||
                <el-breadcrumb-item v-for="(v, k) in state.breadcrumbList" :key="v.meta.title">
 | 
					                <el-breadcrumb-item v-for="(v, k) in state.breadcrumbList" :key="v.meta.title">
 | 
				
			||||||
                    <span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
 | 
					                    <span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
 | 
				
			||||||
                        <SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
 | 
					                        <SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,9 +83,8 @@ type RouterConvCallbackFunc = (router: any) => void;
 | 
				
			|||||||
 * @param name ==> title,路由标题 相当于route.meta.title
 | 
					 * @param name ==> title,路由标题 相当于route.meta.title
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param meta ==> 路由菜单元信息
 | 
					 * @param meta ==> 路由菜单元信息
 | 
				
			||||||
 * @param meta.routeName ==> route.name -> 路由 name (对应页面组件 name, 可用作 KeepAlive 缓存标识 && 按钮权限筛选)
 | 
					 * @param meta.routeName ==> route.name -> 路由 name (对应页面组件 name, 可用作 KeepAlive 缓存标识 && 按钮权限筛选) -> 对应模块下route.ts字段key
 | 
				
			||||||
 * @param meta.redirect ==> route.redirect -> 路由重定向地址
 | 
					 * @param meta.redirect ==> route.redirect -> 路由重定向地址
 | 
				
			||||||
 * @param meta.component ==> 文件路径
 | 
					 | 
				
			||||||
 * @param meta.icon ==> 菜单和面包屑对应的图标
 | 
					 * @param meta.icon ==> 菜单和面包屑对应的图标
 | 
				
			||||||
 * @param meta.isHide ==> 是否在菜单中隐藏 (通常列表详情页需要隐藏)
 | 
					 * @param meta.isHide ==> 是否在菜单中隐藏 (通常列表详情页需要隐藏)
 | 
				
			||||||
 * @param meta.isFull ==> 菜单是否全屏 (示例:数据大屏页面)
 | 
					 * @param meta.isFull ==> 菜单是否全屏 (示例:数据大屏页面)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@
 | 
				
			|||||||
                        <enum-tag :enums="FlowBizType" :value="procinst.bizType"></enum-tag>
 | 
					                        <enum-tag :enums="FlowBizType" :value="procinst.bizType"></enum-tag>
 | 
				
			||||||
                    </el-descriptions-item>
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
                    <el-descriptions-item :span="1" :label="$t('flow.initiator')">
 | 
					                    <el-descriptions-item :span="1" :label="$t('flow.initiator')">
 | 
				
			||||||
                        <AccountInfo :username="procinst.creator" />
 | 
					                        <AccountInfo :username="procinst.creator || ''" />
 | 
				
			||||||
                    </el-descriptions-item>
 | 
					                    </el-descriptions-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <el-descriptions-item :span="1" :label="$t('flow.procinstStatus')">
 | 
					                    <el-descriptions-item :span="1" :label="$t('flow.procinstStatus')">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                <el-table-column :label="$t('flow.approver')" min-width="100">
 | 
					                <el-table-column :label="$t('flow.approver')" min-width="100">
 | 
				
			||||||
                    <template #default="scope">
 | 
					                    <template #default="scope">
 | 
				
			||||||
                        <AccountInfo :username="scope.row.handler" />
 | 
					                        <AccountInfo :username="scope.row.handler || ''" />
 | 
				
			||||||
                    </template>
 | 
					                    </template>
 | 
				
			||||||
                </el-table-column>
 | 
					                </el-table-column>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ const props = defineProps({
 | 
				
			|||||||
    authCerts: {
 | 
					    authCerts: {
 | 
				
			||||||
        type: [Array<any>],
 | 
					        type: [Array<any>],
 | 
				
			||||||
        required: true,
 | 
					        required: true,
 | 
				
			||||||
 | 
					        default: () => [],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,7 @@ const props = defineProps({
 | 
				
			|||||||
    tags: {
 | 
					    tags: {
 | 
				
			||||||
        type: [Array<any>],
 | 
					        type: [Array<any>],
 | 
				
			||||||
        required: true,
 | 
					        required: true,
 | 
				
			||||||
 | 
					        default: () => [],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,10 +19,9 @@
 | 
				
			|||||||
                :default-expanded-keys="props.defaultExpandedKeys"
 | 
					                :default-expanded-keys="props.defaultExpandedKeys"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
                <template #default="{ node, data }">
 | 
					                <template #default="{ node, data }">
 | 
				
			||||||
                    <span
 | 
					                    <div
 | 
				
			||||||
                        :id="node.key"
 | 
					                        :id="node.key"
 | 
				
			||||||
                        @dblclick="treeNodeDblclick(data, node)"
 | 
					                        class="w-full node-container flex items-center 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">
 | 
				
			||||||
@@ -44,7 +43,7 @@
 | 
				
			|||||||
                        <span class="absolute right-2.5 mt-0.5 text-[10px] text-gray-400">
 | 
					                        <span class="absolute right-2.5 mt-0.5 text-[10px] text-gray-400">
 | 
				
			||||||
                            <slot :node="node" :data="data" name="suffix"></slot>
 | 
					                            <slot :node="node" :data="data" name="suffix"></slot>
 | 
				
			||||||
                        </span>
 | 
					                        </span>
 | 
				
			||||||
                    </span>
 | 
					                    </div>
 | 
				
			||||||
                </template>
 | 
					                </template>
 | 
				
			||||||
            </el-tree>
 | 
					            </el-tree>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -153,7 +152,16 @@ const loadNode = async (node: any, resolve: (data: any) => void, reject: () => v
 | 
				
			|||||||
    return resolve(nodes);
 | 
					    return resolve(nodes);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const treeNodeClick = async (data: any) => {
 | 
					let lastNodeClickTime = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const treeNodeClick = async (data: any, node: any) => {
 | 
				
			||||||
 | 
					    const currentClickNodeTime = Date.now();
 | 
				
			||||||
 | 
					    if (currentClickNodeTime - lastNodeClickTime < 300) {
 | 
				
			||||||
 | 
					        treeNodeDblclick(data, node);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    lastNodeClickTime = currentClickNodeTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!data.disabled && !data.type.nodeDblclickFunc && data.type.nodeClickFunc) {
 | 
					    if (!data.disabled && !data.type.nodeDblclickFunc && data.type.nodeClickFunc) {
 | 
				
			||||||
        emit('nodeClick', data);
 | 
					        emit('nodeClick', data);
 | 
				
			||||||
        await data.type.nodeClickFunc(data);
 | 
					        await data.type.nodeClickFunc(data);
 | 
				
			||||||
@@ -170,7 +178,6 @@ const treeNodeDblclick = (data: any, node: any) => {
 | 
				
			|||||||
        node.expand();
 | 
					        node.expand();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // emit('nodeDblick', data);
 | 
					 | 
				
			||||||
    if (!data.disabled && data.type.nodeDblclickFunc) {
 | 
					    if (!data.disabled && data.type.nodeDblclickFunc) {
 | 
				
			||||||
        data.type.nodeDblclickFunc(data);
 | 
					        data.type.nodeDblclickFunc(data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ import { Rules } from '@/common/rule';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
    instance: {
 | 
					    instance: {
 | 
				
			||||||
        type: [Boolean, Object],
 | 
					        type: [Boolean, Object, null],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    db: {
 | 
					    db: {
 | 
				
			||||||
        type: [Boolean, Object],
 | 
					        type: [Boolean, Object],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -365,7 +365,7 @@ const editDb = (data: any) => {
 | 
				
			|||||||
        state.dbEditDialog.data = { ...data };
 | 
					        state.dbEditDialog.data = { ...data };
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        state.dbEditDialog.data = {
 | 
					        state.dbEditDialog.data = {
 | 
				
			||||||
            instanceId: props.instance.id,
 | 
					            instanceId: props.instance?.id,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    state.dbEditDialog.title = data ? useI18nEditTitle('db.db') : useI18nCreateTitle('db.db');
 | 
					    state.dbEditDialog.title = data ? useI18nEditTitle('db.db') : useI18nCreateTitle('db.db');
 | 
				
			||||||
@@ -373,7 +373,7 @@ const editDb = (data: any) => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const confirmEditDb = async (db: any) => {
 | 
					const confirmEditDb = async (db: any) => {
 | 
				
			||||||
    db.instanceId = props.instance.id;
 | 
					    db.instanceId = props.instance?.id;
 | 
				
			||||||
    await dbApi.saveDb.request(db);
 | 
					    await dbApi.saveDb.request(db);
 | 
				
			||||||
    useI18nSaveSuccessMsg();
 | 
					    useI18nSaveSuccessMsg();
 | 
				
			||||||
    search();
 | 
					    search();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -155,7 +155,7 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    dbEditDialog: {
 | 
					    dbEditDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
        instance: null as any,
 | 
					        instance: {},
 | 
				
			||||||
        title: '',
 | 
					        title: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,10 +61,8 @@
 | 
				
			|||||||
            </el-form>
 | 
					            </el-form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                <el-button @click="onCancel()">{{ $t('common.cancel') }}</el-button>
 | 
					                <el-button @click="onCancel()">{{ $t('common.cancel') }}</el-button>
 | 
				
			||||||
                <el-button type="primary" :loading="saveBtnLoading" @click="onConfirm">{{ $t('common.confirm') }}</el-button>
 | 
					                <el-button type="primary" :loading="saveBtnLoading" @click="onConfirm">{{ $t('common.confirm') }}</el-button>
 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-drawer>
 | 
					        </el-drawer>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,20 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <el-dialog
 | 
					        <el-drawer
 | 
				
			||||||
            :title="title"
 | 
					            :title="title"
 | 
				
			||||||
            v-model="dialogVisible"
 | 
					            v-model="dialogVisible"
 | 
				
			||||||
            :close-on-click-modal="false"
 | 
					            :close-on-click-modal="false"
 | 
				
			||||||
            :before-close="cancel"
 | 
					            :before-close="onCancel"
 | 
				
			||||||
            :show-close="true"
 | 
					            :show-close="true"
 | 
				
			||||||
            :destroy-on-close="true"
 | 
					            :destroy-on-close="true"
 | 
				
			||||||
            width="1000px"
 | 
					            size="1000px"
 | 
				
			||||||
 | 
					            header-class="!mb-1"
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <el-form :model="form" :rules="rules" ref="scriptForm" label-width="auto">
 | 
					            <template #header>
 | 
				
			||||||
 | 
					                <DrawerHeader :header="title" :back="onCancel" />
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <el-form :model="form" :rules="rules" ref="scriptForm" label-position="top">
 | 
				
			||||||
                <el-form-item prop="name" :label="$t('common.name')" required>
 | 
					                <el-form-item prop="name" :label="$t('common.name')" required>
 | 
				
			||||||
                    <el-input v-model="form.name"></el-input>
 | 
					                    <el-input v-model="form.name"></el-input>
 | 
				
			||||||
                </el-form-item>
 | 
					                </el-form-item>
 | 
				
			||||||
@@ -22,6 +27,12 @@
 | 
				
			|||||||
                    <EnumSelect :enums="ScriptResultEnum" v-model="form.type" default-first-option />
 | 
					                    <EnumSelect :enums="ScriptResultEnum" v-model="form.type" default-first-option />
 | 
				
			||||||
                </el-form-item>
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <el-form-item prop="category" :label="$t('machine.category')">
 | 
				
			||||||
 | 
					                    <el-select v-model="form.category" filterable allow-create :placeholder="$t('machine.categoryTips')">
 | 
				
			||||||
 | 
					                        <el-option v-for="item in categorys" :key="item" :label="item" :value="item" />
 | 
				
			||||||
 | 
					                    </el-select>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <el-form-item class="!w-full">
 | 
					                <el-form-item class="!w-full">
 | 
				
			||||||
                    <template #label>
 | 
					                    <template #label>
 | 
				
			||||||
                        <el-tooltip placement="top">
 | 
					                        <el-tooltip placement="top">
 | 
				
			||||||
@@ -43,14 +54,12 @@
 | 
				
			|||||||
            </el-form>
 | 
					            </el-form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <el-button @click="onCancel()">{{ $t('common.cancel') }}</el-button>
 | 
				
			||||||
                    <el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
 | 
					                <el-button v-auth="'machine:script:save'" type="primary" :loading="btnLoading" @click="onConfirm">
 | 
				
			||||||
                    <el-button v-auth="'machine:script:save'" type="primary" :loading="btnLoading" @click="btnOk">
 | 
					 | 
				
			||||||
                    {{ $t('common.save') }}
 | 
					                    {{ $t('common.save') }}
 | 
				
			||||||
                </el-button>
 | 
					                </el-button>
 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-drawer>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,6 +73,7 @@ import SvgIcon from '@/components/svgIcon/index.vue';
 | 
				
			|||||||
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
 | 
					import EnumSelect from '@/components/enumselect/EnumSelect.vue';
 | 
				
			||||||
import { useI18nFormValidate, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
 | 
					import { useI18nFormValidate, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
 | 
				
			||||||
import { Rules } from '@/common/rule';
 | 
					import { Rules } from '@/common/rule';
 | 
				
			||||||
 | 
					import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
    data: {
 | 
					    data: {
 | 
				
			||||||
@@ -93,6 +103,7 @@ const rules = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const { isCommon, machineId } = toRefs(props);
 | 
					const { isCommon, machineId } = toRefs(props);
 | 
				
			||||||
const scriptForm: any = ref(null);
 | 
					const scriptForm: any = ref(null);
 | 
				
			||||||
 | 
					const categorys = ref([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    params: [] as any,
 | 
					    params: [] as any,
 | 
				
			||||||
@@ -104,6 +115,7 @@ const state = reactive({
 | 
				
			|||||||
        script: '',
 | 
					        script: '',
 | 
				
			||||||
        params: '',
 | 
					        params: '',
 | 
				
			||||||
        type: null,
 | 
					        type: null,
 | 
				
			||||||
 | 
					        category: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					    btnLoading: false,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
@@ -114,6 +126,9 @@ watch(props, (newValue: any) => {
 | 
				
			|||||||
    if (!dialogVisible.value) {
 | 
					    if (!dialogVisible.value) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    machineApi.scriptCategorys.request().then((res: any) => {
 | 
				
			||||||
 | 
					        categorys.value = res;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    if (newValue.data) {
 | 
					    if (newValue.data) {
 | 
				
			||||||
        state.form = { ...newValue.data };
 | 
					        state.form = { ...newValue.data };
 | 
				
			||||||
        if (state.form.params) {
 | 
					        if (state.form.params) {
 | 
				
			||||||
@@ -125,7 +140,7 @@ watch(props, (newValue: any) => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const btnOk = async () => {
 | 
					const onConfirm = async () => {
 | 
				
			||||||
    state.form.machineId = isCommon.value ? 9999999 : (machineId?.value as any);
 | 
					    state.form.machineId = isCommon.value ? 9999999 : (machineId?.value as any);
 | 
				
			||||||
    await useI18nFormValidate(scriptForm);
 | 
					    await useI18nFormValidate(scriptForm);
 | 
				
			||||||
    if (state.params) {
 | 
					    if (state.params) {
 | 
				
			||||||
@@ -134,11 +149,11 @@ const btnOk = async () => {
 | 
				
			|||||||
    machineApi.saveScript.request(state.form).then(() => {
 | 
					    machineApi.saveScript.request(state.form).then(() => {
 | 
				
			||||||
        useI18nSaveSuccessMsg();
 | 
					        useI18nSaveSuccessMsg();
 | 
				
			||||||
        emit('submitSuccess');
 | 
					        emit('submitSuccess');
 | 
				
			||||||
        cancel();
 | 
					        onCancel();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const cancel = () => {
 | 
					const onCancel = () => {
 | 
				
			||||||
    dialogVisible.value = false;
 | 
					    dialogVisible.value = false;
 | 
				
			||||||
    emit('cancel');
 | 
					    emit('cancel');
 | 
				
			||||||
    state.params = [];
 | 
					    state.params = [];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,6 +99,7 @@ import { DynamicFormDialog } from '@/components/dynamic-form';
 | 
				
			|||||||
import { SearchItem } from '@/components/SearchForm';
 | 
					import { SearchItem } from '@/components/SearchForm';
 | 
				
			||||||
import { useI18n } from 'vue-i18n';
 | 
					import { useI18n } from 'vue-i18n';
 | 
				
			||||||
import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nEditTitle } from '@/hooks/useI18n';
 | 
					import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nEditTitle } from '@/hooks/useI18n';
 | 
				
			||||||
 | 
					import { OptionsApi } from '@/components/SearchForm/index';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { t } = useI18n();
 | 
					const { t } = useI18n();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,11 +118,24 @@ const pageTableRef: Ref<any> = ref(null);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    searchItems: [SearchItem.select('type', 'common.type').withEnum(ScriptTypeEnum)],
 | 
					    searchItems: [
 | 
				
			||||||
 | 
					        SearchItem.select('type', 'common.type').withEnum(ScriptTypeEnum),
 | 
				
			||||||
 | 
					        SearchItem.select('category', 'machine.category').withOptionsApi(
 | 
				
			||||||
 | 
					            OptionsApi.new(machineApi.scriptCategorys, {}).withConvertFn((res) => {
 | 
				
			||||||
 | 
					                return res.map((x: any) => {
 | 
				
			||||||
 | 
					                    return {
 | 
				
			||||||
 | 
					                        label: x,
 | 
				
			||||||
 | 
					                        value: x,
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
    columns: [
 | 
					    columns: [
 | 
				
			||||||
        TableColumn.new('name', 'common.name'),
 | 
					        TableColumn.new('name', 'common.name'),
 | 
				
			||||||
        TableColumn.new('description', 'common.remark'),
 | 
					        TableColumn.new('description', 'common.remark'),
 | 
				
			||||||
        TableColumn.new('type', 'common.type').typeTag(ScriptResultEnum),
 | 
					        TableColumn.new('type', 'common.type').typeTag(ScriptResultEnum),
 | 
				
			||||||
 | 
					        TableColumn.new('category', 'machine.category'),
 | 
				
			||||||
        TableColumn.new('action', 'common.operation').isSlot().setMinWidth(140).alignCenter(),
 | 
					        TableColumn.new('action', 'common.operation').isSlot().setMinWidth(140).alignCenter(),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ export const machineApi = {
 | 
				
			|||||||
    // 删除机器
 | 
					    // 删除机器
 | 
				
			||||||
    del: Api.newDelete('/machines/{id}'),
 | 
					    del: Api.newDelete('/machines/{id}'),
 | 
				
			||||||
    scripts: Api.newGet('/machines/{machineId}/scripts'),
 | 
					    scripts: Api.newGet('/machines/{machineId}/scripts'),
 | 
				
			||||||
 | 
					    scriptCategorys: Api.newGet('/machines/scripts/categorys'),
 | 
				
			||||||
    runScript: Api.newGet('/machines/scripts/{scriptId}/{ac}/run'),
 | 
					    runScript: Api.newGet('/machines/scripts/{scriptId}/{ac}/run'),
 | 
				
			||||||
    saveScript: Api.newPost('/machines/{machineId}/scripts'),
 | 
					    saveScript: Api.newPost('/machines/{machineId}/scripts'),
 | 
				
			||||||
    deleteScript: Api.newDelete('/machines/{machineId}/scripts/{scriptId}'),
 | 
					    deleteScript: Api.newDelete('/machines/{machineId}/scripts/{scriptId}'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,6 +117,7 @@
 | 
				
			|||||||
                        </el-tab-pane>
 | 
					                        </el-tab-pane>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <el-tab-pane
 | 
					                        <el-tab-pane
 | 
				
			||||||
 | 
					                            class="h-full"
 | 
				
			||||||
                            :disabled="currentTag.type != TagResourceTypeEnum.Tag.value"
 | 
					                            :disabled="currentTag.type != TagResourceTypeEnum.Tag.value"
 | 
				
			||||||
                            :label="`Redis (${resourceCount.redis || 0})`"
 | 
					                            :label="`Redis (${resourceCount.redis || 0})`"
 | 
				
			||||||
                            :name="RedisTag"
 | 
					                            :name="RedisTag"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
    <div class="h-full">
 | 
					    <div class="h-full">
 | 
				
			||||||
        <page-table :page-api="logApi.list" :search-items="searchItems" v-model:query-form="query" :columns="columns">
 | 
					        <page-table :page-api="logApi.list" :search-items="searchItems" v-model:query-form="query" :columns="columns">
 | 
				
			||||||
            <template #creator="{ data }">
 | 
					            <template #creator="{ data }">
 | 
				
			||||||
                <account-info :username="data.creator" />
 | 
					                <account-info :username="data.creator || ''" />
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </page-table>
 | 
					        </page-table>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,11 +58,21 @@ const viteConfig: UserConfig = {
 | 
				
			|||||||
                entryFileNames: `assets/[name]-[hash].js`,
 | 
					                entryFileNames: `assets/[name]-[hash].js`,
 | 
				
			||||||
                chunkFileNames: `assets/[name]-[hash].js`,
 | 
					                chunkFileNames: `assets/[name]-[hash].js`,
 | 
				
			||||||
                assetFileNames: `assets/[name]-[hash].[ext]`,
 | 
					                assetFileNames: `assets/[name]-[hash].[ext]`,
 | 
				
			||||||
                compact: true,
 | 
					                advancedChunks: {
 | 
				
			||||||
                manualChunks: {
 | 
					                    groups: [
 | 
				
			||||||
                    vue: ['vue', 'vue-router', 'pinia'],
 | 
					                        {
 | 
				
			||||||
                    echarts: ['echarts'],
 | 
					                            name: 'vue',
 | 
				
			||||||
                    monaco: ['monaco-editor'],
 | 
					                            test: /(vue|vue-router|pinia)/i,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'echarts',
 | 
				
			||||||
 | 
					                            test: /(echarts)/i,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            name: 'monaco',
 | 
				
			||||||
 | 
					                            test: /(monaco-editor)/i,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,7 @@ func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, orderBy ...string) (*
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db) error {
 | 
					func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db) error {
 | 
				
			||||||
	// 查找是否存在
 | 
						// 查找是否存在
 | 
				
			||||||
	oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId}
 | 
						oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId, AuthCertName: dbEntity.AuthCertName}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	authCert, err := d.resourceAuthCertApp.GetAuthCert(dbEntity.AuthCertName)
 | 
						authCert, err := d.resourceAuthCertApp.GetAuthCert(dbEntity.AuthCertName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ type MachineScriptForm struct {
 | 
				
			|||||||
	Name        string `json:"name" binding:"required"`
 | 
						Name        string `json:"name" binding:"required"`
 | 
				
			||||||
	MachineId   uint64 `json:"machineId" binding:"required"`
 | 
						MachineId   uint64 `json:"machineId" binding:"required"`
 | 
				
			||||||
	Type        int    `json:"type" binding:"required"`
 | 
						Type        int    `json:"type" binding:"required"`
 | 
				
			||||||
 | 
						Category    string `json:"category"`
 | 
				
			||||||
	Description string `json:"description" binding:"required"`
 | 
						Description string `json:"description" binding:"required"`
 | 
				
			||||||
	Params      string `json:"params"`
 | 
						Params      string `json:"params"`
 | 
				
			||||||
	Script      string `json:"script" binding:"required"`
 | 
						Script      string `json:"script" binding:"required"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,8 @@ func (ms *MachineScript) ReqConfs() *req.Confs {
 | 
				
			|||||||
		// 获取指定机器脚本列表
 | 
							// 获取指定机器脚本列表
 | 
				
			||||||
		req.NewGet(":machineId/scripts", ms.MachineScripts),
 | 
							req.NewGet(":machineId/scripts", ms.MachineScripts),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req.NewGet("/scripts/categorys", ms.MachineScriptCategorys),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewPost(":machineId/scripts", ms.SaveMachineScript).Log(req.NewLogSave("机器-保存脚本")).RequiredPermissionCode("machine:script:save"),
 | 
							req.NewPost(":machineId/scripts", ms.SaveMachineScript).Log(req.NewLogSave("机器-保存脚本")).RequiredPermissionCode("machine:script:save"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewDelete(":machineId/scripts/:scriptId", ms.DeleteMachineScript).Log(req.NewLogSave("机器-删除脚本")).RequiredPermissionCode("machine:script:del"),
 | 
							req.NewDelete(":machineId/scripts/:scriptId", ms.DeleteMachineScript).Log(req.NewLogSave("机器-删除脚本")).RequiredPermissionCode("machine:script:del"),
 | 
				
			||||||
@@ -39,12 +41,18 @@ func (ms *MachineScript) ReqConfs() *req.Confs {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *MachineScript) MachineScripts(rc *req.Ctx) {
 | 
					func (m *MachineScript) MachineScripts(rc *req.Ctx) {
 | 
				
			||||||
	condition := &entity.MachineScript{MachineId: GetMachineId(rc)}
 | 
						condition := &entity.MachineScript{MachineId: GetMachineId(rc), Category: rc.Query("category")}
 | 
				
			||||||
	res, err := m.machineScriptApp.GetPageList(condition, rc.GetPageParam())
 | 
						res, err := m.machineScriptApp.GetPageList(condition, rc.GetPageParam())
 | 
				
			||||||
	biz.ErrIsNil(err)
 | 
						biz.ErrIsNil(err)
 | 
				
			||||||
	rc.ResData = model.PageResultConv[*entity.MachineScript, *vo.MachineScriptVO](res)
 | 
						rc.ResData = model.PageResultConv[*entity.MachineScript, *vo.MachineScriptVO](res)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *MachineScript) MachineScriptCategorys(rc *req.Ctx) {
 | 
				
			||||||
 | 
						res, err := m.machineScriptApp.GetScriptCategorys(rc.MetaCtx)
 | 
				
			||||||
 | 
						biz.ErrIsNil(err)
 | 
				
			||||||
 | 
						rc.ResData = res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *MachineScript) SaveMachineScript(rc *req.Ctx) {
 | 
					func (m *MachineScript) SaveMachineScript(rc *req.Ctx) {
 | 
				
			||||||
	form, machineScript := req.BindJsonAndCopyTo[*form.MachineScriptForm, *entity.MachineScript](rc)
 | 
						form, machineScript := req.BindJsonAndCopyTo[*form.MachineScriptForm, *entity.MachineScript](rc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,6 +49,7 @@ type MachineScriptVO struct {
 | 
				
			|||||||
	Name        *string `json:"name"`
 | 
						Name        *string `json:"name"`
 | 
				
			||||||
	Script      *string `json:"script"`
 | 
						Script      *string `json:"script"`
 | 
				
			||||||
	Type        *int    `json:"type"`
 | 
						Type        *int    `json:"type"`
 | 
				
			||||||
 | 
						Category    string  `json:"category"`
 | 
				
			||||||
	Description *string `json:"description"`
 | 
						Description *string `json:"description"`
 | 
				
			||||||
	Params      *string `json:"params"`
 | 
						Params      *string `json:"params"`
 | 
				
			||||||
	MachineId   *uint64 `json:"machineId"`
 | 
						MachineId   *uint64 `json:"machineId"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ import (
 | 
				
			|||||||
	"mayfly-go/pkg/base"
 | 
						"mayfly-go/pkg/base"
 | 
				
			||||||
	"mayfly-go/pkg/errorx"
 | 
						"mayfly-go/pkg/errorx"
 | 
				
			||||||
	"mayfly-go/pkg/model"
 | 
						"mayfly-go/pkg/model"
 | 
				
			||||||
 | 
						"mayfly-go/pkg/utils/collx"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MachineScript interface {
 | 
					type MachineScript interface {
 | 
				
			||||||
@@ -15,11 +16,16 @@ type MachineScript interface {
 | 
				
			|||||||
	// 分页获取机器脚本信息列表
 | 
						// 分页获取机器脚本信息列表
 | 
				
			||||||
	GetPageList(condition *entity.MachineScript, pageParam model.PageParam, orderBy ...string) (*model.PageResult[*entity.MachineScript], error)
 | 
						GetPageList(condition *entity.MachineScript, pageParam model.PageParam, orderBy ...string) (*model.PageResult[*entity.MachineScript], error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// GetScriptCategorys 获取脚本分类
 | 
				
			||||||
 | 
						GetScriptCategorys(ctx context.Context) ([]string, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Save(ctx context.Context, entity *entity.MachineScript) error
 | 
						Save(ctx context.Context, entity *entity.MachineScript) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Delete(ctx context.Context, id uint64)
 | 
						Delete(ctx context.Context, id uint64)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ (MachineScript) = (*machineScriptAppImpl)(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type machineScriptAppImpl struct {
 | 
					type machineScriptAppImpl struct {
 | 
				
			||||||
	base.AppImpl[*entity.MachineScript, repository.MachineScript]
 | 
						base.AppImpl[*entity.MachineScript, repository.MachineScript]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,6 +39,15 @@ func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, page
 | 
				
			|||||||
	return m.GetRepo().GetPageList(condition, pageParam, orderBy...)
 | 
						return m.GetRepo().GetPageList(condition, pageParam, orderBy...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *machineScriptAppImpl) GetScriptCategorys(ctx context.Context) ([]string, error) {
 | 
				
			||||||
 | 
						scripts, err := m.ListByCond(new(entity.MachineScript), "category")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return collx.ArrayRemoveBlank(collx.ArrayDeduplicate(collx.ArrayMap(scripts, func(script *entity.MachineScript) string { return script.Category }))), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 保存机器脚本
 | 
					// 保存机器脚本
 | 
				
			||||||
func (m *machineScriptAppImpl) Save(ctx context.Context, ms *entity.MachineScript) error {
 | 
					func (m *machineScriptAppImpl) Save(ctx context.Context, ms *entity.MachineScript) error {
 | 
				
			||||||
	// 如果机器id不为公共脚本id,则校验机器是否存在
 | 
						// 如果机器id不为公共脚本id,则校验机器是否存在
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ type MachineScript struct {
 | 
				
			|||||||
	Name        string `json:"name" gorm:"not null;size:255;comment:脚本名"`     // 脚本名
 | 
						Name        string `json:"name" gorm:"not null;size:255;comment:脚本名"`     // 脚本名
 | 
				
			||||||
	MachineId   uint64 `json:"machineId" gorm:"not null;comment:机器id[0:公共]"`  // 机器id
 | 
						MachineId   uint64 `json:"machineId" gorm:"not null;comment:机器id[0:公共]"`  // 机器id
 | 
				
			||||||
	Type        int    `json:"type" gorm:"comment:脚本类型[1: 有结果;2:无结果;3:实时交互]"` // 脚本类型[1: 有结果;2:无结果;3:实时交互]
 | 
						Type        int    `json:"type" gorm:"comment:脚本类型[1: 有结果;2:无结果;3:实时交互]"` // 脚本类型[1: 有结果;2:无结果;3:实时交互]
 | 
				
			||||||
 | 
						Category    string `json:"category" gorm:"size:20;comment:分类"`
 | 
				
			||||||
	Description string `json:"description" gorm:"size:255;comment:脚本描述"` // 脚本描述
 | 
						Description string `json:"description" gorm:"size:255;comment:脚本描述"` // 脚本描述
 | 
				
			||||||
	Params      string `json:"params" gorm:"size:500;comment:脚本入参"`      // 参数列表json
 | 
						Params      string `json:"params" gorm:"size:500;comment:脚本入参"`      // 参数列表json
 | 
				
			||||||
	Script      string `json:"script" gorm:"type:text;comment:脚本内容"`     // 脚本内容
 | 
						Script      string `json:"script" gorm:"type:text;comment:脚本内容"`     // 脚本内容
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ import "fmt"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	AppName = "mayfly-go"
 | 
						AppName = "mayfly-go"
 | 
				
			||||||
	Version = "v1.10.0"
 | 
						Version = "v1.10.1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetAppInfo() string {
 | 
					func GetAppInfo() string {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package migrations
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	esentity "mayfly-go/internal/es/domain/entity"
 | 
						esentity "mayfly-go/internal/es/domain/entity"
 | 
				
			||||||
	flowentity "mayfly-go/internal/flow/domain/entity"
 | 
						flowentity "mayfly-go/internal/flow/domain/entity"
 | 
				
			||||||
 | 
						machineentity "mayfly-go/internal/machine/domain/entity"
 | 
				
			||||||
	sysentity "mayfly-go/internal/sys/domain/entity"
 | 
						sysentity "mayfly-go/internal/sys/domain/entity"
 | 
				
			||||||
	"mayfly-go/pkg/model"
 | 
						"mayfly-go/pkg/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -14,6 +15,7 @@ import (
 | 
				
			|||||||
func V1_10() []*gormigrate.Migration {
 | 
					func V1_10() []*gormigrate.Migration {
 | 
				
			||||||
	var migrations []*gormigrate.Migration
 | 
						var migrations []*gormigrate.Migration
 | 
				
			||||||
	migrations = append(migrations, V1_10_0()...)
 | 
						migrations = append(migrations, V1_10_0()...)
 | 
				
			||||||
 | 
						migrations = append(migrations, V1_10_1()...)
 | 
				
			||||||
	return migrations
 | 
						return migrations
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -132,3 +134,22 @@ func V1_10_0() []*gormigrate.Migration {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func V1_10_1() []*gormigrate.Migration {
 | 
				
			||||||
 | 
						return []*gormigrate.Migration{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ID: "20250610-v1.10.1",
 | 
				
			||||||
 | 
								Migrate: func(tx *gorm.DB) error {
 | 
				
			||||||
 | 
									if !tx.Migrator().HasColumn(&machineentity.MachineScript{}, "category") {
 | 
				
			||||||
 | 
										if err := tx.Migrator().AddColumn(&machineentity.MachineScript{}, "category"); err != nil {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Rollback: func(tx *gorm.DB) error {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user