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