commit:流程支持自动化任务

This commit is contained in:
Jerry
2024-10-11 21:42:49 +08:00
parent 9a1b811a76
commit 32c31fd4df
52 changed files with 4093 additions and 309 deletions

View File

@@ -52,6 +52,7 @@ declare module 'vue' {
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRadio: typeof import('element-plus/es')['ElRadio']

View File

@@ -0,0 +1,53 @@
import { BaseController } from '@/api/BaseController';
import { RequestOption } from '@/common/http/types';
import { ANY_OBJECT } from '@/types/generic';
import { TableData } from '@/common/types/table';
import { DBLink } from '@/types/online/dblink';
import { TableInfo } from '@/types/online/table';
import { API_CONTEXT } from '../config';
export default class FlowDblinkController extends BaseController {
static list(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.post<TableData<DBLink>>(
API_CONTEXT + '/flow/flowDblink/list',
params,
httpOptions,
);
}
static listDblinkTables(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.get<TableInfo[]>(
API_CONTEXT + '/flow/flowDblink/listDblinkTables',
params,
httpOptions,
);
}
static listDblinkTableColumns(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.get<ANY_OBJECT[]>(
API_CONTEXT + '/flow/flowDblink/listDblinkTableColumns',
params,
httpOptions,
);
}
static view(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.get<DBLink>(API_CONTEXT + '/flow/flowDblink/view', params, httpOptions);
}
static add(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.post(API_CONTEXT + '/flow/flowDblink/add', params, httpOptions);
}
static update(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.post(API_CONTEXT + '/flow/flowDblink/update', params, httpOptions);
}
static delete(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.post(API_CONTEXT + '/flow/flowDblink/delete', params, httpOptions);
}
static testConnection(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.get(API_CONTEXT + '/flow/flowDblink/testConnection', params, httpOptions);
}
}

View File

@@ -286,4 +286,8 @@ export default class FlowOperationController extends BaseController {
httpOptions,
);
}
// 启动自动化任务
static startAutoTask(params: ANY_OBJECT, httpOptions?: RequestOption) {
return super.post(API_CONTEXT + '/flow/flowOperation/startAuto', params, httpOptions);
}
}

View File

@@ -2,10 +2,12 @@ import FlowOperationController from './FlowOperationController';
import FlowDictionaryController from './FlowDictionaryController';
import FlowEntryController from './FlowEntryController';
import FlowEntryVariableController from './FlowEntryVariableController';
import FlowDblinkController from './FlowDblinkController';
export {
FlowOperationController,
FlowEntryController,
FlowDictionaryController,
FlowEntryVariableController,
FlowDblinkController,
};

View File

@@ -293,8 +293,7 @@ export const downloadBlob = (
commonRequest<Blob>(requestUrl(url), params, method, options, axiosOption)
.then(res => {
if (res instanceof Blob) {
const blobData = new Blob([res.data], { type: 'application/octet-stream' });
resolve(blobData);
resolve(res);
} else {
console.warn('下载文件失败', res);
reject(new Error('下载文件失败'));

View File

@@ -1,8 +1,5 @@
// eslint-disable-next-line import/namespace
import * as generatedDict from './generated';
import * as baseDict from './index';
export default {
...baseDict,
...generatedDict,
};

View File

@@ -164,6 +164,16 @@ const SysFlowVariableType = new DictionaryBase('工作流变量类型', [
name: '任务变量',
symbol: 'TASK',
},
{
id: 2,
name: '系统内置变量',
symbol: 'SYSTEM',
},
{
id: 4,
name: '自定义变量',
symbol: 'CUSTOM',
},
]);
const SysFlowWorkOrderStatus = new DictionaryBase('工单状态', [
@@ -340,6 +350,64 @@ const SysAutoCodeType = new DictionaryBase('自动编码类型', [
symbol: 'SECONDS',
},
]);
const FlowEntryType = new DictionaryBase('流程类型', [
{
id: 0,
name: '审批流程',
symbol: 'NORMAL',
},
{
id: 1,
name: '自动化任务',
symbol: 'AUTO_TASK',
},
]);
const AutoTaskValueType = new DictionaryBase('自动化任务值类型', [
{
id: 0,
name: '固定值',
symbol: 'FIXED',
},
{
id: 1,
name: '源表字段',
symbol: 'FIELD',
},
{
id: 2,
name: '流程变量',
symbol: 'VARIABLE',
},
]);
const AutoTaskActionType = new DictionaryBase('自动化任务动作类型', [
{
id: 0,
name: '数据插入',
symbol: 'INSERT',
},
{
id: 1,
name: '数据更新',
symbol: 'UPDATE',
},
{
id: 2,
name: '数据删除',
symbol: 'DELETE',
},
{
id: 3,
name: '数据查询',
symbol: 'QUERY_SINGLE_DATA',
},
{
id: 10,
name: 'HTTP请求',
symbol: 'HTTP',
},
]);
export {
SysFlowEntryPublishedStatus,
@@ -353,4 +421,7 @@ export {
DiagramType,
FlowNodeType,
SysAutoCodeType,
FlowEntryType,
AutoTaskValueType,
AutoTaskActionType,
};

View File

@@ -924,6 +924,68 @@ const DblinkType = new DictionaryBase('数据库连接类型', [
*/
]);
const CriteriaFilterType = new DictionaryBase('条件过滤类型', [
{
id: 0,
name: '等于',
symbol: 'EQ',
},
{
id: 1,
name: '不等于',
symbol: 'NOT_EQ',
},
{
id: 2,
name: '大于等于',
symbol: 'GE',
},
{
id: 3,
name: '大于',
symbol: 'GT',
},
{
id: 4,
name: '小于等于',
symbol: 'LE',
},
{
id: 5,
name: '小于',
symbol: 'LT',
},
{
id: 6,
name: 'LIKE',
symbol: 'LIKE',
},
{
id: 7,
name: 'IN',
symbol: 'IN',
},
{
id: 8,
name: 'NOT IN',
symbol: 'NOT_IN',
},
{
id: 9,
name: 'BETWEEN',
symbol: 'BETWEEN',
},
{
id: 100,
name: '不为空',
symbol: 'NOT_NULL',
},
{
id: 101,
name: '为空',
symbol: 'IS_NULL',
},
]);
export {
SysUserStatus,
SysUserType,
@@ -943,4 +1005,5 @@ export {
SysCustomWidgetBindDataType,
DirectionType,
DblinkType,
CriteriaFilterType,
};

View File

@@ -66,11 +66,6 @@ const widgetId = ref(getUUID());
const selectedItems = ref<ANY_OBJECT[]>([]);
const pps = computed(() => props.props);
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdSelectDept/' + widgetId.value && data.isSuccess) {
handlerEditOperate(data.data);
}
};
const handlerEditOperate = (items: Ref<ANY_OBJECT>) => {
selectedItems.value = [];
if (props.multiple) {
@@ -187,10 +182,6 @@ watch(
immediate: true,
},
);
defineExpose({
refreshData,
});
</script>
<style scoped>

View File

@@ -103,11 +103,11 @@ import { onBeforeUnmount, shallowRef } from 'vue';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import { ANY_OBJECT } from '@/types/generic';
const emit = defineEmits<{ 'update:value': [string | undefined] }>();
const emit = defineEmits<{ 'update:modelValue': [string | undefined] }>();
const props = withDefaults(
defineProps<{
value?: string;
modelValue?: string;
editorConfig?: ANY_OBJECT;
toolbarConfig?: ANY_OBJECT;
height?: string;
@@ -127,16 +127,7 @@ const props = withDefaults(
const editorRef = shallowRef();
const mode = ref('default');
// 内容 HTML
const valueHtml = computed({
get() {
return props.value;
},
set(val) {
console.log('richeditor value input', val);
emit('update:value', val);
},
});
const valueHtml = ref(props.modelValue);
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
@@ -147,16 +138,17 @@ onBeforeUnmount(() => {
const handleCreated = (editor: ANY_OBJECT) => {
editorRef.value = editor; // 记录 editor 实例,重要!
editor.setHtml(valueHtml.value);
console.log('editor', editor);
console.log(editor.getAllMenuKeys());
};
watch(
() => props.value,
() => props.modelValue,
newValue => {
if (editorRef.value && newValue !== editorRef.value.txt.html())
editorRef.value.txt.html(newValue);
if (newValue !== valueHtml.value) {
valueHtml.value = newValue;
}
},
{
deep: true,
@@ -164,8 +156,15 @@ watch(
},
);
watch(
() => valueHtml.value,
newValue => {
emit('update:modelValue', newValue);
},
);
const getHtml = () => {
return editorRef.value ? editorRef.value.txt.html() : undefined;
return editorRef.value ? editorRef.value.getHtml() : undefined;
};
defineExpose({ getHtml });

View File

@@ -65,11 +65,6 @@ const pps = withDefaults(
const widgetId = ref(getUUID());
const selectedItems = ref<ANY_OBJECT[]>([]);
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdSelectUser/' + widgetId.value && data.isSuccess) {
handlerEditOperate(data.data);
}
};
const handlerEditOperate = (items: Ref<ANY_OBJECT>) => {
selectedItems.value = [];
if (pps.multiple) {
@@ -194,10 +189,6 @@ watch(
immediate: true,
},
);
defineExpose({
refreshData,
});
</script>
<style scoped>

View File

@@ -30,7 +30,12 @@
/>
</el-row>
<el-row v-if="inputWidgetType === SysCustomWidgetType.Radio" type="flex" align="middle">
<el-radio-group size="default" v-model="valNum" v-bind="attributeProps" @change="onValueChange">
<el-radio-group
size="default"
v-model="valNum"
v-bind="attributeProps"
@change="onValueChange"
>
<el-radio-button
v-for="item in dropdownData"
:key="item.id"

View File

@@ -76,13 +76,6 @@ const dictId = computed({
},
});
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditDictParamValue' && data.isSuccess) {
handlerEditOperate(data.rowData, data.data);
}
};
defineExpose({ refreshData });
const onDictChange = (val: ANY_OBJECT) => {
emitChange({
dictId: val,

View File

@@ -88,11 +88,4 @@ const onRemoveTableColumn = (row: ANY_OBJECT) => {
console.warn(e);
});
};
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditOnlineListOrder' && data.isSuccess) {
handlerEditOperate(data.rowData, data.data);
}
};
defineExpose({ refreshData });
</script>

View File

@@ -75,10 +75,4 @@ const onRemoveTableColumn = (row: ANY_OBJECT) => {
console.warn(e);
});
};
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditOnlineMobileNumberRangeQuick' && data.isSuccess) {
handlerEditOperate(data.rowData, data.data);
}
};
defineExpose({ refreshData });
</script>

View File

@@ -91,11 +91,4 @@ const onRemoveTableColumn = (row: ANY_OBJECT) => {
console.warn(e);
});
};
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditOnlineTableColumn' && data.isSuccess) {
handlerEditOperate(data.rowData, data.data);
}
};
defineExpose({ refreshData });
</script>

View File

@@ -1,5 +1,3 @@
import { ANY_OBJECT } from '@/types/generic';
import { SysCustomWidgetType } from '@/common/staticDict/index';
import blockConfig from './customBlock';
import baseCardConfig from './baseCard';
import tabsConfig from './tabs';
@@ -23,6 +21,9 @@ import richEditorConfig from './richEditor';
import tableConfig from './table';
import linkConfig from './link';
import treeConfig from './tree';
import { ANY_OBJECT } from '@/types/generic';
import { SysCustomWidgetType, SysCustomWidgetBindDataType } from '@/common/staticDict/index';
import { SysCustomWidgetBindValueType } from '@/common/staticDict/online';
const formWidgetGroupList: ANY_OBJECT = {
pc: [
@@ -231,9 +232,14 @@ function getWidgetObject(widget: ANY_OBJECT): ANY_OBJECT {
// ...widget,
widgetType: widget.widgetType,
bindData: {
//...bindDataConfig,
dataType: SysCustomWidgetBindDataType.Column,
defaultValue: {
//...bindDataConfig.defaultValue,
valueType: SysCustomWidgetBindValueType.INPUT_DATA,
// 默认值是字典字典ID
dictId: undefined,
value: undefined,
// 内置系统变量
systemVariable: undefined,
},
},
operationList: widget.operationList

View File

@@ -28,13 +28,6 @@ const formConfig = inject('formConfig', () => {
return {} as ANY_OBJECT;
});
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditOnlineTabPanel' && data.isSuccess) {
handlerEditOperate(data.rowData, data.data);
}
};
defineExpose({ refreshData });
const handlerEditOperate = (row: ANY_OBJECT | null, res: ANY_OBJECT) => {
if (row == null) {
res = createTabPanel(res);

View File

@@ -30,13 +30,6 @@ const formConfig = inject('formConfig', () => {
return {} as ANY_OBJECT;
});
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditOnlineTableColumn' && data.isSuccess) {
handlerEditOperate(data.rowData, data.data);
}
};
defineExpose({ refreshData });
const emit = defineEmits<{ 'update:value': [ANY_OBJECT[]] }>();
const handlerEditOperate = (row: ANY_OBJECT | null, res: ANY_OBJECT) => {
let tempList: ANY_OBJECT[] = [];

View File

@@ -331,15 +331,6 @@ watch(
deep: true,
},
);
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdTaskUserSelect' && data.isSuccess) {
updateSelectUser(data.data);
} else if (data.path === 'thirdTaskGroupSelect' && data.isSuccess) {
updateSelectDept(data.data);
}
};
defineExpose({ refreshData });
</script>
<style scoped>

View File

@@ -383,13 +383,6 @@ onBeforeUnmount(() => {
postMap = null;
deptPostMap = null;
});
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdAddCopyForItem' && data.isSuccess) {
updateEditCopyForItem(data.data);
}
};
defineExpose({ refreshData });
</script>
<style lang="scss" scoped>

View File

@@ -21,6 +21,8 @@
:bpmn-modeler="modeler"
:prefix="controlForm.prefix"
:width="600"
:autoTaskVariableList="autoTaskVariableList"
:flowVariableList="flowVariableList"
class="process-panel"
/>
</div>
@@ -63,6 +65,9 @@ const controlForm = ref<ANY_OBJECT>({
additionalModel: [CustomContentPadProvider, CustomPaletteProvider],
});
const autoTaskVariableList = ref<ANY_OBJECT[]>([]);
const flowVariableList = ref<ANY_OBJECT[]>([]);
const elementClick = (element: ANY_OBJECT) => {
console.log('ProcessDesigner main', element);
};

View File

@@ -371,13 +371,6 @@ watch(
deep: true,
},
);
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdTaskUserSelect' && data.isSuccess) {
updateSelectAssignee(data.data);
}
};
defineExpose({ refreshData });
</script>
<style scoped>

View File

@@ -80,6 +80,7 @@ watch(
<style lang="scss" scoped>
.task-multiple-select {
:deep(.el-tag) {
padding-right: 4px;
margin-right: 8px;
color: #666;
background-color: #f6f6f6;

View File

@@ -108,13 +108,6 @@ const emitChange = () => {
emit('change', tempValue);
//emit('input', tempValue);
};
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdSelectUserTask/' + widgetId && data.isSuccess) {
handlerEditOperate(data.data);
}
};
defineExpose({ refreshData });
</script>
<style scoped>

View File

@@ -102,7 +102,6 @@ import { useTable } from '@/common/hooks/useTable';
import { TableOptions } from '@/common/types/pagination';
import { ANY_OBJECT } from '@/types/generic';
import FlowCategoryController from '@/api/flow/FlowCategoryController';
import { usePermissions } from '@/common/hooks/usePermission';
import { useDate } from '@/common/hooks/useDate';
import { useLayoutStore } from '@/store';
import formEditFlowCategory from './formEditFlowCategory.vue';
@@ -180,10 +179,6 @@ const refreshFormFlowCategory = (reloadData = false) => {
}
formFlowCategory.isInit = true;
};
const refreshData = () => {
refreshFormFlowCategory();
};
const onReset = () => {
form.value.resetFields();
refreshFormFlowCategory(true);
@@ -286,7 +281,6 @@ onMounted(() => {
});
defineExpose({
refreshData,
onResume,
});
</script>

View File

@@ -17,11 +17,13 @@
>基础信息</StepBarItem
>
<StepBarItem
v-if="formFlowEntryData.flowType === FlowEntryType.NORMAL"
icon="online-icon icon-operator"
:name="SysFlowEntryStep.PROCESS_VARIABLE"
>流程变量</StepBarItem
>
<StepBarItem
v-if="formFlowEntryData.flowType === FlowEntryType.NORMAL"
icon="online-icon icon-flow-stauts"
:name="SysFlowEntryStep.PROCESS_STATUS"
>流程状态</StepBarItem
@@ -98,6 +100,19 @@
>
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="流程类型" prop="flowType">
<el-radio-group v-model="formFlowEntryData.flowType" :disabled="isEdit">
<el-radio
v-for="item in FlowEntryType.getList()"
:key="item.id"
:label="item.id"
>
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formFlowEntryData.flowType === FlowEntryType.NORMAL">
<el-form-item label="表单类型" prop="bindFormType">
<el-select
v-model="formFlowEntryData.bindFormType"
@@ -127,7 +142,10 @@
</el-col>
<el-col :span="24">
<el-form-item label="流程标识" prop="processDefinitionKey">
<el-input v-model="formFlowEntryData.processDefinitionKey" :disabled="isEdit" />
<el-input
v-model="formFlowEntryData.processDefinitionKey"
:disabled="isEdit"
/>
</el-form-item>
</el-col>
<el-col :span="24">
@@ -147,7 +165,7 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="24" v-if="formFlowEntryData.flowType === FlowEntryType.NORMAL">
<el-form-item label="工单编码">
<el-row type="flex" align="middle" style="flex-wrap: nowrap">
<el-input
@@ -157,7 +175,9 @@
:disabled="!formFlowEntryData.encodedRule.calculateWhenView"
>
<template v-slot:prepend>
<el-checkbox v-model="formFlowEntryData.encodedRule.calculateWhenView" />
<el-checkbox
v-model="formFlowEntryData.encodedRule.calculateWhenView"
/>
</template>
</el-input>
<el-select
@@ -191,7 +211,10 @@
</el-col>
<el-col
:span="24"
v-if="formFlowEntryData.bindFormType === SysFlowEntryBindFormType.ONLINE_FORM"
v-if="
formFlowEntryData.bindFormType === SysFlowEntryBindFormType.ONLINE_FORM &&
formFlowEntryData.flowType === FlowEntryType.NORMAL
"
>
<el-form-item label="流程页面" prop="pageId">
<el-select
@@ -213,7 +236,10 @@
</el-col>
<el-col
:span="24"
v-if="formFlowEntryData.bindFormType === SysFlowEntryBindFormType.ONLINE_FORM"
v-if="
formFlowEntryData.bindFormType === SysFlowEntryBindFormType.ONLINE_FORM &&
formFlowEntryData.flowType === FlowEntryType.NORMAL
"
>
<el-form-item label="默认表单" prop="defaultFormId">
<el-select
@@ -233,7 +259,10 @@
</el-col>
<el-col
:span="24"
v-if="formFlowEntryData.bindFormType === SysFlowEntryBindFormType.ROUTER_FORM"
v-if="
formFlowEntryData.bindFormType === SysFlowEntryBindFormType.ROUTER_FORM &&
formFlowEntryData.flowType === FlowEntryType.NORMAL
"
>
<el-form-item label="默认表单" prop="defaultRouterName">
<el-input
@@ -243,7 +272,7 @@
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="12" v-if="formFlowEntryData.flowType === FlowEntryType.NORMAL">
<el-form-item label="通知类型">
<el-select
v-model="formFlowEntryData.notifyTypes"
@@ -255,12 +284,19 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="12" v-if="formFlowEntryData.flowType === FlowEntryType.NORMAL">
<el-form-item label="级联删除业务数据" label-width="128px">
<el-switch v-model="formFlowEntryData.cascadeDeleteBusinessData" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="isEdit && shareFormList.length > 0">
<el-col
:span="24"
v-if="
isEdit &&
shareFormList.length > 0 &&
formFlowEntryData.flowType === FlowEntryType.NORMAL
"
>
<el-form-item label="工单分享">
<el-row type="flex">
<el-button
@@ -454,6 +490,7 @@ import {
SysFlowEntryBindFormType,
SysFlowEntryStep,
SysFlowVariableType,
FlowEntryType,
} from '@/common/staticDict/flow';
import { SysOnlineFormType } from '@/common/staticDict/index';
import { ANY_OBJECT } from '@/types/generic';
@@ -499,6 +536,7 @@ const formFlowEntryData = ref<ANY_OBJECT>({
entryId: undefined,
processDefinitionName: undefined,
processDefinitionKey: undefined,
flowType: FlowEntryType.NORMAL,
categoryId: undefined,
bindFormType: SysFlowEntryBindFormType.ROUTER_FORM,
pageId: undefined,
@@ -537,6 +575,7 @@ const formRules: Partial<Record<string, Arrayable<FormItemRule>>> = {
],
processDefinitionName: [{ required: true, message: '流程名称不能为空!', trigger: 'blur' }],
categoryId: [{ required: true, message: '流程分类不能为空!', trigger: 'blur' }],
flowType: [{ required: true, message: '流程类型不能为空!', trigger: 'blur' }],
pageId: [{ required: true, message: '流程页面不能为空!', trigger: 'blur' }],
defaultFormId: [
{
@@ -650,7 +689,11 @@ const onPrevClick = () => {
activeStep.value = SysFlowEntryStep.PROCESS_VARIABLE;
break;
case SysFlowEntryStep.PROCESS_DESIGN:
if (formFlowEntryData.value.flowType === FlowEntryType.AUTO_TASK) {
activeStep.value = SysFlowEntryStep.BASIC;
} else {
activeStep.value = SysFlowEntryStep.PROCESS_STATUS;
}
break;
}
};
@@ -738,7 +781,9 @@ const loadDatasourceAllColumnList = (res: ResponseDataType<TableData<ANY_OBJECT>
// 获取流程绑定页面数据源信息
const initFlowDatasourceInfo = () => {
return new Promise((resolve, reject) => {
if (entryDatasource != null) return resolve(null);
if (entryDatasource != null || formFlowEntryData.value.flowType === FlowEntryType.AUTO_TASK) {
return resolve(null);
}
if (formFlowEntryData.value.bindFormType === SysFlowEntryBindFormType.ONLINE_FORM) {
OnlinePageController.listOnlinePageDatasource({
pageId: formFlowEntryData.value.pageId,
@@ -819,12 +864,6 @@ const onNextClick = () => {
entryBasicInfo.value.validate((valid: boolean) => {
if (!valid) return;
if (formFlowEntryData.value.encodedRule.calculateWhenView) {
/*
if (formFlowEntryData.value.encodedRule.prefix == null || formFlowEntryData.value.encodedRule.prefix === '') {
ElMessage.error('工单编码前缀不能为空!');
return;
}
*/
if (
formFlowEntryData.value.encodedRule.precisionTo == null ||
formFlowEntryData.value.encodedRule.precisionTo === ''
@@ -845,6 +884,11 @@ const onNextClick = () => {
.then(res => {
if (!isEdit.value) formFlowEntryData.value.entryId = res.data;
ElMessage.success('保存成功');
// 自动化任务直接跳转到流程设计页面
if (formFlowEntryData.value.flowType === FlowEntryType.AUTO_TASK) {
activeStep.value = SysFlowEntryStep.PROCESS_DESIGN;
return;
}
// 获取流程页面数据源信息
initFlowDatasourceInfo()
.then(() => {
@@ -900,8 +944,8 @@ const onBindFormTypeChange = () => {
};
// 流程绑定表单页面改变
const onEntryPageChange = () => {
formFlowEntryData.value.defaultFormId = undefined;
defaultFormIdWidget.setDirty(true);
formFlowEntryData.value.defaultFormId = undefined;
entryDatasource = null;
};
const getFormShareInfo = (form: ANY_OBJECT) => {
@@ -1088,6 +1132,7 @@ const initFlowEntryInfo = () => {
processDefinitionName: undefined,
processDefinitionKey: undefined,
categoryId: undefined,
flowType: FlowEntryType.NORMAL,
bindFormType: SysFlowEntryBindFormType.ONLINE_FORM,
pageId: undefined,
defaultFormId: undefined,
@@ -1157,24 +1202,6 @@ onMounted(() => {
provide('flowEntry', () => formFlowEntryData);
provide('formList', () => (defaultFormIdWidget ? defaultFormIdWidget.dropdownList : []));
provide('allVariableList', () => processVariableList);
// 获取流程绑定页面数据源信息
// const initFlowEntryDatasourceInfo = (entryId: string) => {
// return FlowEntryController.viewDatasource({
// entryId,
// });
// };
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdFormEditFlowEntryVariable' && data.isSuccess) {
loadEntryVariableList();
} else if (data.path === 'thirdFormEditFlowEntryStatus' && data.isSuccess) {
formFlowEntryData.value.extensionData.approvalStatusDict = [...data.data];
}
};
defineExpose({
refreshData,
});
</script>
<style scoped>

View File

@@ -27,6 +27,22 @@
/>
</el-select>
</el-form-item>
<el-form-item label="流程类型" prop="formFilter.flowType">
<el-select
class="filter-item"
v-model="formFlowEntry.formFilter.flowType"
:clearable="true"
filterable
placeholder="流程类型"
>
<el-option
v-for="item in FlowEntryType.getList()"
:key="item.id"
:value="item.id"
:label="item.name"
/>
</el-select>
</el-form-item>
<el-form-item label="流程名称" prop="formFilter.processDefinitionName">
<el-input
class="filter-item"
@@ -87,6 +103,16 @@
<vxe-column title="流程名称" field="processDefinitionName"> </vxe-column>
<vxe-column title="流程标识" field="processDefinitionKey"> </vxe-column>
<vxe-column title="流程分类" field="flowCategory.name"> </vxe-column>
<vxe-column title="流程类型">
<template v-slot="scope">
<el-tag
:size="layoutStore.defaultFormItemSize"
:type="scope.row.flowType === FlowEntryType.FLOW ? 'success' : 'primary'"
>
{{ FlowEntryType.getValue(scope.row.flowType || FlowEntryType.NORMAL) }}
</el-tag>
</template>
</vxe-column>
<vxe-column title="流程图类型">
<template v-slot="scope">
<el-tag
@@ -212,6 +238,7 @@ import {
DiagramType,
SysFlowEntryPublishedStatus,
SysFlowTaskOperationType,
FlowEntryType,
} from '@/common/staticDict/flow';
import { useLayoutStore } from '@/store';
import FormPublishedFlowEntry from './formPublishedFlowEntry.vue';
@@ -251,6 +278,7 @@ const loadFlowEntryWidgetData = (params: ANY_OBJECT) => {
categoryId: formFlowEntry.formFilterCopy.categoryId,
processDefinitionName: formFlowEntry.formFilterCopy.processDefinitionName,
processDefinitionKey: formFlowEntry.formFilterCopy.processDefinitionKey,
flowType: formFlowEntry.formFilterCopy.flowType,
status: formFlowEntry.formFilterCopy.status,
},
};
@@ -272,6 +300,7 @@ const loadFlowEntryWidgetData = (params: ANY_OBJECT) => {
*/
const loadFlowEntryVerify = () => {
formFlowEntry.formFilterCopy.categoryId = formFlowEntry.formFilter.categoryId;
formFlowEntry.formFilterCopy.flowType = formFlowEntry.formFilter.flowType;
formFlowEntry.formFilterCopy.processDefinitionName =
formFlowEntry.formFilter.processDefinitionName;
formFlowEntry.formFilterCopy.processDefinitionKey = formFlowEntry.formFilter.processDefinitionKey;
@@ -291,12 +320,14 @@ const formFlowEntry = reactive({
categoryId: undefined,
processDefinitionName: undefined,
processDefinitionKey: undefined,
flowType: undefined,
},
formFilterCopy: {
status: undefined,
categoryId: undefined,
processDefinitionName: undefined,
processDefinitionKey: undefined,
flowType: undefined,
},
categoryIdWidget: reactive(useDropdown(dropdownOptions)),
flowEntryWidget: reactive(useTable(tableOptions)),
@@ -331,8 +362,16 @@ const onStartFlowEntryClick = (row: ANY_OBJECT) => {
let params = {
processDefinitionKey: row.processDefinitionKey,
};
FlowOperationController.viewInitialTaskInfo(params)
let httpCall =
row.flowType === FlowEntryType.AUTO_TASK
? FlowOperationController.startAutoTask(params)
: FlowOperationController.viewInitialTaskInfo(params);
httpCall
.then(res => {
if (row.flowType === FlowEntryType.AUTO_TASK) {
ElMessage.success('启动成功!');
return;
}
if (res.data && res.data.taskType === SysFlowTaskType.USER_TASK && res.data.assignedMe) {
let params = {
processDefinitionKey: row.processDefinitionKey || '',
@@ -390,9 +429,7 @@ const onAddFlowEntryClick = () => {
area: ['100vw', '100vh'],
skin: 'fullscreen-dialog',
},
{
//path: 'thirdFormEditFlowEntry',
},
{},
{
fullscreen: true,
pathName: '/thirdParty/thirdFormEditFlowEntry',
@@ -418,7 +455,6 @@ const onEditFlowEntryClick = (row: ANY_OBJECT) => {
skin: 'fullscreen-dialog',
},
{
//path: 'thirdFormEditFlowEntry',
flowEntry: row,
},
{
@@ -523,9 +559,6 @@ const onDeleteFlowEntryClick = (row: ANY_OBJECT) => {
});
};
const refreshData = () => {
refreshFormFlowEntry(true);
};
const onResume = () => {
refreshFormFlowEntry();
};
@@ -537,7 +570,6 @@ onMounted(() => {
formInit();
});
defineExpose({
refreshData,
onResume,
});
</script>

View File

@@ -0,0 +1,422 @@
<template>
<el-container class="edit-flow-dblink">
<el-header
class="step-header"
style="overflow: hidden; height: 72px; background: white; border-bottom: 1px solid #ebeef5"
>
<el-row type="flex" justify="space-between" align="middle" style="height: 100%">
<div class="title" style="display: flex; width: 200px; height: 40px; line-height: 40px">
<i class="header-logo logo online-icon icon-orange-icon" style="font-size: 40px" />
<span style="font-size: 22px; color: #333; font-weight: bold">数据库链接</span>
</div>
<el-row type="flex" justify="end">
<el-button :size="formItemSize" type="primary" @click="onSaveClick"> 保存 </el-button>
<el-button
:size="formItemSize"
type="success"
:disabled="formData.flowDblink.dblinkId == null"
@click="() => onTestConnect(true).catch(e => {})"
>
测试链接
</el-button>
<el-button :size="formItemSize" @click="onCancelClick">退出</el-button>
</el-row>
</el-row>
</el-header>
<el-main style="padding: 15px; background-color: #f9f9f9">
<el-row type="flex" justify="center" style="height: 100%">
<el-scrollbar style="height: calc(100vh - 90px)" class="custom-scroll edit-box">
<el-form
ref="form"
:model="formData"
class="full-width-input"
:rules="rules"
style="width: 100%; padding: 20px"
label-width="110px"
:size="formItemSize"
label-position="right"
@submit.prevent
>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="类型" prop="flowDblink.dblinkType">
<el-select
class="input-item"
v-model="formData.flowDblink.dblinkType"
:clearable="true"
filterable
placeholder="数据源类型"
>
<el-option
v-for="item in getValidDblinkType"
:key="item.id"
:value="item.id"
:label="item.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="名称" prop="flowDblink.dblinkName">
<el-input
class="input-item"
v-model="formData.flowDblink.dblinkName"
:clearable="true"
placeholder="数据源名称"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="描述" prop="flowDblink.dblinkDescription">
<el-input
class="input-item"
v-model="formData.flowDblink.dblinkDescription"
:clearable="true"
placeholder="数据源描述"
/>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.flowDblink.dblinkType != null">
<el-form-item label="服务器地址" prop="flowDblink.configuration.host">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.host"
:clearable="true"
placeholder="服务器地址"
/>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.flowDblink.dblinkType != null">
<el-form-item label="端口号" prop="flowDblink.configuration.port">
<el-input-number
class="input-item"
v-model="formData.flowDblink.configuration.port"
:controls="false"
:clearable="true"
placeholder="端口号"
/>
</el-form-item>
</el-col>
<el-col
:span="24"
v-if="
formData.flowDblink.dblinkType != null &&
formData.flowDblink.dblinkType !== DblinkType.ORACLE
"
>
<el-form-item label="数据库名" prop="flowDblink.configuration.database">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.database"
:clearable="true"
placeholder="数据库名称"
/>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.flowDblink.dblinkType != null">
<el-form-item label="用户名" prop="flowDblink.configuration.username">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.username"
:clearable="true"
placeholder="用户名"
/>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.flowDblink.dblinkType != null">
<el-form-item label="密码" prop="flowDblink.configuration.password">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.password"
:clearable="true"
placeholder="密码"
/>
</el-form-item>
</el-col>
<el-col
:span="24"
v-if="
formData.flowDblink.dblinkType === DblinkType.MYSQL ||
formData.flowDblink.dblinkType === DblinkType.POSTGRESQL ||
formData.flowDblink.dblinkType === DblinkType.OPENGAUSS
"
>
<el-form-item label="JDBC额外参数" prop="flowDblink.configuration.jdbcString">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.jdbcString"
:clearable="true"
placeholder="JDBC额外参数"
/>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.flowDblink.dblinkType === DblinkType.ORACLE">
<el-form-item label="服务名 / SID" prop="flowDblink.configuration.sid">
<el-radio-group v-model="formData.flowDblink.configuration.sid">
<el-radio :value="true">SID</el-radio>
<el-radio :value="false">服务名</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.flowDblink.dblinkType === DblinkType.ORACLE">
<el-form-item label="服务名 / SID" prop="flowDblink.configuration.serviceId">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.serviceId"
:clearable="true"
placeholder="服务名 / SID"
/>
</el-form-item>
</el-col>
<el-col
:span="24"
v-if="
formData.flowDblink.dblinkType === DblinkType.POSTGRESQL ||
formData.flowDblink.dblinkType === DblinkType.OPENGAUSS
"
>
<el-form-item label="数据库 Schema" prop="flowDblink.configuration.schema">
<el-input
class="input-item"
v-model="formData.flowDblink.configuration.schema"
:clearable="true"
placeholder="数据库 Schema"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-divider>高级设置</el-divider>
</el-col>
<el-col :span="24">
<el-form-item label="初始连接数" prop="flowDblink.configuration.initialPoolSize">
<el-input-number
class="input-item"
v-model="formData.flowDblink.configuration.initialPoolSize"
:controls="false"
:clearable="true"
placeholder="初始连接数"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="最小连接数" prop="flowDblink.configuration.minPoolSize">
<el-input-number
class="input-item"
v-model="formData.flowDblink.configuration.minPoolSize"
:controls="false"
:clearable="true"
placeholder="最小连接数"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="最大连接数" prop="flowDblink.configuration.maxPoolSize">
<el-input-number
class="input-item"
v-model="formData.flowDblink.configuration.maxPoolSize"
:controls="false"
:clearable="true"
placeholder="最大连接数"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-scrollbar>
</el-row>
</el-main>
</el-container>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { computed, reactive } from 'vue';
import { DialogProp } from '@/components/Dialog/types';
import { FlowDblinkController } from '@/api/flow';
import { DblinkType } from '@/common/staticDict';
import { DBLink } from '@/types/online/dblink';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
dblink?: DBLink;
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<boolean>;
}
const props = defineProps<IProps>();
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const formItemSize = computed(() => {
return layoutStore.defaultFormItemSize || thirdParams.value.defaultFormItemSize?.value;
});
const defaultDBLink = {
configuration: { sid: true, initialPoolSize: 5, minPoolSize: 5, maxPoolSize: 50 },
isDatasourceInit: false,
} as DBLink;
const form = ref();
const formData = reactive({ flowDblink: defaultDBLink });
const rules = {
'flowDblink.dblinkName': [{ required: true, message: '请输入名称', trigger: 'blur' }],
'flowDblink.configuration.host': [
{ required: true, message: '请输入服务器地址', trigger: 'blur' },
],
'flowDblink.configuration.database': [
{ required: true, message: '请输入数据库名称', trigger: 'blur' },
],
'flowDblink.configuration.username': [
{ required: true, message: '请输入用户名', trigger: 'blur' },
],
'flowDblink.configuration.password': [{ required: true, message: '请输入密码', trigger: 'blur' }],
'flowDblink.configuration.port': [{ required: true, message: '请输入端口号', trigger: 'blur' }],
'flowDblink.configuration.initialPoolSize': [
{ required: true, message: '请输入初始连接数', trigger: 'blur' },
],
'flowDblink.configuration.minPoolSize': [
{ required: true, message: '请输入最小连接数', trigger: 'blur' },
],
'flowDblink.configuration.maxPoolSize': [
{ required: true, message: '请输入最大连接数', trigger: 'blur' },
],
'flowDblink.dblinkType': [{ required: true, message: '请输入类型', trigger: 'blur' }],
'flowDblink.configuration.serviceId': [
{ required: true, message: '请输入服务名 / SID', trigger: 'blur' },
],
};
const dialogParams = computed(() => {
return {
// 第三方参数
dblink: props.dblink || thirdParams.value.dblink,
};
});
const getValidDblinkType = computed(() => {
return DblinkType.getList().filter(item => {
return item.id !== DblinkType.CLICK_HOUS && item.id !== DblinkType.DORIS;
});
});
const onCancelClick = () => {
if (props.dialog) {
props.dialog.cancel();
} else {
// 关闭第三方弹窗
onCloseThirdDialog(false);
}
};
const onTestConnect = (showMsg = false) => {
return new Promise((resolve, reject) => {
FlowDblinkController.testConnection({
dblinkId: formData.flowDblink.dblinkId,
})
.then(res => {
if (showMsg) ElMessage.success('连接成功!');
resolve(res);
})
.catch(e => {
reject(e);
});
});
};
/**
* 获取数据库链接详细信息
*/
const loadFlowDblinkData = () => {
if (dialogParams.value.dblink == null) {
return;
}
let params = {
dblinkId: dialogParams.value.dblink.dblinkId,
};
FlowDblinkController.view(params)
.then(res => {
res.data.configuration = JSON.parse(res.data.configuration);
formData.flowDblink = { ...res.data, isDatasourceInit: true };
})
.catch(e => {
console.warn(e);
});
};
/**
* 保存
*/
const onSaveClick = () => {
form.value.validate((valid: boolean) => {
if (!valid) return;
let params = {
flowDblinkDto: {
dblinkId: (dialogParams.value.dblink || {}).dblinkId,
dblinkName: formData.flowDblink.dblinkName,
dblinkDescription: formData.flowDblink.dblinkDescription,
dblinkType: formData.flowDblink.dblinkType,
configuration: JSON.stringify(formData.flowDblink.configuration),
},
};
let httpCall = dialogParams.value.dblink
? FlowDblinkController.update(params)
: FlowDblinkController.add(params);
httpCall
.then(res => {
console.log('dblink saved', res);
ElMessage.success('保存成功');
if (dialogParams.value.dblink == null) formData.flowDblink.dblinkId = res.data as string;
return onTestConnect(false);
})
.then(() => {
if (props.dialog) {
props.dialog.submit(true);
} else {
onCloseThirdDialog(true);
}
})
.catch(e => {
console.warn(e);
});
});
};
const reset = () => {
formData.flowDblink = defaultDBLink;
};
watch(
() => dialogParams.value.dblink,
newValue => {
if (newValue == null) {
reset();
} else {
loadFlowDblinkData();
}
},
{
deep: true,
immediate: true,
},
);
</script>
<style scoped>
.edit-flow-dblink {
position: fixed;
top: 0;
left: 0;
z-index: 100;
width: 100vw;
height: 100vh;
background: #f9f9f9;
}
.edit-box {
width: 600px;
height: 100%;
padding: 20px;
background: white;
}
</style>

View File

@@ -0,0 +1,204 @@
<template>
<AdvanceQuery
class="form-flow-dblink advance-box"
:height="mainContextHeight"
:treePanel="dblinkGroupConfig"
:tablePanel="dblinkConfig"
@refreshTable="onRefresDblink"
@addTableItem="onEditFlowDblink(null)"
>
<template v-slot:table>
<table-box
class="page-table"
:data="flowDblinkWidget.dataList"
:size="layoutStore.defaultFormItemSize"
header-cell-class-name="table-header-gray"
height="auto"
:hasExtend="false"
:seq-config="{
startIndex: (flowDblinkWidget.currentPage - 1) * flowDblinkWidget.pageSize,
}"
>
<vxe-column title="序号" type="seq" width="50px" :index="flowDblinkWidget.getTableIndex" />
<vxe-column title="链接名称" field="dblinkName" />
<vxe-column title="链接类型" field="dblinkTypeDictMap.name" />
<vxe-column title="操作" width="100px">
<template v-slot="scope">
<el-button
link
type="primary"
:size="layoutStore.defaultFormItemSize"
@click="onEditFlowDblink(scope.row)"
>
编辑
</el-button>
<el-button
type="danger"
link
:size="layoutStore.defaultFormItemSize"
@click="onDeleteDblink(scope.row)"
>
删除
</el-button>
</template>
</vxe-column>
<template v-slot:pagination>
<el-row type="flex" justify="end" style="margin-top: 16px">
<el-pagination
:total="flowDblinkWidget.totalCount"
:current-page="flowDblinkWidget.currentPage"
:page-size="flowDblinkWidget.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, prev, pager, next, sizes"
@current-change="flowDblinkWidget.onCurrentPageChange"
@size-change="flowDblinkWidget.onPageSizeChange"
>
</el-pagination>
</el-row>
</template>
</table-box>
</template>
</AdvanceQuery>
</template>
<script lang="ts">
export default {
name: 'formFlowDblink',
};
</script>
<script setup lang="ts">
import { ElMessageBox, ElMessage } from 'element-plus';
import AdvanceQuery from '@/components/AdvanceQuery/index.vue';
import { useCommon } from '@/common/hooks/useCommon';
import { DblinkType } from '@/common/staticDict/index';
import { TableOptions } from '@/common/types/pagination';
import { TableData } from '@/common/types/table';
import { ANY_OBJECT } from '@/types/generic';
import { FlowDblinkController } from '@/api/flow';
import { DBLink } from '@/types/online/dblink';
import { useThirdPartyAlive } from '@/components/thirdParty/hooks';
import { useLayoutStore } from '@/store';
import EditFlowDblink from './editFlowDblink.vue';
const layoutStore = useLayoutStore();
useThirdPartyAlive();
const { mainContextHeight, useTable, Dialog } = useCommon();
const dblinkConfig = reactive({
title: '数据库链接',
supportAdd: true,
addText: '新建链接',
});
let currentDblinkType = DblinkType.MYSQL;
const loadDblinkGroupData = () => {
//return Promise.resolve(DblinkType.getList().filter(item => item.id !== DblinkType.CLICK_HOUSE));
return Promise.resolve(
DblinkType.getList().filter(item => {
return item.id !== DblinkType.CLICK_HOUSE && item.id !== DblinkType.DORIS;
}),
);
};
const dblinkGroupConfig = reactive({
title: '数据库链接类型',
supportAdd: false,
supportEdit: false,
supportDelete: false,
keyColumnName: 'id',
nameColumnName: 'name',
loadFunction: loadDblinkGroupData,
});
const loadDblinkData = (params: ANY_OBJECT): Promise<TableData<ANY_OBJECT>> => {
return new Promise((resolve, reject) => {
params.flowDblinkDtoFilter = {
dblinkType: currentDblinkType,
};
FlowDblinkController.list(params)
.then(res => {
resolve({
dataList: res.data.dataList,
totalCount: res.data.totalCount,
});
})
.catch(e => {
console.log(e);
reject(e);
});
});
};
const loadDblinkDataVerify = () => {
return true;
};
const tableOptions: TableOptions<ANY_OBJECT> = {
loadTableData: loadDblinkData,
verifyTableParameter: loadDblinkDataVerify,
paged: true,
};
const flowDblinkWidget = reactive(useTable(tableOptions));
const refresDblink = (reload = false) => {
if (reload) {
flowDblinkWidget.refreshTable(true, 1);
} else {
flowDblinkWidget.refreshTable();
}
};
// 新建数据库链接与编辑
const onEditFlowDblink = (row: DBLink | null) => {
Dialog.show(
'编辑数据库链接',
EditFlowDblink,
{
area: ['100vw', '100vh'],
skin: 'fullscreen-dialog',
},
{
dblink: row,
path: 'thirdEditFlowDblink',
},
{
fullscreen: true,
pathName: '/thirdParty/thirdEditFlowDblink',
},
)
.then(() => {
refresDblink(true);
})
.catch(e => {
console.warn(e);
});
};
const onDeleteDblink = (row: DBLink) => {
//console.log(row);
ElMessageBox.confirm(`是否删除数据链接【${row.dblinkName}】?`, '', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
return FlowDblinkController.delete({
dblinkId: row.dblinkId,
});
})
.then(() => {
ElMessage.success('删除成功');
refresDblink(true);
})
.catch(e => {
console.warn(e);
});
};
const onRefresDblink = (dblinkType: ANY_OBJECT) => {
currentDblinkType = dblinkType.id;
refresDblink(true);
};
</script>
<style scoped>
:deep(.page-table) {
padding: 0 16px 16px !important;
}
</style>

View File

@@ -544,16 +544,6 @@ const initFormData = () => {
onMounted(() => {
initFormData();
});
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdTaskCommit' && data.isSuccess) {
preHandlerOperationThen(data.rowData.operation, data.rowData.copyItemList, data.data);
}
};
defineExpose({
refreshData,
});
</script>
<style scoped>

View File

@@ -617,7 +617,8 @@ const createNewDiagram = async (xml: string | ArrayBuffer | null) => {
// 将字符串转换成图显示出来
let newId = props.processId || `Process_${new Date().getTime()}`;
let newName = props.processName || `业务流程_${new Date().getTime()}`;
let xmlString = xml || DefaultEmptyXML(newId, newName, props.prefix, diagramType.value);
let flowType = props.flowEntryInfo?.flowType || 0;
let xmlString = xml || DefaultEmptyXML(newId, newName, props.prefix, diagramType.value, flowType);
try {
if (bpmnModeler) {
let { warnings } = await bpmnModeler.importXML(xmlString);

View File

@@ -1,6 +1,12 @@
import { ANY_OBJECT } from '@/types/generic';
import { uuid } from '../../utils';
export default (key: string, name: string, type: string, diagramType: number): string => {
export default (
key: string,
name: string,
type: string,
diagramType: number,
flowType: number,
): string => {
if (!type) type = 'camunda';
const TYPE_TARGET: ANY_OBJECT = {
activiti: 'http://activiti.org/bpmn',
@@ -19,10 +25,10 @@ export default (key: string, name: string, type: string, diagramType: number): s
<bpmn2:startEvent id="Event_${startId}">
<bpmn2:outgoing>Flow_${lineId1}</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:userTask id="Activity_${userTaskId}">
<bpmn2:${flowType === 1 ? 'receiveTask' : 'userTask'} id="Activity_${userTaskId}">
<bpmn2:incoming>Flow_${lineId1}</bpmn2:incoming>
<bpmn2:outgoing>Flow_${lineId2}</bpmn2:outgoing>
</bpmn2:userTask>
</bpmn2:${flowType === 1 ? 'receiveTask' : 'userTask'}>
<bpmn2:sequenceFlow id="Flow_${lineId1}" sourceRef="Event_${startId}" targetRef="Activity_${userTaskId}" />
<bpmn2:endEvent id="Event_${endId}">
<bpmn2:incoming>Flow_${lineId2}</bpmn2:incoming>

View File

@@ -37,14 +37,13 @@
:id="elementId"
:type="elementType"
:tabType="activeName"
v-if="elementType === 'ServiceTask' && activeName === 'baseInfo'"
v-if="
(elementType === 'ServiceTask' || elementType === 'ReceiveTask') &&
activeName === 'baseInfo'
"
/>
</div>
<div v-if="formVisible" key="goback">
<GoBack :id="elementId" :isCountersign="isCountersign" />
</div>
<div v-if="conditionFormVisible" key="condition">
<flow-condition :business-object="elementBusinessObject" :type="elementType" />
</div>
@@ -166,16 +165,22 @@ const props = withDefaults(
prefix?: string;
width?: number;
idEditDisabled?: boolean;
autoTaskVariableList: ANY_OBJECT[];
flowVariableList: ANY_OBJECT[];
}>(),
{
prefix: 'camunda',
width: 480,
idEditDisabled: false,
autoTaskVariableList: () => [],
flowVariableList: () => [],
},
);
provide('prefix', props.prefix);
provide('width', props.width);
provide('flowVariableList', () => props.flowVariableList);
provide('autoTaskVariableList', () => props.autoTaskVariableList);
// refs
const elementForm = ref();
@@ -328,6 +333,8 @@ onBeforeUnmount(() => {
.el-form-item__label {
font-size: 14px;
color: #333;
width: 100%;
text-align: left;
}
.el-button {

View File

@@ -0,0 +1,275 @@
<template>
<div class="autotask-delete-settting">
<el-form-item label="目标表">
<el-row :gutter="8" style="width: 100%">
<el-col :span="12">
<!-- 目标表数据库链接选择 -->
<el-select
v-model="formData.destDblinkId"
clearable
placeholder="请选择数据库链接"
@change="onDestDblinkChange"
>
<el-option
v-for="item in props.flowDblinkList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-col>
<el-col :span="12">
<!-- 目标表表选择 -->
<el-select
v-model="formData.destTableName"
clearable
filterable
placeholder="请选择数据目标表"
@change="onDestTableChange"
>
<el-option v-for="item in destTableList" :key="item" :label="item" :value="item" />
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="逻辑删除字段">
<el-select
v-model="formData.logicDeleteField"
clearable
filterable
placeholder="请选择逻辑删除字段"
@change="onChange"
>
<el-option
v-for="item in destColumnList"
:key="item.columnName"
:label="item.columnName"
:value="item.columnName"
/>
</el-select>
</el-form-item>
<el-form-item label="目标表过滤类型">
<el-radio-group v-model="formData.destFilterType" @change="onChange">
<el-radio label="field">字段过滤</el-radio>
<el-radio label="sql">自定义SQL</el-radio>
</el-radio-group>
</el-form-item>
<MultiItemList
v-if="formData.destFilterType === 'field'"
label="目标表过滤条件"
:data="formData.destFilterList"
addText="添加"
:disabled="formData.destTableName == null || formData.destTableName === ''"
@add="onEditDestFilter()"
@edit="onEditDestFilter"
@delete="onDeleteDestFilter"
:prop="{
label: 'filterColumnName',
value: 'filterColumnName',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).filterColumnName }}</span>
<span style="margin: 0px 10px">{{
CriteriaFilterType.getValue((scope.data || {}).filterType)
}}</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.valueType)
}}</span>
<span>
{{ (scope.data || {}).filterValue }}
</span>
</template>
</MultiItemList>
<el-input v-else v-model="formData.destFilterSql" type="textarea" rows="5" @change="onChange" />
</div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus';
import { defineProps, defineEmits } from 'vue';
import EditSrcTableFilter from './editSrcTableFilter.vue';
import { CriteriaFilterType } from '@/common/staticDict/index';
import { Dialog } from '@/components/Dialog';
import { AutoTaskActionType, AutoTaskValueType } from '@/common/staticDict/flow';
import { ANY_OBJECT } from '@/types/generic';
import MultiItemList from '@/components/MultiItemList/index.vue';
import { FlowDblinkController } from '@/api/flow';
const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps<{
modelValue: string;
flowDblinkList: ANY_OBJECT[];
}>();
const flowEntry = inject('flowEntry', () => {
return {} as ANY_OBJECT;
});
const formList = inject('formList', () => {
return {} as ANY_OBJECT;
});
const prefix = inject('prefix');
const getAllAutoVariableList = inject('getAllAutoVariableList', () => {
return [];
});
type FormDataType = {
actionType?: number;
destDblinkId?: string;
destDblinkType?: string;
destTableName: string | null;
destFilterType: string;
destFilterList: ANY_OBJECT[];
destFilterSql: string;
logicDeleteField: string;
};
const formData = ref<FormDataType>({
actionType: AutoTaskActionType.DELETE,
destDblinkId: undefined,
destDblinkType: undefined,
destTableName: null,
destFilterType: 'field',
destFilterList: [],
destFilterSql: '',
logicDeleteField: '',
});
const destTableList = ref<string[]>([]);
const destColumnList = ref<ANY_OBJECT[]>([]);
const onChange = () => {
let tempData = {
...formData.value,
};
emit('update:modelValue', JSON.stringify(tempData));
emit('change', JSON.stringify(tempData));
};
const loadDblinkTableList = async dblinkId => {
let res = await FlowDblinkController.listDblinkTables({
dblinkId,
});
return Array.isArray(res.data) ? res.data.map(item => item.tableName) : [];
};
const updateTableFilter = (row, data) => {
if (row == null) {
// 新建
formData.value.destFilterList.push(data);
} else {
// 编辑
formData.value.destFilterList = formData.value.destFilterList.map(item => {
return item.filterColumnName === data.filterColumnName ? data : item;
});
}
onChange();
};
const onEditDestFilter = (data?: ANY_OBJECT) => {
Dialog.show(
'编辑过滤字段',
EditSrcTableFilter,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data,
dblinkId: formData.value.destDblinkId,
tableName: formData.value.destTableName,
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditDeleteFilter',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditTableFilter',
},
)
.then(res => {
updateTableFilter(data, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteDestFilter = data => {
ElMessageBox.confirm('是否删除此过滤字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.destFilterList = formData.value.destFilterList.filter(
item => item.filterColumnName !== data.filterColumnName,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
const onDestDblinkChange = val => {
formData.value.destTableName = '';
formData.value.destDblinkType = (
(props.flowDblinkList || []).find(item => item.id === val) || {}
).type;
onChange();
};
const onDestTableChange = val => {
onChange();
};
watch(
() => props.modelValue,
val => {
if (val) {
let taskInfo = val && val !== '' ? JSON.parse(val) : {};
formData.value = {
actionType: AutoTaskActionType.DELETE,
destDblinkId: taskInfo.destDblinkId,
destDblinkType: taskInfo.destDblinkType,
destTableName: taskInfo.destTableName,
destFilterType: taskInfo.destFilterType || 'field',
destFilterList: taskInfo.destFilterList || [],
destFilterSql: taskInfo.destFilterSql || '',
logicDeleteField: taskInfo.logicDeleteField || '',
};
}
},
{ immediate: true },
);
watch(
() => formData.value.destDblinkId,
val => {
if (val) {
loadDblinkTableList(val).then(tableList => {
destTableList.value = tableList;
});
} else {
destTableList.value = [];
}
},
{ immediate: true },
);
watch(
() => formData.value.destTableName,
val => {
if (val) {
FlowDblinkController.listDblinkTableColumns({
dblinkId: formData.value.destDblinkId,
tableName: val,
}).then(res => {
destColumnList.value = res.data;
});
} else {
destColumnList.value = [];
}
},
);
</script>
<style></style>

View File

@@ -0,0 +1,631 @@
<template>
<div class="autotask-http-settting">
<el-form-item label="API Url">
<el-input
placeholder="请输入请求URL"
v-model="formData.httpRequestInfo.url"
@change="onChange"
>
<template #prepend>
<el-select
class="url-select"
v-model="formData.httpRequestInfo.httpMethod"
placeholder="请选择"
@change="onChange"
>
<el-option label="GET" value="GET" />
<el-option label="POST" value="POST" />
<el-option label="PUT" value="PUT" />
<el-option label="DELETE" value="DELETE" />
</el-select>
</template>
</el-input>
</el-form-item>
<MultiItemList
label="请求头设置"
:data="formData.httpRequestInfo.headerList"
addText="添加"
@add="onEditHttpHeader()"
@edit="onEditHttpHeader"
@delete="onDeleteHttpHeader"
:prop="{
label: 'key',
value: 'key',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).key }}</span>
<span style="margin: 0px 10px">等于</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.type)
}}</span>
<span>
{{ (scope.data || {}).srcValue }}
</span>
</template>
</MultiItemList>
<MultiItemList
label="URL参数设置"
:data="formData.httpRequestInfo.urlParamList"
addText="添加"
@add="onEditUrlParam()"
@edit="onEditUrlParam"
@delete="onDeleteUrlParam"
:prop="{
label: 'name',
value: 'id',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).key }}</span>
<span style="margin: 0px 10px">等于</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.type)
}}</span>
<span>
{{ (scope.data || {}).srcValue }}
</span>
</template>
</MultiItemList>
<el-form-item labe="请求Body类型">
<el-radio-group v-model="formData.httpRequestInfo.bodyType" @change="onChange">
<el-radio v-for="item in BodyType.getList()" :key="item.id" :label="item.id">
<el-row type="flex" align="middle">
<span>{{ item.name }}</span>
<el-dropdown
v-if="formData.httpRequestInfo.bodyType === BodyType.RAW && item.id === BodyType.RAW"
style="margin-left: 10px"
@command="cmd => (formData.httpRequestInfo.rawType = cmd)"
>
<el-link>{{ RawType.getValue(formData.httpRequestInfo.rawType) }}</el-link>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="item in RawType.getList()"
:key="item.id"
:command="item.id"
>
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-row>
</el-radio>
</el-radio-group>
</el-form-item>
<MultiItemList
v-if="formData.httpRequestInfo.bodyType === BodyType.FORM_DATA"
label="Body参数设置"
:data="formData.httpRequestInfo.formDataList"
addText="添加"
@add="onEditBodyParam()"
@edit="onEditBodyParam"
@delete="onDeleteBodyParam"
:prop="{
label: 'name',
value: 'id',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).key }}</span>
<span style="margin: 0px 10px">等于</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.type)
}}</span>
<span>
{{ (scope.data || {}).srcValue }}
</span>
</template>
</MultiItemList>
<el-form-item label="Body参数设置" v-if="formData.httpRequestInfo.bodyType === BodyType.RAW">
<el-input
v-model="formData.httpRequestInfo.bodyData"
type="textarea"
rows="5"
clearable
placeholder="请输入请求Body"
@change="onChange"
/>
</el-form-item>
<el-form-item label="请求成功的HTTP状态码">
<el-input
v-model="formData.httpResponnseData.successStatusCode"
clearable
placeholder="示例200,201 (多个状态码使用英文逗号分隔)"
@change="onChange"
/>
</el-form-item>
<el-form-item label="请求成功字段">
<el-input
v-model="formData.httpResponnseData.successBodyField"
clearable
placeholder="示例data.isSuccess 请求成功情况下,进一步判断是否成功字段"
@change="onChange"
/>
</el-form-item>
<el-form-item label="失败信息字段">
<el-input
v-model="formData.httpResponnseData.errorMessageBodyField"
clearable
placeholder="示例data.message 请求成功情况下,返回的失败信息字段"
@change="onChange"
/>
</el-form-item>
<el-form-item label="请求失败处理方式">
<el-radio-group v-model="formData.httpResponnseData.failHandleType" @change="onChange">
<el-radio v-for="item in FailHandleType.getList()" :key="item.id" :label="item.id">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="响应数据">
<el-table
:show-header="false"
:data="responseDataTree"
size="mini"
row-key="id"
:tree-props="{ children: 'children' }"
>
<el-table-column prop="fieldName" label="字段名" />
<el-table-column prop="fieldType" label="字段类型" width="100px" />
<el-table-column label="操作" width="120px">
<template v-slot="scope">
<el-button type="primary" link size="small" @click="onEditResponseData(scope.row)">
编辑
</el-button>
<el-button type="primary" link size="small" @click="onDeleteResponseData(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-button
type="primary"
plain
size="small"
icon="el-icon-plus"
style="width: 100%"
@click="onEditResponseData()"
>
添加响应字段
</el-button>
</el-form-item>
</div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus';
import { defineProps, defineEmits } from 'vue';
import EditHttpHeader from './editHttpHeader.vue';
import EditHttpParameter from './editHttpParameter.vue';
import EditResponseData from './editResponseData.vue';
import { treeDataTranslate } from '@/common/utils/index';
import { DictionaryBase } from '@/common/staticDict/types';
import MultiItemList from '@/components/MultiItemList/index.vue';
import { Dialog } from '@/components/Dialog';
import { AutoTaskActionType, AutoTaskValueType } from '@/common/staticDict/flow';
import { ANY_OBJECT } from '@/types/generic';
const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps<{
modelValue: string;
}>();
const flowEntry = inject('flowEntry', () => {
return {} as ANY_OBJECT;
});
const formList = inject('formList', () => {
return {} as ANY_OBJECT;
});
const prefix = inject('prefix');
const getAllAutoVariableList = inject('getAllAutoVariableList', () => {
return [];
});
type FormDataType = {
actionType?: number;
httpRequestInfo: {
url: string;
httpMethod: string;
headerList: Array<ANY_OBJECT>;
bodyType: string;
urlParamList: Array<ANY_OBJECT>;
formDataList: Array<ANY_OBJECT>;
rawType: string;
bodyData: string;
};
httpResponnseData: {
successStatusCode: string;
successBodyField: string;
errorMessageBodyField: string;
failHandleType: string;
httpResponseBody: Array<ANY_OBJECT>;
};
};
const formData = ref<FormDataType>({
actionType: AutoTaskActionType.HTTP,
httpRequestInfo: {
url: '',
httpMethod: 'GET',
headerList: [],
bodyType: 'formData',
urlParamList: [],
formDataList: [],
rawType: 'json',
bodyData: '',
},
httpResponnseData: {
successStatusCode: '',
successBodyField: '',
errorMessageBodyField: '',
failHandleType: 'stop',
httpResponseBody: [],
},
});
const BodyType = new DictionaryBase('Body类型', [
{
id: 'formData',
name: 'form-data',
symbol: 'FORM_DATA',
},
{
id: 'raw',
name: 'raw',
symbol: 'RAW',
},
]);
const RawType = new DictionaryBase('Raw类型', [
{
id: 'text',
name: 'text',
symbol: 'TEXT',
},
{
id: 'json',
name: 'json',
symbol: 'JSON',
},
]);
const FailHandleType = new DictionaryBase('失败处理方式', [
{
id: 'stop',
name: '流程中止执行',
symbol: 'EXIT',
},
{
id: 'continue',
name: '继续执行',
symbol: 'CONTINUE',
},
]);
const responseDataTree = computed(() => {
let dataList = formData.value.httpResponnseData.httpResponseBody.map(item => {
return {
...item,
disabled: item.fieldType !== 'Object' && item.fieldType !== 'Array',
};
});
return treeDataTranslate(dataList, 'id', 'parentId');
});
const onChange = () => {
let tempData = {
...formData.value,
};
emit('update:modelValue', JSON.stringify(tempData));
emit('change', JSON.stringify(tempData));
};
const updateHttpHeader = (row, data) => {
if (row == null) {
// 新建
if (formData.value.httpRequestInfo.headerList == null) {
formData.value.httpRequestInfo.headerList = [];
}
formData.value.httpRequestInfo.headerList.push(data);
} else {
// 编辑
formData.value.httpRequestInfo.headerList = formData.value.httpRequestInfo.headerList.map(
item => {
return item.key === data.key ? data : item;
},
);
}
onChange();
};
const onEditHttpHeader = (row?: ANY_OBJECT) => {
Dialog.show(
'编辑请求头',
EditHttpHeader,
{
area: ['500px', '300px'],
},
{
entryId: flowEntry().entryId,
data: row,
usedKeyList: formData.value.httpRequestInfo.headerList.map(item => item.key),
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditHttpHeader',
},
{
width: '500px',
height: '300px',
pathName: '/thirdParty/thirdEditHttpHeader',
},
)
.then(res => {
updateHttpHeader(row, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteHttpHeader = row => {
ElMessageBox.confirm('是否删除此请求头?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.httpRequestInfo.headerList = formData.value.httpRequestInfo.headerList.filter(
item => item.key !== row.key,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
const updateUrlParam = (row, data) => {
if (row == null) {
// 新建
if (formData.value.httpRequestInfo.urlParamList == null) {
formData.value.httpRequestInfo.urlParamList = [];
}
formData.value.httpRequestInfo.urlParamList.push(data);
} else {
// 编辑
formData.value.httpRequestInfo.urlParamList = formData.value.httpRequestInfo.urlParamList.map(
item => {
return item.key === data.key ? data : item;
},
);
}
onChange();
};
const onEditUrlParam = (row?: ANY_OBJECT) => {
Dialog.show(
'编辑URL参数',
EditHttpParameter,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data: row,
usedParamList: formData.value.httpRequestInfo.urlParamList.map(item => item.key),
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditHttpUrlParam',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditHttpRequestParam',
},
)
.then(res => {
updateUrlParam(row, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteUrlParam = row => {
ElMessageBox.confirm('是否删除此URL参数', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(res => {
formData.value.httpRequestInfo.urlParamList =
formData.value.httpRequestInfo.urlParamList.filter(item => item.key !== row.key);
onChange();
})
.catch(e => {
console.log(e);
});
};
const updateBodyParam = (row, res) => {
if (formData.value.httpRequestInfo.formDataList == null) {
formData.value.httpRequestInfo.formDataList = [];
}
if (row == null) {
// 新建
formData.value.httpRequestInfo.formDataList.push(res);
} else {
// 编辑
formData.value.httpRequestInfo.formDataList = formData.value.httpRequestInfo.formDataList.map(
item => {
return item.key === res.key ? res : item;
},
);
}
onChange();
};
const onEditBodyParam = (row?: ANY_OBJECT) => {
Dialog.show(
'编辑Body参数',
EditHttpParameter,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data: row,
usedParamList: formData.value.httpRequestInfo.formDataList.map(item => item.key),
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditHttpBodyParam',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditHttpRequestParam',
},
)
.then(res => {
updateBodyParam(row, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteBodyParam = row => {
ElMessageBox.confirm('是否删除此Body参数', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(res => {
formData.value.httpRequestInfo.formDataList =
formData.value.httpRequestInfo.formDataList.filter(item => item.key !== row.key);
onChange();
})
.catch(e => {
console.log(e);
});
};
const updateResponseData = (row, res) => {
function buildChildId(node, parentId) {
if (parentId == null || parentId === '') {
node.id = parentId + '.' + node.fieldName;
} else {
node.id = node.fieldName;
}
if (Array.isArray(node.children)) {
node.children.forEach(child => {
buildChildId(child, node.id);
});
}
}
if (formData.value.httpResponnseData.httpResponseBody == null) {
formData.value.httpResponnseData.httpResponseBody = [];
}
if (row == null) {
// 新建
formData.value.httpResponnseData.httpResponseBody.push(res);
} else {
// 编辑
formData.value.httpResponnseData.httpResponseBody =
formData.value.httpResponnseData.httpResponseBody.map(item => {
if (item.id === res.oldIId) {
buildChildId(res, res.parentId);
return res;
} else {
return item;
}
});
}
onChange();
};
const onEditResponseData = (row?: ANY_OBJECT) => {
Dialog.show(
'编辑响应字段',
EditResponseData,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data: row,
usedFieldList: responseDataTree.value,
path: 'thirdEditResponseData',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditResponseData',
},
)
.then(res => {
updateResponseData(row, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteResponseData = row => {
ElMessageBox.confirm('是否删除此响应字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(res => {
formData.value.httpResponnseData.httpResponseBody =
formData.value.httpResponnseData.httpResponseBody.filter(item => item.id !== row.id);
onChange();
})
.catch(e => {
console.log(e);
});
};
watch(
() => props.modelValue,
val => {
let taskInfo = val && val !== '' ? JSON.parse(val) : {};
if (taskInfo.httpRequestInfo == null) {
taskInfo.httpRequestInfo = {};
}
if (taskInfo.httpResponnseData == null) {
taskInfo.httpResponnseData = {};
}
formData.value = {
actionType: AutoTaskActionType.HTTP,
httpRequestInfo: {
url: taskInfo.httpRequestInfo.url || '',
httpMethod: taskInfo.httpRequestInfo.httpMethod || 'GET',
headerList: taskInfo.httpRequestInfo.headerList || [],
bodyType: taskInfo.httpRequestInfo.bodyType || 'formData',
urlParamList: taskInfo.httpRequestInfo.urlParamList || [],
formDataList: taskInfo.httpRequestInfo.formDataList || [],
rawType: taskInfo.httpRequestInfo.rawType || 'json',
bodyData: taskInfo.httpRequestInfo.bodyData || '',
},
httpResponnseData: {
successStatusCode: taskInfo.httpResponnseData.successStatusCode || '',
successBodyField: taskInfo.httpResponnseData.successBodyField || '',
errorMessageBodyField: taskInfo.httpResponnseData.errorMessageBodyField || '',
failHandleType: taskInfo.httpResponnseData.failHandleType || 'stop',
httpResponseBody: taskInfo.httpResponnseData.httpResponseBody || [],
},
};
},
{ immediate: true },
);
</script>
<style scoped>
.url-select {
width: 100px;
}
.url-select /deep/ .el-input--suffix {
width: 100px;
}
.url-select /deep/ .el-input__inner {
padding: 0px 15px;
}
</style>

View File

@@ -0,0 +1,404 @@
<template>
<div class="autotask-insert-settting">
<el-form-item label="源表">
<el-row :gutter="8" style="width: 100%">
<el-col :span="12">
<!-- 源表数据库链接选择 -->
<el-select
v-model="formData.srcDblinkId"
clearable
placeholder="请选择数据库链接"
@change="onSrcDblinkChange"
>
<el-option
v-for="item in flowDblinkList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-col>
<el-col :span="12">
<!-- 源表选择 -->
<el-select
v-model="formData.srcTableName"
clearable
filterable
placeholder="请选择数据源表"
@change="onSrcTableChange"
>
<el-option v-for="item in srcTableList" :key="item" :label="item" :value="item" />
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="源表过滤类型">
<el-radio-group v-model="formData.srcFilterType" @change="onChange">
<el-radio label="field">字段过滤</el-radio>
<el-radio label="sql">自定义SQL</el-radio>
</el-radio-group>
</el-form-item>
<MultiItemList
v-if="formData.srcFilterType === 'field'"
label="源表过滤条件"
:data="formData.srcFilterList"
addText="添加"
:disabled="formData.srcTableName == null || formData.srcTableName === ''"
@add="onEditSrcFilter()"
@edit="onEditSrcFilter"
@delete="onDeleteSrcFilter"
:prop="{
label: 'filterColumnName',
value: 'filterColumnName',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).filterColumnName }}</span>
<span style="margin: 0px 10px">{{
CriteriaFilterType.getValue((scope.data || {}).filterType)
}}</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.valueType)
}}</span>
<span>
{{ (scope.data || {}).filterValue }}
</span>
</template>
</MultiItemList>
<el-input
v-else
v-model="formData.srcFilterSql"
type="textarea"
rows="5"
placeholder="重要过滤值使用流程变量时需要手动输入变量名的两边一定不要添加任何引号name = ${variableName}"
@change="onChange"
/>
<el-form-item label="目标表">
<el-row :gutter="8" style="width: 100%">
<el-col :span="12">
<!-- 目标表数据库链接选择 -->
<el-select
v-model="formData.destDblinkId"
clearable
placeholder="请选择数据库链接"
@change="onDestDblinkChange"
>
<el-option
v-for="item in flowDblinkList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-col>
<el-col :span="12">
<!-- 目标表表选择 -->
<el-select
v-model="formData.destTableName"
clearable
filterable
placeholder="请选择数据目标表"
@change="onDestTableChange"
>
<el-option v-for="item in destTableList" :key="item" :label="item" :value="item" />
</el-select>
</el-col>
</el-row>
</el-form-item>
<MultiItemList
label="数据插入对象"
:data="formData.insertDataList"
addText="添加"
:disabled="formData.destTableName == null || formData.destTableName === ''"
@add="onEditInsertData()"
@edit="onEditInsertData"
@delete="onDeleteInsertData"
:prop="{
label: 'destColumnName',
value: 'destColumnName',
}"
>
<template v-slot="scope">
<span>{{ scope.data.destColumnName }}</span>
<span style="margin: 0px 10px">等于</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.type)
}}</span>
<span>{{ scope.data.srcValue }}</span>
</template>
</MultiItemList>
</div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus';
import { defineProps, defineEmits } from 'vue';
import EditInsertData from './editInsertData.vue';
import EditSrcTableFilter from './editSrcTableFilter.vue';
import { CriteriaFilterType } from '@/common/staticDict/index';
import { Dialog } from '@/components/Dialog';
import { AutoTaskActionType, AutoTaskValueType } from '@/common/staticDict/flow';
import { ANY_OBJECT } from '@/types/generic';
import MultiItemList from '@/components/MultiItemList/index.vue';
import { FlowDblinkController } from '@/api/flow';
const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps<{
modelValue: string;
flowDblinkList: ANY_OBJECT[];
}>();
const flowEntry = inject('flowEntry', () => {
return {} as ANY_OBJECT;
});
const formList = inject('formList', () => {
return {} as ANY_OBJECT;
});
const prefix = inject('prefix');
const getAllAutoVariableList = inject('getAllAutoVariableList', () => {
return [];
});
type FormDataType = {
actionType?: number;
srcFilterType: string;
srcFilterSql: string;
srcDblinkId?: number;
srcDblinkType?: string;
srcTableName: string;
destDblinkId?: number;
destDblinkType?: string;
destTableName: string;
srcFilterList: Array<ANY_OBJECT>;
insertDataList: Array<ANY_OBJECT>;
};
const formData = ref<FormDataType>({
actionType: AutoTaskActionType.INSERT,
srcFilterType: 'field',
srcFilterSql: '',
srcDblinkId: undefined,
srcDblinkType: undefined,
srcTableName: '',
destDblinkId: undefined,
destTableName: '',
destDblinkType: undefined,
srcFilterList: [],
insertDataList: [],
});
const srcTableList = ref<string[]>([]);
const destTableList = ref<string[]>([]);
const onChange = () => {
let tempData = {
...formData.value,
};
emit('update:modelValue', JSON.stringify(tempData));
emit('change', JSON.stringify(tempData));
};
const loadDblinkTableList = async dblinkId => {
let res = await FlowDblinkController.listDblinkTables({
dblinkId,
});
return Array.isArray(res.data) ? res.data.map(item => item.tableName) : [];
};
const updateInsertData = (data, res) => {
if (data == null) {
// 新建
formData.value.insertDataList.push(res);
} else {
// 编辑
formData.value.insertDataList = formData.value.insertDataList.map(item => {
return item.destColumnName === res.destColumnName ? res : item;
});
}
onChange();
};
const onEditInsertData = (data?: ANY_OBJECT) => {
Dialog.show(
'编辑插入字段',
EditInsertData,
{
area: ['500px', '300px'],
},
{
entryId: flowEntry().entryId,
data,
dblinkId: formData.value.destDblinkId,
tableName: formData.value.destTableName,
srcDblinkId: formData.value.srcDblinkId,
srcTableName: formData.value.srcTableName,
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditInsertData',
},
{
width: '500px',
height: '300px',
pathName: '/thirdParty/thirdEditFieldUpdateData',
},
)
.then(res => {
updateInsertData(data, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteInsertData = data => {
ElMessageBox.confirm('是否删除此字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.insertDataList = formData.value.insertDataList.filter(
item => item.destColumnName !== data.destColumnName,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
const updateSrcFilter = (data, res) => {
if (data == null) {
// 新建
formData.value.srcFilterList.push(res);
} else {
// 编辑
formData.value.srcFilterList = formData.value.srcFilterList.map(item => {
return item.filterColumnName === res.filterColumnName ? res : item;
});
}
onChange();
};
const onEditSrcFilter = (data?: ANY_OBJECT) => {
Dialog.show(
'编辑过滤字段',
EditSrcTableFilter,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data,
dblinkId: formData.value.srcDblinkId,
tableName: formData.value.srcTableName,
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditSrcFilter',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditTableFilter',
},
)
.then(res => {
updateSrcFilter(data, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteSrcFilter = data => {
ElMessageBox.confirm('是否删除此过滤字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.srcFilterList = formData.value.srcFilterList.filter(
item => item.filterColumnName !== data.filterColumnName,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
const onSrcDblinkChange = val => {
formData.value.srcTableName = '';
formData.value.srcDblinkType = (props.flowDblinkList.find(item => item.id === val) || {}).type;
formData.value.srcFilterSql = '';
formData.value.srcFilterList = [];
onChange();
};
const onSrcTableChange = val => {
formData.value.srcFilterSql = '';
formData.value.srcFilterList = [];
onChange();
};
const onDestDblinkChange = val => {
formData.value.destTableName = '';
formData.value.destDblinkType = (props.flowDblinkList.find(item => item.id === val) || {}).type;
formData.value.insertDataList = [];
onChange();
};
const onDestTableChange = val => {
formData.value.insertDataList = [];
onChange();
};
watch(
() => props.modelValue,
val => {
if (val) {
let taskInfo = val && val !== '' ? JSON.parse(val) : {};
formData.value = {
actionType: taskInfo.actionType || 0,
srcFilterType: taskInfo.srcFilterType || 'field',
srcFilterSql: taskInfo.srcFilterSql || '',
srcDblinkId: taskInfo.srcDblinkId,
srcTableName: taskInfo.srcTableName || '',
srcDblinkType: taskInfo.srcDblinkType,
destDblinkId: taskInfo.destDblinkId,
destDblinkType: taskInfo.destDblinkType,
destTableName: taskInfo.destTableName || '',
insertDataList: taskInfo.insertDataList || [],
srcFilterList: taskInfo.srcFilterList || [],
};
}
},
{ immediate: true },
);
watch(
() => formData.value.srcDblinkId,
val => {
if (val) {
loadDblinkTableList(val).then(tableList => {
srcTableList.value = tableList;
});
} else {
srcTableList.value = [];
}
},
{ immediate: true },
);
watch(
() => formData.value.destDblinkId,
val => {
if (val) {
loadDblinkTableList(val).then(tableList => {
destTableList.value = tableList;
});
} else {
destTableList.value = [];
}
},
{ immediate: true },
);
</script>
<style></style>

View File

@@ -0,0 +1,293 @@
<template>
<div class="autotask-query-single-settting">
<el-form-item label="源表">
<el-row :gutter="8" style="width: 100%">
<el-col :span="12">
<!-- 源表数据库链接选择 -->
<el-select
v-model="formData.srcDblinkId"
clearable
placeholder="请选择数据库链接"
@change="onSrcDblinkChange"
>
<el-option
v-for="item in flowDblinkList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-col>
<el-col :span="12">
<!-- 源表选择 -->
<el-select
v-model="formData.srcTableName"
clearable
filterable
placeholder="请选择数据源表"
@change="onSrcTableChange"
>
<el-option v-for="item in srcTableList" :key="item" :label="item" :value="item" />
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="源表过滤类型">
<el-radio-group v-model="formData.srcFilterType" @change="onChange">
<el-radio label="field">字段过滤</el-radio>
<el-radio label="sql">自定义SQL</el-radio>
</el-radio-group>
</el-form-item>
<MultiItemList
v-if="formData.srcFilterType === 'field'"
label="源表过滤条件"
:data="formData.srcFilterList"
addText="添加"
:disabled="formData.srcTableName == null || formData.srcTableName === ''"
@add="onEditSrcFilter()"
@edit="onEditSrcFilter"
@delete="onDeleteSrcFilter"
:prop="{
label: 'filterColumnName',
value: 'filterColumnName',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).filterColumnName }}</span>
<span style="margin: 0px 10px">{{
CriteriaFilterType.getValue((scope.data || {}).filterType)
}}</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.valueType)
}}</span>
<span>
{{ (scope.data || {}).filterValue }}
</span>
</template>
</MultiItemList>
<el-input
v-else
v-model="formData.srcFilterSql"
type="textarea"
rows="5"
placeholder="重要过滤值使用流程变量时需要手动输入变量名的两边一定不要添加任何引号name = ${variableName}"
@change="onChange"
/>
<el-form-item label="查询字段">
<el-select
v-model="formData.selectFieldList"
clearable
filterable
multiple
placeholder="请选择查询字段"
@change="onChange"
>
<el-option
v-for="item in srcColumnList"
:key="item.columnName"
:label="item.columnName"
:value="item.columnName"
/>
</el-select>
</el-form-item>
</div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus';
import { defineProps, defineEmits } from 'vue';
import EditSrcTableFilter from './editSrcTableFilter.vue';
import { CriteriaFilterType } from '@/common/staticDict/index';
import { Dialog } from '@/components/Dialog';
import { AutoTaskActionType, AutoTaskValueType } from '@/common/staticDict/flow';
import { ANY_OBJECT } from '@/types/generic';
import MultiItemList from '@/components/MultiItemList/index.vue';
import { FlowDblinkController } from '@/api/flow';
const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps<{
modelValue: string;
flowDblinkList: ANY_OBJECT[];
}>();
const flowEntry = inject('flowEntry', () => {
return {} as ANY_OBJECT;
});
const formList = inject('formList', () => {
return {} as ANY_OBJECT;
});
const prefix = inject('prefix');
const getAllAutoVariableList = inject('getAllAutoVariableList', () => {
return [];
});
type FormDataType = {
actionType?: number;
srcDblinkId?: string;
srcDblinkType?: string | number;
srcTableName: string | null;
srcFilterType: string;
srcFilterList: ANY_OBJECT[];
srcFilterSql: string;
selectFieldList: string[];
};
const formData = ref<FormDataType>({
actionType: AutoTaskActionType.QUERY_SINGLE_DATA,
srcDblinkId: undefined,
srcDblinkType: undefined,
srcTableName: null,
srcFilterType: 'field',
srcFilterList: [],
srcFilterSql: '',
selectFieldList: [],
});
const srcColumnList = ref<ANY_OBJECT[]>([]);
const srcTableList = ref<string[]>([]);
const onChange = () => {
let tempData = {
...formData.value,
};
emit('update:modelValue', JSON.stringify(tempData));
emit('change', JSON.stringify(tempData));
};
const loadDblinkTableList = async dblinkId => {
let res = await FlowDblinkController.listDblinkTables({
dblinkId,
});
return Array.isArray(res.data) ? res.data.map(item => item.tableName) : [];
};
const getColumnList = () => {
if (
formData.value.srcDblinkId == null ||
formData.value.srcTableName == null ||
formData.value.srcTableName === '' ||
formData.value.srcDblinkId === ''
) {
srcColumnList.value = [];
return;
}
FlowDblinkController.listDblinkTableColumns({
dblinkId: formData.value.srcDblinkId,
tableName: formData.value.srcTableName,
}).then(res => {
srcColumnList.value = res.data;
});
};
const onSrcDblinkChange = val => {
formData.value.srcTableName = '';
formData.value.srcDblinkType = (props.flowDblinkList.find(item => item.id === val) || {}).type;
formData.value.srcFilterSql = '';
formData.value.srcFilterList = [];
onChange();
};
const onSrcTableChange = () => {
formData.value.srcFilterSql = '';
formData.value.srcFilterList = [];
onChange();
};
const updateSrcTableFilter = (data, res) => {
if (data == null) {
// 新建
formData.value.srcFilterList.push(res);
} else {
// 编辑
formData.value.srcFilterList = formData.value.srcFilterList.map(item => {
return item.srcTableName === res.srcTableName ? res : item;
});
}
onChange();
};
const onEditSrcFilter = (data?: ANY_OBJECT) => {
Dialog.show(
'编辑过滤字段',
EditSrcTableFilter,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data,
dblinkId: formData.value.srcDblinkId,
tableName: formData.value.srcTableName,
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditQuerySingleFilter',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditTableFilter',
},
)
.then(res => {
updateSrcTableFilter(data, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteSrcFilter = data => {
ElMessageBox.confirm('是否删除此过滤字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.srcFilterList = formData.value.srcFilterList.filter(
item => item.filterColumnName !== data.filterColumnName,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
watch(
() => props.modelValue,
val => {
let taskInfo = val && val !== '' ? JSON.parse(val) : {};
formData.value = {
actionType: AutoTaskActionType.QUERY_SINGLE_DATA,
srcFilterType: taskInfo.srcFilterType || 'field',
srcFilterSql: taskInfo.srcFilterSql || '',
srcDblinkId: taskInfo.srcDblinkId,
srcTableName: taskInfo.srcTableName || '',
srcDblinkType: taskInfo.srcDblinkType,
srcFilterList: taskInfo.srcFilterList || [],
selectFieldList: taskInfo.selectFieldList || [],
};
},
{ immediate: true },
);
watch(
() => formData.value.srcDblinkId,
val => {
if (val) {
loadDblinkTableList(val).then(tableList => {
srcTableList.value = tableList;
});
} else {
srcTableList.value = [];
}
},
);
watch(
() => formData.value.srcTableName,
() => {
getColumnList();
},
{ immediate: true },
);
</script>
<style scoped></style>

View File

@@ -0,0 +1,324 @@
<template>
<div class="autotask-update-settting">
<el-form-item label="目标表">
<el-row :gutter="8" style="width: 100%">
<el-col :span="12">
<!-- 目标表数据库链接选择 -->
<el-select
v-model="formData.destDblinkId"
clearable
placeholder="请选择数据库链接"
@change="onDestDblinkChange"
>
<el-option
v-for="item in flowDblinkList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-col>
<el-col :span="12">
<!-- 目标表表选择 -->
<el-select
v-model="formData.destTableName"
clearable
filterable
placeholder="请选择数据目标表"
@change="onDestTableChange"
>
<el-option v-for="item in destTableList" :key="item" :label="item" :value="item" />
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="目标表过滤类型">
<el-radio-group v-model="formData.destFilterType" @change="onChange">
<el-radio label="field">字段过滤</el-radio>
<el-radio label="sql">自定义SQL</el-radio>
</el-radio-group>
</el-form-item>
<MultiItemList
v-if="formData.destFilterType === 'field'"
label="目标表过滤条件"
:data="formData.destFilterList"
addText="添加"
:disabled="formData.destTableName == null || formData.destTableName === ''"
@add="onEditDestFilter()"
@edit="onEditDestFilter"
@delete="onDeleteDestFilter"
:prop="{
label: 'filterColumnName',
value: 'filterColumnName',
}"
>
<template v-slot="scope">
<span>{{ (scope.data || {}).filterColumnName }}</span>
<span style="margin: 0px 10px">{{
CriteriaFilterType.getValue((scope.data || {}).filterType)
}}</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.valueType)
}}</span>
<span>
{{ (scope.data || {}).filterValue }}
</span>
</template>
</MultiItemList>
<el-input v-else v-model="formData.destFilterSql" type="textarea" rows="5" @change="onChange" />
<MultiItemList
label="数据更新配置"
:data="formData.updateDataList"
addText="添加"
:disabled="formData.destTableName == null || formData.destTableName === ''"
@add="onEditUpdateData()"
@edit="onEditUpdateData"
@delete="onDeleteUpdateData"
:prop="{
label: 'destColumnName',
value: 'destColumnName',
}"
>
<template v-slot="scope">
<span>{{ scope.data.destColumnName }}</span>
<span style="margin: 0px 10px">等于</span>
<span style="margin: 0px 10px 0px 0px">{{
AutoTaskValueType.getValue(scope.data.type)
}}</span>
<span>{{ scope.data.srcValue }}</span>
</template>
</MultiItemList>
</div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus';
import { defineProps, defineEmits } from 'vue';
import EditInsertData from './editInsertData.vue';
import EditSrcTableFilter from './editSrcTableFilter.vue';
import { CriteriaFilterType } from '@/common/staticDict/index';
import { Dialog } from '@/components/Dialog';
import { AutoTaskActionType, AutoTaskValueType } from '@/common/staticDict/flow';
import { ANY_OBJECT } from '@/types/generic';
import MultiItemList from '@/components/MultiItemList/index.vue';
import { FlowDblinkController } from '@/api/flow';
const emit = defineEmits(['update:modelValue', 'change']);
const props = defineProps<{
modelValue: string;
flowDblinkList: ANY_OBJECT[];
}>();
const flowEntry = inject('flowEntry', () => {
return {} as ANY_OBJECT;
});
const formList = inject('formList', () => {
return {} as ANY_OBJECT;
});
const prefix = inject('prefix');
const getAllAutoVariableList = inject('getAllAutoVariableList', () => {
return [];
});
type FormDataType = {
actionType?: number;
destDblinkId?: string;
destDblinkType?: string;
destTableName?: string;
destFilterType: string;
destFilterList: Array<ANY_OBJECT>;
destFilterSql: string;
updateDataList: Array<ANY_OBJECT>;
};
const formData = ref<FormDataType>({
actionType: AutoTaskActionType.UPDATE,
destDblinkId: undefined,
destDblinkType: undefined,
destTableName: undefined,
destFilterType: 'field',
destFilterList: [],
destFilterSql: '',
updateDataList: [],
});
const destTableList = ref<string[]>([]);
const onChange = () => {
let tempData = {
...formData.value,
};
emit('update:modelValue', JSON.stringify(tempData));
emit('change', JSON.stringify(tempData));
};
const loadDblinkTableList = async dblinkId => {
let res = await FlowDblinkController.listDblinkTables({
dblinkId,
});
return Array.isArray(res.data) ? res.data.map(item => item.tableName) : [];
};
const updateUpdateField = (data, res) => {
if (data == null) {
// 新建
formData.value.updateDataList.push(res);
} else {
// 编辑
formData.value.updateDataList = formData.value.updateDataList.map(item => {
return item.destColumnName === res.destColumnName ? res : item;
});
}
onChange();
};
const onEditUpdateData = (data?: ANY_OBJECT) => {
Dialog.show(
'编辑更新字段',
EditInsertData,
{
area: ['500px', '300px'],
},
{
entryId: flowEntry().entryId,
data,
dblinkId: formData.value.destDblinkId,
tableName: formData.value.destTableName,
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditUpdateField',
},
{
width: '500px',
height: '300px',
pathName: '/thirdParty/thirdEditFieldUpdateData',
},
)
.then(res => {
updateUpdateField(data, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteUpdateData = data => {
ElMessageBox.confirm('是否删除此字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.updateDataList = formData.value.updateDataList.filter(
item => item.destColumnName !== data.destColumnName,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
const updateDestTableFilter = (data, res) => {
if (data == null) {
// 新建
formData.value.destFilterList.push(res);
} else {
// 编辑
formData.value.destFilterList = formData.value.destFilterList.map(item => {
return item.filterColumnName === res.filterColumnName ? res : item;
});
}
onChange();
};
const onEditDestFilter = (data?: ANY_OBJECT) => {
Dialog.show(
'编辑过滤字段',
EditSrcTableFilter,
{
area: ['500px', '400px'],
},
{
entryId: flowEntry().entryId,
data,
dblinkId: formData.value.destDblinkId,
tableName: formData.value.destTableName,
flowVariableList: getAllAutoVariableList(),
path: 'thirdEditDestFilter',
},
{
width: '500px',
height: '400px',
pathName: '/thirdParty/thirdEditTableFilter',
},
)
.then(res => {
updateDestTableFilter(data, res);
})
.catch(e => {
console.log(e);
});
};
const onDeleteDestFilter = data => {
ElMessageBox.confirm('是否删除此过滤字段?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
formData.value.destFilterList = formData.value.destFilterList.filter(
item => item.filterColumnName !== data.filterColumnName,
);
onChange();
})
.catch(e => {
console.log(e);
});
};
const onDestDblinkChange = val => {
formData.value.destTableName = '';
formData.value.destDblinkType = (props.flowDblinkList.find(item => item.id === val) || {}).type;
formData.value.updateDataList = [];
onChange();
};
const onDestTableChange = () => {
formData.value.updateDataList = [];
onChange();
};
watch(
() => props.modelValue,
val => {
if (val) {
let taskInfo = val && val !== '' ? JSON.parse(val) : {};
formData.value = {
actionType: AutoTaskActionType.UPDATE,
destDblinkId: taskInfo.destDblinkId,
destDblinkType: taskInfo.destDblinkType,
destTableName: taskInfo.destTableName,
destFilterType: taskInfo.destFilterType || 'field',
destFilterList: taskInfo.destFilterList || [],
destFilterSql: taskInfo.destFilterSql || '',
updateDataList: taskInfo.updateDataList || [],
};
}
},
{ immediate: true },
);
watch(
() => formData.value.destDblinkId,
val => {
if (val) {
loadDblinkTableList(val).then(tableList => {
destTableList.value = tableList;
});
} else {
destTableList.value = [];
}
},
);
</script>
<style></style>

View File

@@ -7,6 +7,9 @@
:size="layoutStore.defaultFormItemSize"
:model="formData"
@submit.prevent
>
<template
v-if="flowEntry().value.flowType === FlowEntryType.NORMAL || props.type !== 'ReceiveTask'"
>
<el-form-item label="Java委托类">
<el-input
@@ -16,6 +19,73 @@
@change="updateServiceTaskClass"
/>
</el-form-item>
</template>
<template v-else>
<el-form-item label="任务类型">
<el-select
v-model="formData.actionType"
clearable
placeholder="请选择任务类型"
@change="onActionTypeChange"
>
<el-option-group label="数据操作">
<el-option
:label="AutoTaskActionType.getValue(AutoTaskActionType.INSERT)"
:value="AutoTaskActionType.INSERT"
/>
<el-option
:label="AutoTaskActionType.getValue(AutoTaskActionType.UPDATE)"
:value="AutoTaskActionType.UPDATE"
/>
<el-option
:label="AutoTaskActionType.getValue(AutoTaskActionType.DELETE)"
:value="AutoTaskActionType.DELETE"
/>
</el-option-group>
<el-option-group label="查询计算">
<el-option
:label="AutoTaskActionType.getValue(AutoTaskActionType.QUERY_SINGLE_DATA)"
:value="AutoTaskActionType.QUERY_SINGLE_DATA"
/>
</el-option-group>
<el-option-group label="开发者">
<el-option
:label="AutoTaskActionType.getValue(AutoTaskActionType.HTTP)"
:value="AutoTaskActionType.HTTP"
/>
</el-option-group>
</el-select>
</el-form-item>
<AutoInsertTaskSetting
v-if="formData.actionType === AutoTaskActionType.INSERT"
v-model="taskData"
:flowDblinkList="flowDblinkList"
@change="updateServiceTaskClass"
/>
<AutoQuerySingleDataSetting
v-if="formData.actionType === AutoTaskActionType.QUERY_SINGLE_DATA"
v-model="taskData"
:flowDblinkList="flowDblinkList"
@change="updateServiceTaskClass"
/>
<AutoHttpTaskSetting
v-if="formData.actionType === AutoTaskActionType.HTTP"
v-model="taskData"
@change="updateServiceTaskClass"
/>
<AutoUpdateTaskSetting
v-if="formData.actionType === AutoTaskActionType.UPDATE"
v-model="taskData"
:flowDblinkList="flowDblinkList"
@change="updateServiceTaskClass"
/>
<AutoDeleteTaskSetting
v-if="formData.actionType === AutoTaskActionType.DELETE"
v-model="taskData"
:flowDblinkList="flowDblinkList"
@change="updateServiceTaskClass"
/>
</template>
</el-form>
</div>
</template>
@@ -24,6 +94,13 @@
import { defineProps, ref, inject, watch, nextTick } from 'vue';
import { ANY_OBJECT } from '@/types/generic';
import { useLayoutStore } from '@/store';
import { FlowEntryType, AutoTaskActionType } from '@/common/staticDict/flow';
import { FlowDblinkController } from '@/api/flow';
import AutoInsertTaskSetting from './AutoInsertTaskSetting.vue';
import AutoQuerySingleDataSetting from './AutoQuerySingleDataSetting.vue';
import AutoHttpTaskSetting from './AutoHttpTaskSetting.vue';
import AutoUpdateTaskSetting from './AutoUpdateTaskSetting.vue';
import AutoDeleteTaskSetting from './AutoDeleteTaskSetting.vue';
const layoutStore = useLayoutStore();
const props = defineProps<{
@@ -34,27 +111,115 @@ const props = defineProps<{
const flowEntry = inject('flowEntry', () => {
return {} as ANY_OBJECT;
});
const formList = inject('formList', () => {
return {} as ANY_OBJECT;
});
const prefix = inject('prefix');
const flowVariableList = inject('flowVariableList', () => {
return [];
});
const autoTaskVariableList = inject('autoTaskVariableList', () => {
return [];
});
const win: ANY_OBJECT = window;
const getAllAutoVariableList = () => {
let tempFlowVariableList = flowVariableList();
let tempAutoTaskVariableList = autoTaskVariableList();
return [...tempFlowVariableList, ...tempAutoTaskVariableList];
};
provide('getAllAutoVariableList', getAllAutoVariableList);
type FormDataType = {
class: string;
actionType: number;
};
const formData = ref<FormDataType>({
class: '',
actionType: AutoTaskActionType.INSERT,
});
const taskInfoElement = ref();
let bpmnELement = win.bpmnInstances.bpmnElement;
const taskInfoElement = ref();
const taskData = ref();
const flowDblinkList = ref<ANY_OBJECT[]>([]);
const onActionTypeChange = () => {
taskData.value = undefined;
updateServiceTaskClass();
};
const loadFlowDblinkList = () => {
FlowDblinkController.list({})
.then(res => {
flowDblinkList.value = (res.data.dataList || []).map(item => {
return {
id: item.dblinkId,
name: item.dblinkName,
type: item.dblinkType,
};
});
})
.catch(e => {
console.error(e);
});
};
const resetTaskInfo = () => {
let bpmnELement = win.bpmnInstances.bpmnElement;
let elExtensionElements =
bpmnELement.businessObject.get('extensionElements') ||
win.bpmnInstances.moddle.create('bpmn:ExtensionElements', { values: [] });
taskInfoElement.value = elExtensionElements.values.filter(
ex => ex.$type === `${prefix}:TaskInfo`,
)[0];
if (taskInfoElement.value == null) {
taskInfoElement.value = win.bpmnInstances.moddle.create(`${prefix}:TaskInfo`, {
data: '{}',
});
}
taskData.value = taskInfoElement.value.data;
let actionType = AutoTaskActionType.INSERT;
if (taskData.value) {
let tempTaskData = taskData.value ? JSON.parse(taskData.value) : {};
console.log('tempTaskData', tempTaskData);
actionType = tempTaskData.actionType || AutoTaskActionType.INSERT;
}
formData.value = {
actionType,
class: bpmnELement.businessObject.class,
};
};
const updateServiceTaskClass = () => {
let bpmnELement = win.bpmnInstances.bpmnElement;
if (flowEntry().value.flowType === FlowEntryType.NORMAL) {
win.bpmnInstances.modeling.updateProperties(bpmnELement, {
class: formData.value.class,
});
win.bpmnInstances.modeling.updateProperties(bpmnELement, {
extensionElements: null,
});
return;
}
let elExtensionElements =
bpmnELement.businessObject.get('extensionElements') ||
win.bpmnInstances.moddle.create('bpmn:ExtensionElements', { values: [] });
let otherExtensions = elExtensionElements.values.filter(ex => ex.$type !== `${prefix}:TaskInfo`);
taskInfoElement.value.data =
taskData.value == null
? JSON.stringify({ actionType: formData.value.actionType })
: taskData.value;
const newElExtensionElements = win.bpmnInstances.moddle.create(`bpmn:ExtensionElements`, {
// values: otherExtensions.concat(this.taskInfoElement)
values: [taskInfoElement.value],
});
// 更新到元素上
win.bpmnInstances.modeling.updateProperties(bpmnELement, {
extensionElements: newElExtensionElements,
});
win.bpmnInstances.modeling.updateProperties(bpmnELement, {
class: undefined,
});
};
watch(
@@ -66,6 +231,10 @@ watch(
immediate: true,
},
);
onMounted(() => {
loadFlowDblinkList();
});
</script>
<style></style>

View File

@@ -0,0 +1,153 @@
<template>
<div class="form-single-fragment third-party-dlg" style="position: relative; height: 100%">
<el-form
ref="form"
:model="formData"
class="full-width-input form-box"
:rules="rules"
style="width: 100%"
label-width="100px"
:size="layoutStore.defaultFormItemSize"
label-position="right"
@submit.prevent
>
<el-form-item label="Key" prop="key">
<el-input v-model="formData.key" clearable :disabled="dialogParams.data != null" />
</el-form-item>
<el-form-item label="绑定值类型" prop="type">
<el-select v-model="formData.type" clearable placeholder="请选择绑定值类型">
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.FIXED)"
:value="AutoTaskValueType.FIXED"
/>
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.VARIABLE)"
:value="AutoTaskValueType.VARIABLE"
/>
</el-select>
</el-form-item>
<el-form-item label="绑定值" prop="srcValue">
<!-- 固定值 -->
<el-input
v-if="formData.type === AutoTaskValueType.FIXED"
v-model="formData.srcValue"
clearable
placeholder="请输入绑定值"
/>
<!-- 流程变量 -->
<el-input
v-else-if="formData.type === AutoTaskValueType.VARIABLE"
v-model="formData.srcValue"
clearable
placeholder="请输入流程变量"
/>
</el-form-item>
</el-form>
<el-row class="no-scroll flex-box menu-box" type="flex" justify="end" style="padding-top: 10px">
<el-button :size="layoutStore.defaultFormItemSize" :plain="true" @click="onCancel()">
取消
</el-button>
<el-button type="primary" :size="layoutStore.defaultFormItemSize" @click="onSubmit()">
保存
</el-button>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { ANY_OBJECT } from '@/types/generic';
import { AutoTaskValueType } from '@/common/staticDict/flow';
import { findTreeNodePath } from '@/common/utils';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
data?: ANY_OBJECT;
flowVariableList?: ANY_OBJECT[];
usedKeyList?: string[];
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = withDefaults(defineProps<IProps>(), {
data: undefined,
flowVariableList: undefined,
usedKeyList: undefined,
});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const form = ref();
type FormDataType = {
key: string;
type: number | string;
srcValue: string | string[];
};
const formData = ref<FormDataType>({
key: '',
type: AutoTaskValueType.FIXED,
srcValue: '',
});
const rules = {
key: [{ required: true, message: '请输入Key', trigger: 'blur' }],
srcValue: [{ required: true, message: '请输入Value', trigger: 'blur' }],
};
const dialogParams = computed(() => {
return {
data: props.data || thirdParams.value.data,
flowVariableList: props.flowVariableList || thirdParams.value.flowVariableList,
usedKeyList: props.usedKeyList || thirdParams.value.usedKeyList,
};
});
const finalUsedKeyList = computed(() => {
return dialogParams.value.data
? dialogParams.value.usedKeyList.filter(item => item !== dialogParams.value.data.key)
: dialogParams.value.usedKeyList;
});
const onCancel = () => {
if (props.dialog) {
props.dialog.cancel();
} else {
onCloseThirdDialog(false);
}
};
const onSubmit = () => {
if ((dialogParams.value.usedKeyList || []).includes(formData.value.key)) {
ElMessage.error('Key已存在');
return;
}
form.value.validate(valid => {
if (valid) {
let srcValue: string | string[] | undefined;
srcValue = formData.value.srcValue;
let tempData = {
...formData.value,
srcValue,
};
if (props.dialog) {
props.dialog.submit(tempData);
} else {
onCloseThirdDialog(true, dialogParams.value.data, tempData);
}
}
});
};
onMounted(() => {
if (dialogParams.value.data) {
let srcValue: string | undefined;
srcValue = dialogParams.value.data.srcValue;
formData.value = {
...formData.value,
...dialogParams.value.data,
srcValue: srcValue,
};
}
});
</script>
<style></style>

View File

@@ -0,0 +1,153 @@
<template>
<div class="form-single-fragment third-party-dlg" style="position: relative; height: 100%">
<el-form
ref="form"
:model="formData"
class="full-width-input form-box"
:rules="rules"
style="width: 100%"
label-width="100px"
:size="layoutStore.defaultFormItemSize"
label-position="right"
@submit.prevent
>
<el-form-item label="参数名称" prop="key">
<el-input v-model="formData.key" clearable :disabled="dialogParams.data != null" />
</el-form-item>
<el-form-item label="绑定值类型" prop="type">
<el-select v-model="formData.type" clearable placeholder="请选择绑定值类型">
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.FIXED)"
:value="AutoTaskValueType.FIXED"
/>
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.VARIABLE)"
:value="AutoTaskValueType.VARIABLE"
/>
</el-select>
</el-form-item>
<el-form-item label="参数值" prop="srcValue">
<!-- 固定值 -->
<el-input
v-if="formData.type === AutoTaskValueType.FIXED"
v-model="formData.srcValue"
clearable
placeholder="请输入参数值"
/>
<!-- 流程变量 -->
<el-input
v-else-if="formData.type === AutoTaskValueType.VARIABLE"
v-model="formData.srcValue"
clearable
placeholder="请输入流程变量"
/>
</el-form-item>
</el-form>
<el-row class="no-scroll flex-box menu-box" type="flex" justify="end" style="padding-top: 10px">
<el-button :size="layoutStore.defaultFormItemSize" :plain="true" @click="onCancel()">
取消
</el-button>
<el-button type="primary" :size="layoutStore.defaultFormItemSize" @click="onSubmit()">
保存
</el-button>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { ANY_OBJECT } from '@/types/generic';
import { AutoTaskValueType } from '@/common/staticDict/flow';
import { findTreeNodePath } from '@/common/utils';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
data?: ANY_OBJECT;
flowVariableList?: ANY_OBJECT[];
usedParamList?: ANY_OBJECT[];
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = withDefaults(defineProps<IProps>(), {
data: undefined,
flowVariableList: undefined,
usedParamList: undefined,
});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const form = ref();
type FormDataType = {
key: string;
type: number | string;
srcValue: string | string[];
};
const formData = ref<FormDataType>({
key: '',
type: AutoTaskValueType.FIXED,
srcValue: '',
});
const rules = {
key: [{ required: true, message: '请输入参数名称', trigger: 'blur' }],
type: [{ required: true, message: '请选择绑定值类型', trigger: 'blur' }],
srcValue: [{ required: true, message: '请输入参数值', trigger: 'blur' }],
};
const dialogParams = computed(() => {
return {
data: props.data || thirdParams.value.data,
flowVariableList: props.flowVariableList || thirdParams.value.flowVariableList,
usedParamList: props.usedParamList || thirdParams.value.usedParamList,
};
});
const finalUsedParamList = computed(() => {
return dialogParams.value.data
? dialogParams.value.usedParamList.filter(item => item !== dialogParams.value.data.key)
: dialogParams.value.usedParamList;
});
const onCancel = () => {
if (props.dialog) {
props.dialog.cancel();
} else {
onCloseThirdDialog(false);
}
};
const onSubmit = () => {
if ((finalUsedParamList.value || []).includes(formData.value.key)) {
ElMessage.error('参数名称已存在');
return;
}
form.value.validate(valid => {
if (valid) {
let srcValue: string | string[] | undefined;
srcValue = formData.value.srcValue;
let tempData = {
...formData.value,
srcValue,
};
if (props.dialog) {
props.dialog.submit(tempData);
} else {
onCloseThirdDialog(true, dialogParams.value.data, tempData);
}
}
});
};
onMounted(() => {
if (dialogParams.value.data) {
let srcValue = dialogParams.value.data.srcValue;
formData.value = {
...formData.value,
...dialogParams.value.data,
srcValue,
};
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,226 @@
<template>
<div class="form-single-fragment third-party-dlg" style="position: relative; height: 100%">
<el-form
ref="form"
:model="formData"
class="full-width-input form-box"
:rules="rules"
style="width: 100%"
label-width="100px"
:size="layoutStore.defaultFormItemSize"
label-position="right"
@submit.prevent
>
<el-form-item label="目标表字段" prop="destColumnName">
<el-select
v-model="formData.destColumnName"
clearable
filterable
:disabled="dialogParams.data != null"
placeholder="请选择字段名"
>
<el-option
v-for="item in columnList"
:key="item.columnName"
:label="item.columnName"
:value="item.columnName"
/>
</el-select>
</el-form-item>
<el-form-item label="字段值类型">
<el-select
v-model="formData.type"
clearable
placeholder="请选择值类型"
@change="onValueTypeChange"
>
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.FIXED)"
:value="AutoTaskValueType.FIXED"
/>
<el-option
v-if="dialogParams.srcDblinkId != null && dialogParams.srcTableName != null"
:label="AutoTaskValueType.getValue(AutoTaskValueType.FIELD)"
:value="AutoTaskValueType.FIELD"
/>
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.VARIABLE)"
:value="AutoTaskValueType.VARIABLE"
/>
</el-select>
</el-form-item>
<el-form-item label="字段值" prop="srcValue">
<!-- 固定值 -->
<el-input
v-if="formData.type === AutoTaskValueType.FIXED"
v-model="formData.srcValue"
clearable
placeholder="请输入字段值"
/>
<!-- 表字段名 -->
<el-select
v-else-if="formData.type === AutoTaskValueType.FIELD"
v-model="formData.srcValue"
clearable
filterable
placeholder="请选择字段名"
>
<el-option
v-for="item in srcColumnList"
:key="item.columnName"
:label="item.columnName"
:value="item.columnName"
/>
</el-select>
<!-- 流程变量 -->
<el-input
v-else-if="formData.type === AutoTaskValueType.VARIABLE"
v-model="formData.srcValue"
clearable
placeholder="请输入流程变量"
/>
</el-form-item>
</el-form>
<el-row class="no-scroll flex-box menu-box" type="flex" justify="end" style="padding-top: 10px">
<el-button :size="layoutStore.defaultFormItemSize" :plain="true" @click="onCancel()">
取消
</el-button>
<el-button type="primary" :size="layoutStore.defaultFormItemSize" @click="onSubmit()">
保存
</el-button>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ANY_OBJECT } from '@/types/generic';
import { AutoTaskValueType } from '@/common/staticDict/flow';
import { findTreeNodePath } from '@/common/utils';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
import { FlowDblinkController } from '@/api/flow';
const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
dblinkId?: string;
tableName?: string;
srcDblinkId?: string;
srcTableName?: string;
data?: ANY_OBJECT;
flowVariableList?: ANY_OBJECT[];
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = withDefaults(defineProps<IProps>(), {
dblinkId: undefined,
tableName: undefined,
srcDblinkId: undefined,
srcTableName: undefined,
data: undefined,
flowVariableList: undefined,
});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const form = ref();
type FormDataType = {
type: number | string;
destColumnName: string;
srcValue: string | string[] | undefined;
};
const formData = ref<FormDataType>({
type: AutoTaskValueType.FIXED,
destColumnName: '',
srcValue: '',
});
const columnList = ref<ANY_OBJECT[]>([]);
const srcColumnList = ref<ANY_OBJECT[]>([]);
const rules = ref({
destColumnName: [{ required: true, message: '请输入字段名', trigger: 'blur' }],
srcValue: [{ required: true, message: '请输入字段值', trigger: 'blur' }],
});
const dialogParams = computed(() => {
return {
dblinkId: props.dblinkId || thirdParams.value.dblinkId,
tableName: props.tableName || thirdParams.value.tableName,
srcDblinkId: props.srcDblinkId || thirdParams.value.srcDblinkId,
srcTableName: props.srcTableName || thirdParams.value.srcTableName,
data: props.data || thirdParams.value.data,
flowVariableList: props.flowVariableList || thirdParams.value.flowVariableList || [],
};
});
const getColumnList = () => {
if (dialogParams.value.dblinkId == null || dialogParams.value.tableName == null) {
return;
}
FlowDblinkController.listDblinkTableColumns({
dblinkId: dialogParams.value.dblinkId,
tableName: dialogParams.value.tableName,
}).then(res => {
columnList.value = res.data;
});
};
const getSrcColumnList = () => {
if (
dialogParams.value.srcDblinkId == null ||
dialogParams.value.srcTableName == null ||
dialogParams.value.srcDblinkId === '' ||
dialogParams.value.srcTableName === ''
) {
return;
}
FlowDblinkController.listDblinkTableColumns({
dblinkId: dialogParams.value.srcDblinkId,
tableName: dialogParams.value.srcTableName,
}).then(res => {
srcColumnList.value = res.data;
});
};
const onValueTypeChange = () => {
formData.value.srcValue = undefined;
};
const onCancel = () => {
if (props.dialog) {
props.dialog.cancel();
} else {
onCloseThirdDialog(false);
}
};
const onSubmit = () => {
form.value.validate(valid => {
if (valid) {
let srcValue: string | string[] | undefined;
srcValue = formData.value.srcValue;
let tempData = {
...formData.value,
srcValue,
};
if (props.dialog) {
props.dialog.submit(tempData);
} else {
onCloseThirdDialog(true, dialogParams.value.data, tempData);
}
}
});
};
onMounted(() => {
getColumnList();
getSrcColumnList();
if (dialogParams.value.data) {
let srcValue = dialogParams.value.data.srcValue;
formData.value = {
...formData.value,
...dialogParams.value.data,
srcValue,
};
}
});
</script>
<style></style>

View File

@@ -0,0 +1,148 @@
<template>
<div class="form-single-fragment third-party-dlg" style="position: relative; height: 100%">
<el-form
ref="form"
:model="formData"
class="full-width-input form-box"
:rules="rules"
style="width: 100%"
label-width="100px"
:size="layoutStore.defaultFormItemSize"
label-position="right"
@submit.prevent
>
<el-form-item label="父字段">
<el-cascader
v-model="parentPath"
:options="dialogParams.usedFieldList"
:props="{
value: 'id',
label: 'fieldName',
children: 'children',
checkStrictly: true,
disabled: 'disabled',
}"
clearable
filterable
:disabled="dialogParams.data != null"
placeholder="请选择父字段"
@change="onParentChange"
/>
</el-form-item>
<el-form-item label="字段名" prop="fieldName" :disabled="dialogParams.data != null">
<el-input v-model="formData.fieldName" clearable />
</el-form-item>
<el-form-item label="字段类型" prop="fieldType">
<el-select v-model="formData.fieldType" clearable placeholder="请选择字段类型">
<el-option v-for="item in ValidFieldTypes" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
</el-form>
<el-row class="no-scroll flex-box menu-box" type="flex" justify="end" style="padding-top: 10px">
<el-button :size="layoutStore.defaultFormItemSize" :plain="true" @click="onCancel()">
取消
</el-button>
<el-button type="primary" :size="layoutStore.defaultFormItemSize" @click="onSubmit()">
保存
</el-button>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { ANY_OBJECT } from '@/types/generic';
import { AutoTaskValueType } from '@/common/staticDict/flow';
import { findTreeNodePath, findTreeNodeObjectPath } from '@/common/utils';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
const ValidFieldTypes = ref(['String', 'Number', 'Boolean', 'Object', 'Array']);
const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
data?: ANY_OBJECT;
usedFieldList?: ANY_OBJECT[];
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = withDefaults(defineProps<IProps>(), {
data: undefined,
usedFieldList: undefined,
});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const form = ref();
type FormDataType = {
id: number | string | undefined;
parentId: number | string | undefined;
fieldName: string;
fieldType: string;
};
const formData = ref<FormDataType>({
id: undefined,
parentId: undefined,
fieldName: '',
fieldType: 'String',
});
const parentPath = ref<Array<string | number>>([]);
const rules = {
fieldName: [{ required: true, message: '请输入字段名', trigger: 'blur' }],
fieldType: [{ required: true, message: '请输入字段类型', trigger: 'blur' }],
};
const dialogParams = computed(() => {
return {
data: props.data || thirdParams.value.data,
usedFieldList: props.usedFieldList || thirdParams.value.usedFieldList || [],
};
});
const parentNode = computed(() => {
let parentNodePath = findTreeNodeObjectPath(dialogParams.value.usedFieldList, formData.value.parentId);
return parentNodePath ? parentNodePath[parentNodePath.length - 1] : null;
});
const onParentChange = (value: Array<string | number>) => {
formData.value.parentId = parentPath.value[parentPath.value.length - 1];
};
const onCancel = () => {
if (props.dialog) {
props.dialog.cancel();
} else {
onCloseThirdDialog(false);
}
};
const onSubmit = () => {
let childList = parentNode.value ? parentNode.value.children : dialogParams.value.usedFieldList;
if ((childList || []).some(item => item.fieldName === formData.value.fieldName)) {
ElMessage.error('字段名已存在');
return;
}
form.value.validate(valid => {
if (valid) {
formData.value.parentId = parentNode.value ? parentNode.value.id : undefined;
formData.value.id = parentNode.value
? parentNode.value.id + '.' + formData.value.fieldName
: formData.value.fieldName;
if (props.dialog) {
props.dialog.submit(formData.value);
} else {
onCloseThirdDialog(true, dialogParams.value.data, formData.value);
}
}
});
};
onMounted(() => {
if (dialogParams.value.data) {
formData.value = {
...formData.value,
...dialogParams.value.data,
};
parentPath.value = findTreeNodePath(
dialogParams.value.usedFieldList,
dialogParams.value.data.parentId,
);
}
});
</script>
<style scoped></style>

View File

@@ -0,0 +1,192 @@
<template>
<div class="form-single-fragment third-party-dlg" style="position: relative; height: 100%">
<el-form
ref="form"
:model="formData"
class="full-width-input form-box"
:rules="rules"
style="width: 100%"
label-width="100px"
:size="layoutStore.defaultFormItemSize"
label-position="right"
@submit.prevent
>
<el-form-item label="过滤字段" prop="filterColumnName">
<el-select
v-model="formData.filterColumnName"
clearable
filterable
:disabled="dialogParams.data != null"
placeholder="请选择过滤字段"
>
<el-option
v-for="item in columnList"
:key="item.columnName"
:label="item.columnName"
:value="item.columnName"
/>
</el-select>
</el-form-item>
<el-form-item label="过滤类型">
<el-select v-model="formData.filterType" placeholder="请选择过滤类型">
<el-option
v-for="item in CriteriaFilterType.getList()"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="字段值类型">
<el-select
v-model="formData.valueType"
placeholder="请选择过滤值类型"
@change="onValueTypeChange"
>
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.FIXED)"
:value="AutoTaskValueType.FIXED"
/>
<el-option
:label="AutoTaskValueType.getValue(AutoTaskValueType.VARIABLE)"
:value="AutoTaskValueType.VARIABLE"
/>
</el-select>
</el-form-item>
<el-form-item label="过滤值" prop="filterValue">
<!-- 固定值 -->
<el-input
v-if="formData.valueType === AutoTaskValueType.FIXED"
v-model="formData.filterValue"
clearable
placeholder="请输入过滤值"
/>
<!-- 流程变量 -->
<el-input
v-else-if="formData.valueType === AutoTaskValueType.VARIABLE"
v-model="formData.filterValue"
clearable
placeholder="请输入流程变量"
/>
</el-form-item>
</el-form>
<el-row class="no-scroll flex-box menu-box" type="flex" justify="end" style="padding-top: 10px">
<el-button :size="layoutStore.defaultFormItemSize" :plain="true" @click="onCancel()">
取消
</el-button>
<el-button type="primary" :size="layoutStore.defaultFormItemSize" @click="onSubmit()">
保存
</el-button>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ANY_OBJECT } from '@/types/generic';
import { AutoTaskValueType } from '@/common/staticDict/flow';
import { FlowDblinkController, FlowEntryVariableController } from '@/api/flow';
import { CriteriaFilterType } from '@/common/staticDict/index';
import { findTreeNodePath } from '@/common/utils';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
dblinkId?: string;
tableName?: string;
data?: ANY_OBJECT;
flowVariableList?: ANY_OBJECT[];
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = withDefaults(defineProps<IProps>(), {
dblinkId: undefined,
tableName: undefined,
data: undefined,
flowVariableList: undefined,
});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const form = ref();
type FormDataType = {
id: number | undefined;
filterColumnName: string;
filterType: number;
valueType: number;
filterValue?: string | string[];
};
const formData = ref<FormDataType>({
id: undefined,
filterColumnName: '',
filterType: 0,
valueType: AutoTaskValueType.FIXED,
filterValue: '',
});
const columnList = ref<ANY_OBJECT[]>([]);
const rules = {
filterColumnName: [{ required: true, message: '请选择过滤字段', trigger: 'blur' }],
filterType: [{ required: true, message: '请选择过滤类型', trigger: 'blur' }],
filterValue: [{ required: true, message: '请输入过滤值', trigger: 'blur' }],
};
const dialogParams = computed(() => {
return {
dblinkId: props.dblinkId || thirdParams.value.dblinkId,
tableName: props.tableName || thirdParams.value.tableName,
data: props.data || thirdParams.value.data,
flowVariableList: props.flowVariableList || thirdParams.value.flowVariableList,
};
});
const onValueTypeChange = () => {
formData.value.filterValue = undefined;
};
const getColumnList = () => {
if (dialogParams.value.dblinkId == null || dialogParams.value.tableName == null) {
return;
}
FlowDblinkController.listDblinkTableColumns({
dblinkId: dialogParams.value.dblinkId,
tableName: dialogParams.value.tableName,
}).then(res => {
columnList.value = res.data;
});
};
const onCancel = () => {
if (props.dialog) {
props.dialog.cancel();
} else {
onCloseThirdDialog(false);
}
};
const onSubmit = () => {
form.value.validate(valid => {
if (valid) {
let tempData = {
...formData.value,
};
if (tempData.id == null) tempData.id = new Date().getTime();
if (props.dialog) {
props.dialog.submit(tempData);
} else {
onCloseThirdDialog(true, dialogParams.value.data, tempData);
}
}
});
};
onMounted(() => {
getColumnList();
if (dialogParams.value.data) {
let filterValue = dialogParams.value.data.filterValue;
formData.value = {
...dialogParams.value.data,
valueType: dialogParams.value.data.valueType || 0,
filterValue,
};
}
});
</script>
<style></style>

View File

@@ -261,15 +261,6 @@ const onSetOnlineFormAuth = () => {
console.warn(e);
});
};
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdEditOperation' && data.isSuccess) {
updateEditOperation(data.data);
} else if (data.path === 'thirdSetOnlineFormAuth' && data.isSuccess) {
formData.value.formAuth = data.data;
updateElementFormKey();
}
};
const resetFormList = () => {
bpmnElement = win.bpmnInstances.bpmnElement;
let formKey = bpmnElement.businessObject.formKey;
@@ -420,7 +411,7 @@ watch(
},
);
defineExpose({ refreshData, onEditOperation });
defineExpose({ onEditOperation });
</script>
<style lang="scss" scoped>

View File

@@ -168,7 +168,7 @@ import { SysCommonBizController } from '@/api/system';
import { findTreeNodePath, treeDataTranslate, findItemFromList } from '@/common/utils';
import TaskGroupSelect from '@/pages/workflow/components/TaskGroupSelect.vue';
import TagSelect from '@/pages/workflow/components/TagSelect.vue';
import { SysFlowTaskOperationType } from '@/common/staticDict/flow';
import { SysFlowTaskOperationType, FlowEntryType } from '@/common/staticDict/flow';
import { Dialog } from '@/components/Dialog';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
@@ -179,11 +179,15 @@ const layoutStore = useLayoutStore();
interface IProps extends ThirdProps {
rowData?: ANY_OBJECT;
validStatusList?: ANY_OBJECT[];
flowType?: string | number;
// 当使用Dialog.show弹出组件时须定义该prop属性以便对dialog进行回调
dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = withDefaults(defineProps<IProps>(), {
validStatusList: () => [],
rowData: undefined,
validStatusList: undefined,
flowType: undefined,
dialog: undefined,
});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
@@ -216,6 +220,7 @@ const dialogParams = computed(() => {
return {
rowData: props.rowData || thirdParams.value.rowData,
validStatusList: props.validStatusList || thirdParams.value.validStatusList || [],
flowType: props.flowType || thirdParams.value.flowType,
};
});
const multiSignGroupList = computed(() => {
@@ -235,7 +240,18 @@ const multiSignGroupList = computed(() => {
}
});
const getValidOperationList = computed(() => {
let autoSupportOperationList = [
SysFlowTaskOperationType.REJECT,
SysFlowTaskOperationType.REJECT_TO_TASK,
SysFlowTaskOperationType.MULTI_SIGN,
SysFlowTaskOperationType.MULTI_AGREE,
SysFlowTaskOperationType.MULTI_REFUSE,
SysFlowTaskOperationType.MULTI_ABSTAIN,
];
return SysFlowTaskOperationType.getList().filter(item => {
if (dialogParams.value.flowType === FlowEntryType.AUTO_TASK) {
return autoSupportOperationList.indexOf(item.id) !== -1;
}
return (
[
SysFlowTaskOperationType.INTERVENE,
@@ -653,15 +669,6 @@ onMounted(() => {
}
}
});
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdTaskUserSelect' && data.isSuccess) {
updateSelectUser(data.data);
} else if (data.path === 'thirdTaskGroupSelect' && data.isSuccess) {
updateSelectDept(data.data);
}
};
defineExpose({ refreshData });
</script>
<style scoped>

View File

@@ -38,7 +38,7 @@
:model="newMessageForm"
:size="layoutStore.defaultFormItemSize"
label-width="90px"
@submit.native.prevent
@submit.prevent
>
<el-form-item label="消息ID">
<el-input v-model="newMessageForm.id" clearable />

View File

@@ -774,19 +774,6 @@ const updateElementTask = (key: string) => {
win.bpmnInstances.modeling.updateProperties(win.bpmnInstances.bpmnElement, taskAttr);
};
const refreshData = (data: ANY_OBJECT) => {
if (data.path === 'thirdTaskUserSelect' && data.isSuccess) {
updateAssignee(data.data);
} else if (data.path === 'thirdTaskUserSelectCandidateUsers' && data.isSuccess) {
updateCandidateUsers(data.data);
} else if (data.path === 'thirdTaskGroupSelect' && data.isSuccess) {
updateDept(data.data);
} else if (data.path === 'thirdTaskPostSelect' && data.isSuccess) {
updatePost(data.data);
}
};
defineExpose({ refreshData });
onBeforeUnmount(() => {
groupMap = null;
postMap = null;

View File

@@ -77,10 +77,7 @@
:size="layoutStore.defaultFormItemSize"
type="danger"
link
:disabled="
scope.row.endTime != null ||
!checkPermCodeExist('formAllInstance:formAllInstance:stop')
"
:disabled="scope.row.endTime != null"
@click="onStopTask(scope.row)"
>
终止
@@ -89,10 +86,7 @@
:size="layoutStore.defaultFormItemSize"
type="danger"
link
:disabled="
scope.row.endTime == null ||
!checkPermCodeExist('formAllInstance:formAllInstance:delete')
"
:disabled="scope.row.endTime == null"
@click="onDeleteTask(scope.row)"
>
删除
@@ -123,14 +117,13 @@ import { Dialog } from '@/components/Dialog';
import { useTable } from '@/common/hooks/useTable';
import { TableOptions } from '@/common/types/pagination';
import { FlowOperationController } from '@/api/flow';
import { FlowEntryType } from '@/common/staticDict/flow';
import { ANY_OBJECT } from '@/types/generic';
import { usePermissions } from '@/common/hooks/usePermission';
import { useLayoutStore } from '@/store';
import FormTaskProcessViewer from './formTaskProcessViewer.vue';
import StopTask from './stopTask.vue';
import FormTaskProcessViewer from './formTaskProcessViewer.vue';
const layoutStore = useLayoutStore();
const { checkPermCodeExist } = usePermissions();
const form = ref();
const formFilter = reactive({
@@ -275,14 +268,10 @@ onMounted(() => {
formInit();
});
const refreshData = () => {
refreshFormAllInstance();
};
const onResume = () => {
refreshFormAllInstance();
};
defineExpose({
refreshData,
onResume,
});
</script>

View File

@@ -3,6 +3,7 @@
<div class="form-single-fragment" style="position: relative">
<el-row>
<ProcessViewer
v-if="finishedInfo != null"
:xml="taskProcessXml"
:finishedInfo="finishedInfo"
:allCommentList="flowTaskCommentList"

View File

@@ -152,7 +152,7 @@ export const routers: Array<RouteRecordRaw> = [
props: getProps,
meta: { title: '在线表单' },
},
// 流模管理
// 工作流模块
{
path: 'formMessage',
component: () => import('@/pages/workflow/formMessage/index.vue'),
@@ -271,6 +271,12 @@ export const routers: Array<RouteRecordRaw> = [
component: () => import('@/pages/workflow/components/UserTaskSelect/userTaskSelectDlg.vue'),
},
// 流程设计
{
path: 'thirdEditFlowDblink',
name: 'thirdEditFlowDblink',
props: getProps,
component: () => import('@/pages/workflow/formFlowDblink/editFlowDblink.vue'),
},
{
path: 'thirdFormFlowEntry',
name: 'thirdFormFlowEntry',
@@ -351,6 +357,41 @@ export const routers: Array<RouteRecordRaw> = [
props: getProps,
component: () => import('@/pages/workflow/components/TaskCommit.vue'),
},
// 自动化任务 - 编辑过滤条件
{
path: 'thirdEditTableFilter',
name: 'thirdEditTableFilter',
props: getProps,
component: () => import('@/pages/workflow/package/refactor/form/editSrcTableFilter.vue'),
},
// 自动化任务 - 编辑更新字段
{
path: 'thirdEditFieldUpdateData',
name: 'thirdEditFieldUpdateData',
props: getProps,
component: () => import('@/pages/workflow/package/refactor/form/editInsertData.vue'),
},
// 自动化任务 - 编辑响应字段
{
path: 'thirdEditResponseData',
name: 'thirdEditResponseData',
props: getProps,
component: () => import('@/pages/workflow/package/refactor/form/editResponseData.vue'),
},
// 自动化任务 - 编辑HTTP请求参数
{
path: 'thirdEditHttpRequestParam',
name: 'thirdEditHttpRequestParam',
props: getProps,
component: () => import('@/pages/workflow/package/refactor/form/editHttpParameter.vue'),
},
// 自动化任务 - 编辑HTTP请求头
{
path: 'thirdEditHttpHeader',
name: 'thirdEditHttpHeader',
props: getProps,
component: () => import('@/pages/workflow/package/refactor/form/editHttpHeader.vue'),
},
// 待办任务
{
path: 'thirdFormMyTask',