初始版本提交

This commit is contained in:
yaoyn
2024-02-05 09:15:37 +08:00
parent b52d4414be
commit 445292105f
1848 changed files with 236859 additions and 75 deletions

View File

@ -0,0 +1,58 @@
<template>
<SelectApiConfig
v-model="config"
:paramTree="ProcessDataVariable"
:exampleStr="exampleStr"
@update:modelValue="submit"
>
<slot></slot>
</SelectApiConfig>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { SelectApiConfig } from '/@/components/ApiConfig';
import { useMessage } from '/@/hooks/web/useMessage';
import { ApiConfig } from '/@/components/ApiConfig/src/interface';
import { ProcessDataVariable } from '/@bpmn/config/rules';
import { MemberConfig } from '/@/model/workflow/memberSetting';
import { MemberType } from '/@/enums/workflowEnum';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emit = defineEmits(['change']);
let props = withDefaults(defineProps<{ memberList: Array<MemberConfig> }>(), {
memberList: () => {
return [];
},
});
let config = ref<ApiConfig>();
const exampleStr = `{
code: 0,
msg: 'success',
data: '1830999999983899309,2835993035383895389', //用户ID可以多个用逗号分隔
}`;
const memberType = MemberType.API;
const { notification } = useMessage();
function submit() {
let list: Array<MemberConfig> = [];
if (props.memberList.length > 0) {
list = props.memberList.filter((ele: MemberConfig) => {
if (ele.memberType != memberType) return ele;
});
}
if (config.value?.path) {
list.push({
memberType: memberType,
id: config.value.id,
name: config.value.path,
apiConfig: config.value,
});
emit('change', [...list]);
} else {
notification.warning({
message: t('提示'),
description: t('您没有选择API'),
});
}
}
</script>

View File

@ -0,0 +1,185 @@
<template>
<div>
<div @click="show"><slot></slot></div>
<ModalPanel
:visible="visible"
:width="400"
:title="t('表单字段配置人员')"
@submit="submit"
@close="close"
>
<div class="title">
<NodeHead :node-name="t('表单字段列表')" />
</div>
<div class="list-box" v-if="Object.keys(expandedNames).length > 0">
<a-tree
checkable
:tree-data="nodes.treeData"
autoExpandParent
defaultExpandAll
v-model:checkedKeys="checkedKeys"
/>
</div>
<EmptyBox v-else />
</ModalPanel>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { useBpmnStore } from '/@bpmn/store/bpmn';
import { BpmnNodeKey, MemberType } from '/@/enums/workflowEnum';
import { FormFiledConfig, MemberConfig } from '/@/model/workflow/memberSetting';
import { ModalPanel, EmptyBox } from '/@/components/ModalPanel/index';
import { NodeHead } from '/@/components/ModalPanel/index';
import { TreeProps } from 'ant-design-vue';
import { separator } from '../../config/info';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits(['change']);
const props = withDefaults(
defineProps<{
memberList: Array<MemberConfig>;
}>(),
{
memberList: () => {
return [];
},
},
);
const visible = ref(false);
const memberType = MemberType.FORM_FIELD;
let nodes: { treeData: TreeProps['treeData'] } = reactive({
treeData: [],
});
const checkedKeys = ref<string[]>([]);
const expandedNames = ref<{}>({});
let selectedList: { list: Array<MemberConfig> } = reactive({ list: [] });
function show() {
checkedKeys.value = [];
nodes.treeData = [];
if (props.memberList.length > 0) {
selectedList.list = props.memberList.filter((ele: MemberConfig) => {
if (ele.memberType === memberType) return ele;
});
if (selectedList.list.length > 0) {
selectedList.list.forEach((ele) => {
if (ele.formFieldConfig) {
checkedKeys.value.push(
ele.formFieldConfig.nodeId +
separator +
ele.formFieldConfig.formId +
separator +
ele.formFieldConfig.formField +
separator +
ele.formFieldConfig.formKey,
);
}
});
}
}
const store = useBpmnStore();
const { info } = store;
for (let item of info.values()) {
let showNodeTypes = [BpmnNodeKey.START, BpmnNodeKey.USER];
if (showNodeTypes.includes(item.type)) {
let name = item.name ? item.name : item.type;
let id = item.id;
let info: FormFiledConfig = {
title: name,
key: id,
disabled: true,
children: [],
};
if (item.formConfigs && item.formConfigs.length > 0) {
item.formConfigs.forEach((ele1) => {
let formChildren: Array<FormFiledConfig> = [];
if (ele1.children && ele1.children.length > 0) {
ele1.children.forEach((ele2) => {
let key =
id + separator + ele1.formId + separator + ele2.fieldId + separator + ele1.key;
formChildren.push({
title: ele2.fieldName,
key,
disabled: false,
children: [],
});
expandedNames.value[key] = name + '-' + ele1.formName + '-' + ele2.fieldName;
});
}
info.children.push({
title: ele1.formName,
key: id + separator + ele1.formId,
disabled: true,
children: formChildren,
});
});
}
nodes.treeData.push(info);
}
}
visible.value = true;
}
function submit() {
let list: Array<MemberConfig> = [];
if (props.memberList.length > 0) {
list = props.memberList.filter((ele: MemberConfig) => {
if (ele.memberType != memberType) return ele;
});
}
console.log(checkedKeys.value, 'sss');
for (const item of checkedKeys.value) {
let arr = item.split(separator);
if (arr.length === 4) {
let nodeId = arr[0];
let formId = arr[1];
let formField = arr[2];
let formKey = arr[3];
list.push({
memberType: memberType,
id: nodeId,
name: expandedNames.value[item],
formFieldConfig: { nodeId, formId, formField, formKey },
});
}
}
console.log(list, 'list');
emits('change', [...list]);
close();
}
function close() {
visible.value = false;
}
</script>
<style scoped>
.title {
display: flex;
justify-content: space-between;
height: 40px;
font-size: 16px;
color: #333333;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 10px;
}
.list-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
overflow: auto;
}
:deep(.ant-tree-treenode) {
margin-left: 8px;
margin-bottom: 10px;
}
:deep(.ant-tree-list) {
height: 460px;
}
</style>

View File

@ -0,0 +1,153 @@
<template>
<div class="list-box">
<div class="opr-box">
<div class="header-box"><NodeHead :nodeName="t('人员列表')" /></div>
<div class="button-box">
<div v-for="(item, index) in allComponentList" :key="index">
<component
v-if="item.show"
:is="item.component"
:memberList="props.memberList"
@change="changeList"
>
<a-button type="primary">{{ item.name }}</a-button>
</component>
</div>
</div>
</div>
<a-table :dataSource="props.memberList" :columns="configColumns" :pagination="false">
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'memberType'">
{{ getMemberType(record.memberType) }}
</template>
<template v-if="column.key === 'operation'">
<Icon icon="ant-design:delete-outlined" class="delete-icon" @click="deleteItem(index)" />
</template>
</template>
</a-table>
</div>
</template>
<script setup lang="ts">
import { NodeHead } from '/@/components/ModalPanel/index';
import Icon from '/@/components/Icon/index';
import Posts from '/@bpmn/components/member/Posts.vue';
import Roles from '/@bpmn/components/member/Roles.vue';
import Users from '/@bpmn/components/member/Users.vue';
import NodeApprover from '/@bpmn/components/member/NodeApprover.vue';
import UpperManagement from '/@bpmn/components/member/UpperManagement.vue';
import FormFields from '/@bpmn/components/member/FormFields.vue';
import { MemberType } from '/@/enums/workflowEnum';
import { MemberConfig } from '/@/model/workflow/memberSetting';
import { computed } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
import ApiSelect from '/@bpmn/components/member/ApiSelect.vue';
const { t } = useI18n();
const emits = defineEmits(['update:memberList']);
const props = withDefaults(
defineProps<{
isCommonType: Boolean;
isUpper?: Boolean;
isApiApprover?: Boolean;
memberList: Array<MemberConfig>;
}>(),
{
isCommonType: () => false,
isUpper: () => false,
isApiApprover: () => false,
memberList: () => {
return [];
},
},
);
const configColumns = [
{
title: t('类型'),
dataIndex: 'memberType',
key: 'memberType',
align: 'center',
},
{
title: t('名称'),
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: t('操作'),
dataIndex: 'operation',
key: 'operation',
align: 'center',
},
];
const allComponentList = computed(() => {
return [
{ name: t('添加岗位'), component: Posts, show: true },
{ name: t('添加角色'), component: Roles, show: true },
{ name: t('添加人员'), component: Users, show: true },
{ name: t('节点审批人'), component: NodeApprover, show: props.isCommonType ? false : true },
{
name: t('上级领导'),
component: UpperManagement,
show: props.isCommonType ? false : props.isUpper ? false : true,
},
{ name: t('表单字段'), component: FormFields, show: props.isCommonType ? false : true },
{ name: t('API审批人'), component: ApiSelect, show: props.isApiApprover ? true : false },
];
});
// 类型
function getMemberType(val: MemberType) {
if (val === MemberType.POST) return t('岗位');
if (val === MemberType.ROLE) return t('角色');
if (val === MemberType.USER) return t('人员');
if (val === MemberType.SPECIFY_NODE_APPROVER) return t('指定审批人');
if (val === MemberType.SUPERIOR_LEADERS) return t('上级领导');
if (val === MemberType.FORM_FIELD) return t('表单字段');
if (val === MemberType.API) return t('API审批人');
return val;
}
function changeList(list: Array<MemberConfig>) {
emits('update:memberList', list);
}
function deleteItem(index: number) {
let list = props.memberList;
list.splice(index, 1);
emits('update:memberList', list);
}
</script>
<style lang="less" scoped>
.list-box {
.opr-box {
display: flex;
justify-content: space-between;
margin-bottom: 6px;
.header-box {
flex-basis: 220px;
align-items: flex-start;
margin-bottom: -10px;
}
}
.button-box {
display: flex;
align-items: center;
flex-wrap: wrap;
:deep(button) {
margin: 4px;
width: 88px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.delete-icon {
color: @clear-color;
}
</style>

View File

@ -0,0 +1,125 @@
<template>
<div>
<div @click="show"><slot></slot></div>
<ModalPanel
:visible="visible"
:width="400"
:title="t('指定节点审批人')"
@submit="submit"
@close="close"
>
<div class="title">
<NodeHead :node-name="t('节点列表')" />
</div>
<div class="list-box">
<a-checkbox
v-for="(item, index) in nodes.list"
:key="index"
:value="item.id"
size="small"
v-model:checked="item.checked"
>{{ item.name }}</a-checkbox
>
</div>
</ModalPanel>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { MemberType } from '/@/enums/workflowEnum';
import { MemberConfig, NodesConfig } from '/@/model/workflow/memberSetting';
import { NodeHead, ModalPanel } from '/@/components/ModalPanel/index';
import { InfoId } from '/@/model/workflow/bpmnConfig';
import { getNodeList } from '/@bpmn/config/info';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits(['change']);
const props = withDefaults(
defineProps<{
memberList: Array<MemberConfig>;
}>(),
{
memberList: () => {
return [];
},
},
);
const visible = ref(false);
const memberType = MemberType.SPECIFY_NODE_APPROVER;
let nodes: { list: Array<NodesConfig> } = reactive({
list: [],
});
function show() {
nodes.list = [];
let selectIds: Array<InfoId> = [];
if (props.memberList.length > 0) {
selectIds = props.memberList
.filter((ele: MemberConfig) => {
if (ele.memberType && ele.memberType === memberType) return ele;
})
.map((ele: MemberConfig) => {
return ele.id;
});
}
getNodeList().map((item) => {
nodes.list.push({ id: item.id, name: item.name, checked: selectIds.includes(item.id) });
});
visible.value = true;
}
function submit() {
let list: Array<MemberConfig> = [];
if (props.memberList.length > 0) {
list = props.memberList.filter((ele: MemberConfig) => {
if (ele.memberType != memberType) return ele;
});
}
nodes.list.forEach((item: NodesConfig) => {
if (item.checked) {
list.push({
memberType: memberType,
name: item.name,
id: item.id,
});
}
});
emits('change', [...list]);
close();
}
function close() {
visible.value = false;
}
</script>
<style scoped>
.title {
display: flex;
justify-content: space-between;
height: 40px;
font-size: 16px;
color: #333333;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 10px;
}
.list-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
margin: 0 20px;
}
:deep(.ant-checkbox-wrapper) {
margin-left: 8px;
margin-bottom: 10px;
}
:deep(.ant-checkbox-inner) {
border-radius: unset;
}
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
border-radius: unset;
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<div>
<SelectPost :selectedIds="selectedIds" :multiple="true" @change="submit">
<a-button type="primary">{{ t('添加岗位') }}</a-button>
</SelectPost>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getPostMulti } from '/@/api/system/post';
import { SelectPost } from '/@/components/SelectOrganizational/index';
import { MemberType } from '/@/enums/workflowEnum';
import { MemberConfig } from '/@/model/workflow/memberSetting';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits(['change']);
const props = withDefaults(
defineProps<{
memberList: Array<MemberConfig>;
}>(),
{
memberList: () => {
return [];
},
},
);
let selectedIds = computed(() => {
if (props.memberList && props.memberList.length > 0) {
return props.memberList
.filter((ele: MemberConfig) => {
return ele.memberType === MemberType.POST;
})
.map((ele: MemberConfig) => {
return ele.id;
});
} else {
return [];
}
});
async function submit(ids: Array<string>) {
let list: Array<MemberConfig> = [];
if (props.memberList && props.memberList.length > 0) {
props.memberList.forEach((ele) => {
if (ele.memberType != MemberType.POST)
list.push({
name: ele.name,
id: ele.id,
memberType: ele.memberType,
});
});
}
try {
let postRes = await getPostMulti(ids.join(','));
if (postRes.length > 0) {
postRes.forEach((ele) => {
list.push({
name: ele.name,
id: ele.id,
memberType: MemberType.POST,
});
});
}
} catch (error) {
ids.forEach((id) => {
if (id)
list.push({
name: id,
id: id,
memberType: MemberType.POST,
});
});
}
emits('change', list);
}
</script>

View File

@ -0,0 +1,78 @@
<template>
<div>
<SelectRole :selectedIds="selectedIds" :multiple="true" @change="submit">
<a-button type="primary">{{ t('添加角色') }}</a-button>
</SelectRole>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getRoleMulti } from '/@/api/system/role';
import { SelectRole } from '/@/components/SelectOrganizational/index';
import { MemberType } from '/@/enums/workflowEnum';
import { MemberConfig } from '/@/model/workflow/memberSetting';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits(['change']);
const props = withDefaults(
defineProps<{
memberList: Array<MemberConfig>;
}>(),
{
memberList: () => {
return [];
},
},
);
let selectedIds = computed(() => {
if (props.memberList && props.memberList.length > 0) {
return props.memberList
.filter((ele: MemberConfig) => {
return ele.memberType === MemberType.ROLE;
})
.map((ele: MemberConfig) => {
return ele.id;
});
} else {
return [];
}
});
async function submit(ids: Array<string>) {
let list: Array<MemberConfig> = [];
if (props.memberList && props.memberList.length > 0) {
props.memberList.forEach((ele) => {
if (ele.memberType != MemberType.ROLE)
list.push({
name: ele.name,
id: ele.id,
memberType: ele.memberType,
});
});
}
try {
let roleRes = await getRoleMulti(ids.join(','));
if (roleRes.length > 0) {
roleRes.forEach((ele) => {
list.push({
name: ele.name,
id: ele.id,
memberType: MemberType.ROLE,
});
});
}
} catch (error) {
ids.forEach((id) => {
if (id)
list.push({
name: id,
id: id,
memberType: MemberType.ROLE,
});
});
}
emits('change', list);
}
</script>

View File

@ -0,0 +1,190 @@
<template>
<div>
<div @click="show"><slot></slot></div>
<ModalPanel
:visible="visible"
:width="400"
:title="t('上级领导配置')"
@submit="submit"
@close="close"
>
<div class="title">
<NodeHead :node-name="t('上级领导列表')" />
</div>
<div class="list-box">
<a-tree
checkable
:tree-data="data.treeData"
autoExpandParent
defaultExpandAll
v-model:checkedKeys="data.checkedKeys"
>
<template #title="{ title, key }">
<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
<template v-else>{{ title }}</template>
</template>
</a-tree>
</div>
</ModalPanel>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { useBpmnStore } from '/@bpmn/store/bpmn';
import { BpmnNodeKey, LevelEnum, MemberType } from '/@/enums/workflowEnum';
import { MemberConfig } from '/@/model/workflow/memberSetting';
import { ModalPanel } from '/@/components/ModalPanel/index';
import { NodeHead } from '/@/components/ModalPanel/index';
import { TreeProps } from 'ant-design-vue';
import { separator } from '../../config/info';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits(['change']);
const props = withDefaults(
defineProps<{
memberList: Array<MemberConfig>;
}>(),
{
memberList: () => {
return [];
},
},
);
const visible = ref(false);
const memberType = MemberType.SUPERIOR_LEADERS;
let data: {
treeData: TreeProps['treeData'];
checkedKeys: string[];
expandedNames: Object;
selected: Array<MemberConfig>;
} = reactive({ treeData: [], checkedKeys: [], expandedNames: {}, selected: [] });
function show() {
data.checkedKeys = [];
data.treeData = [];
if (props.memberList.length > 0) {
data.selected = props.memberList.filter((ele: MemberConfig) => {
if (ele.memberType === memberType) return ele;
});
if (data.selected.length > 0) {
data.selected.forEach((ele) => {
if (ele.leaderConfig?.level)
data.checkedKeys.push(ele.leaderConfig.nodeId + separator + ele.leaderConfig.level);
});
}
}
const store = useBpmnStore();
const { info } = store;
for (let item of info.values()) {
let showNodeTypes = [BpmnNodeKey.START, BpmnNodeKey.USER];
if (showNodeTypes.includes(item.type)) {
let name = item.name ? item.name : item.type;
data.treeData.push({
title: name,
key: item.id,
children: getLeaveChildren(item.id),
});
data.expandedNames[item.id] = name;
}
}
visible.value = true;
}
function submit() {
let list: Array<MemberConfig> = [];
if (props.memberList.length > 0) {
list = props.memberList.filter((ele: MemberConfig) => {
if (ele.memberType != memberType) return ele;
});
}
for (const leader of data.checkedKeys) {
let arr = leader.split(separator);
if (arr.length == 2) {
let nodeId = arr[0];
let level = Number(arr[1]);
list.push({
memberType: memberType,
id: nodeId,
name: data.expandedNames[nodeId] + '-' + getLeaveName(level),
leaderConfig: { nodeId, level },
});
}
}
emits('change', [...list]);
close();
}
function close() {
visible.value = false;
}
function getLeaveName(level: LevelEnum) {
switch (level) {
case LevelEnum.ONE:
return '上一级领导';
case LevelEnum.SECOND:
return '上二级领导';
case LevelEnum.THREE:
return '上三级领导';
case LevelEnum.FOUR:
return '上四级领导';
case LevelEnum.FIVE:
return '上五级领导';
default:
break;
}
}
function getLeaveChildren(id: string) {
return [
{
title: getLeaveName(LevelEnum.ONE),
key: id + separator + LevelEnum.ONE,
},
{
title: getLeaveName(LevelEnum.SECOND),
key: id + separator + LevelEnum.SECOND,
},
{
title: getLeaveName(LevelEnum.THREE),
key: id + separator + LevelEnum.THREE,
},
{
title: getLeaveName(LevelEnum.FOUR),
key: id + separator + LevelEnum.FOUR,
},
{
title: getLeaveName(LevelEnum.FIVE),
key: id + separator + LevelEnum.FIVE,
},
];
}
</script>
<style scoped>
.title {
display: flex;
justify-content: space-between;
height: 40px;
font-size: 16px;
color: #333333;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 10px;
}
.list-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
overflow: auto;
}
:deep(.ant-tree-treenode) {
margin-left: 8px;
margin-bottom: 10px;
}
:deep(.ant-tree-list) {
height: 460px;
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<div>
<SelectUser :selectedIds="selectedIds" :multiple="true" @change="submit">
<a-button type="primary">{{ t('添加人员') }}</a-button>
</SelectUser>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getUserMulti } from '/@/api/system/user';
import { SelectUser } from '/@/components/SelectOrganizational/index';
import { MemberType } from '/@/enums/workflowEnum';
import { MemberConfig } from '/@/model/workflow/memberSetting';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const emits = defineEmits(['change']);
const props = withDefaults(
defineProps<{
memberList: Array<MemberConfig>;
}>(),
{
memberList: () => {
return [];
},
},
);
let selectedIds = computed(() => {
if (props.memberList && props.memberList.length > 0) {
return props.memberList
.filter((ele: MemberConfig) => {
return ele.memberType === MemberType.USER;
})
.map((ele: MemberConfig) => {
return ele.id;
});
} else {
return [];
}
});
async function submit(ids: Array<string>) {
let list: Array<MemberConfig> = [];
if (props.memberList && props.memberList.length > 0) {
props.memberList.forEach((ele) => {
if (ele.memberType != MemberType.USER)
list.push({
name: ele.name,
id: ele.id,
memberType: ele.memberType,
});
});
}
let users = await getUserMulti(ids.join(','));
if (users.length > 0) {
users.forEach((ele) => {
list.push({
name: ele.name,
id: ele.id,
memberType: MemberType.USER,
});
});
}
emits('change', list);
}
</script>