初始化版本,引入智慧食堂模块,第三方模块
This commit is contained in:
commit
d22f88efd3
677 files changed
+69341
No files matched your search
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-view">
|
||||
<div class="titlebar">
|
||||
<div class="f1"></div>
|
||||
<div class="f2">
|
||||
<span class="center_t" effect="dark" :activeStep="activeStep == 0" @click="activeStep = 0">
|
||||
<span :activeStep="activeStep == 0">1</span>
|
||||
<span>{{ $t('flow.basicInformation') }}</span>
|
||||
</span>
|
||||
<span class="center_t" effect="dark" :activeStep="activeStep == 1" @click="activeStep = 1">
|
||||
<span :activeStep="activeStep == 1">2</span>
|
||||
<span>{{ $t('flow.formDesign') }}</span>
|
||||
</span>
|
||||
<span class="center_t" effect="dark" :activeStep="activeStep == 2" @click="activeStep = 2">
|
||||
<span :activeStep="activeStep == 2">3</span>
|
||||
<span>{{ $t('flow.processDesign') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="f3">
|
||||
<el-button type="primary" @click="publish">{{ $t('flow.publish') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-scrollbar height="calc(100vh - 250px)">
|
||||
<step1 v-show="activeStep === 0" :groupId="paramGroupId" ref="step1Ref" />
|
||||
<step2 v-show="activeStep === 1" ref="step2Ref" />
|
||||
<step3 v-show="activeStep === 2" :nodeConfigObj="step3NodeConfig" ref="step3Ref" />
|
||||
</el-scrollbar>
|
||||
<!-- //验证每一步-->
|
||||
<el-dialog v-model="validateDialogShow" :title="$t('flow.processCheck')">
|
||||
<el-steps :active="validateFlowStep" finish-status="success" simple style="margin-top: 20px">
|
||||
<el-step :title="$t('flow.basicInformation')" />
|
||||
<el-step :title="$t('flow.formDesign')" />
|
||||
<el-step :title="$t('flow.processDesign')" />
|
||||
</el-steps>
|
||||
|
||||
<div style="text-align: center">
|
||||
<el-result v-if="validateFlowStep == 3" icon="success" :title="$t('flow.checkSuccess')" :sub-title="$t('flow.checkSubSuccess')">
|
||||
<template #extra>
|
||||
<el-button type="primary" @click="submitFlow">{{ $t('flow.submit') }}</el-button>
|
||||
</template>
|
||||
</el-result>
|
||||
|
||||
<el-result
|
||||
:title="$t('flow.checkIng')"
|
||||
:sub-title="$t('flow.checkSubIng')"
|
||||
v-if="validateErrMsg.length == 0 && validateDialogShow && validatingShow && validateFlowStep < 3"
|
||||
>
|
||||
<template #icon>
|
||||
<span v-loading="true" style="display: inline-block; border: 0px solid red; width: 100px; height: 100px"> </span>
|
||||
</template>
|
||||
</el-result>
|
||||
|
||||
<el-result v-if="validateErrMsg.length > 0" icon="error" title="检查失败">
|
||||
<template #sub-title>
|
||||
<div v-for="item in validateErrMsg" :key="item">
|
||||
<el-text type="danger">
|
||||
<el-icon>
|
||||
<WarnTriangleFilled />
|
||||
</el-icon>
|
||||
{{ item }}
|
||||
</el-text>
|
||||
</div>
|
||||
</template>
|
||||
<template #extra>
|
||||
<el-button type="primary" @click="gotoEdit">{{ $t('common.editBtn') }}</el-button>
|
||||
</template>
|
||||
</el-result>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { WarnTriangleFilled } from '@element-plus/icons-vue';
|
||||
import { addFlow } from '/@/api/flow/flow';
|
||||
import Step1 from './step1.vue';
|
||||
import Step2 from './step2.vue';
|
||||
import Step3 from './step3.vue';
|
||||
import { useFlowStore } from '../workflow/stores/flow';
|
||||
import { LocationQuery, LocationQueryValue, useRouter } from 'vue-router';
|
||||
|
||||
let store = useFlowStore();
|
||||
const step1Ref = ref();
|
||||
const step2Ref = ref();
|
||||
const step3Ref = ref();
|
||||
|
||||
const validateErrMsg = ref([]);
|
||||
|
||||
const activeStep = ref(0);
|
||||
const validateFlowStep = ref(0);
|
||||
const validateDialogShow = ref(false);
|
||||
const validatingShow = ref(false);
|
||||
|
||||
const gotoEdit = () => {
|
||||
activeStep.value = validateFlowStep.value;
|
||||
validateDialogShow.value = false;
|
||||
};
|
||||
const publish = (t) => {
|
||||
validateErrMsg.value = [];
|
||||
|
||||
validateFlowStep.value = 0;
|
||||
validateDialogShow.value = true;
|
||||
validatingShow.value = true;
|
||||
|
||||
setTimeout(function () {
|
||||
//1
|
||||
checkStep1();
|
||||
}, 500);
|
||||
};
|
||||
import { useRoute } from 'vue-router';
|
||||
import { getFlowDetail } from '/@/api/flow/flow';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import other from '/@/utils/other';
|
||||
|
||||
const route = useRoute();
|
||||
onMounted(() => {
|
||||
const query: LocationQuery = route.query;
|
||||
|
||||
const groupId = (query.groupId as LocationQueryValue) ?? '';
|
||||
const flowId = (query.flowId as LocationQueryValue) ?? '';
|
||||
const cp = (query.cp as LocationQueryValue) ?? '';
|
||||
|
||||
if (groupId) {
|
||||
paramGroupId.value = groupId;
|
||||
}
|
||||
if (flowId) {
|
||||
getFlowDetail(flowId).then((res) => {
|
||||
var { data } = res;
|
||||
|
||||
store.step1.adminList = JSON.parse(data.adminList);
|
||||
store.step1.name = data.name;
|
||||
store.step1.logo = data.logo;
|
||||
if (!cp || !(parseInt(cp) === 1)) {
|
||||
//复制
|
||||
store.step1.flowId = flowId;
|
||||
}
|
||||
store.step1.remark = data.remark;
|
||||
store.step1.groupId = data.groupId;
|
||||
|
||||
store.setStep2(JSON.parse(data.formItems));
|
||||
step3NodeConfig = JSON.parse(data.process);
|
||||
});
|
||||
} else {
|
||||
//新增
|
||||
let userId = useUserInfo().userInfos.user.userId;
|
||||
let name = useUserInfo().userInfos.user.username;
|
||||
let avatar = useUserInfo().userInfos.user.avatar;
|
||||
//清空 store 属性
|
||||
store.clearStep1();
|
||||
store.clearStep2();
|
||||
store.step1.adminList = [
|
||||
{
|
||||
id: userId,
|
||||
name: name,
|
||||
avatar: avatar,
|
||||
type: 'user',
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
let step3NodeConfig = reactive({});
|
||||
|
||||
var paramGroupId = ref();
|
||||
|
||||
const checkStep1 = () => {
|
||||
step1Ref.value.validate(function (valid, arr) {
|
||||
if (valid) {
|
||||
validateFlowStep.value = 1;
|
||||
|
||||
setTimeout(function () {
|
||||
checkStep2();
|
||||
}, 500);
|
||||
} else {
|
||||
validatingShow.value = false;
|
||||
//错误信息
|
||||
validateErrMsg.value = arr;
|
||||
}
|
||||
});
|
||||
};
|
||||
const checkStep2 = () => {
|
||||
step2Ref.value.validate(function (valid, arr) {
|
||||
if (valid) {
|
||||
setTimeout(function () {
|
||||
validateFlowStep.value = 2;
|
||||
checkStep3();
|
||||
});
|
||||
} else {
|
||||
validatingShow.value = false;
|
||||
//错误信息
|
||||
validateErrMsg.value = arr;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const checkStep3 = () => {
|
||||
setTimeout(function () {
|
||||
step3Ref.value.validate(function (valid, arr) {
|
||||
if (valid) {
|
||||
validateFlowStep.value = 3;
|
||||
} else {
|
||||
validatingShow.value = false;
|
||||
//错误信息
|
||||
validateErrMsg.value = arr;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
const router = useRouter();
|
||||
|
||||
const submitFlow = () => {
|
||||
step3Ref.value.getProcessData().then((res) => {
|
||||
let step1 = store.step1;
|
||||
let step2 = store.step2;
|
||||
|
||||
let flow = other.deepClone(step1);
|
||||
flow.formItems = JSON.stringify(step2);
|
||||
flow.process = JSON.stringify(res);
|
||||
flow.adminList = JSON.stringify(step1.adminList);
|
||||
|
||||
addFlow(flow).then((res) => {
|
||||
validateDialogShow.value = false;
|
||||
store.$reset();
|
||||
router.push('/flow/list/index');
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.f2-width {
|
||||
--f2-width: 600px;
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
height: 60px;
|
||||
flex-direction: row;
|
||||
margin-bottom: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.f1 {
|
||||
width: calc(100% / 2 - var(--f2-width) / 2);
|
||||
}
|
||||
|
||||
.f2 {
|
||||
width: var(--f2-width);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.f3 {
|
||||
width: calc(100% / 2 - var(--f2-width) / 2);
|
||||
text-align: right;
|
||||
line-height: 46px;
|
||||
height: 46px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.center_t {
|
||||
cursor: pointer;
|
||||
padding: 10px 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.center_t span:first-child {
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
line-height: 22px;
|
||||
border: 1px solid;
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.center_t span:first-child[activeStep='true'] {
|
||||
color: white;
|
||||
background-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.center_t span:last-child {
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.center_t[activeStep='true'] {
|
||||
border-bottom: 2px solid var(--el-color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="container-div">
|
||||
<el-card class="box-card" style="padding-right: 10%; padding-left: 10%">
|
||||
<el-form ref="ruleForm" :model="form" :rules="rules" label-position="top" status-icon label-width="120px" @submit.prevent>
|
||||
<el-form-item :label="$t('flow.logo')" prop="logo">
|
||||
<upload-img v-model:imageUrl="form.logo" height="100px" width="100px">
|
||||
<template #empty>
|
||||
<el-icon>
|
||||
<Avatar />
|
||||
</el-icon>
|
||||
<span>{{ $t('flow.logo') }}</span>
|
||||
</template>
|
||||
</upload-img>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('flow.name')" prop="name">
|
||||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('flow.remark')" prop="remark">
|
||||
<el-input v-model="form.remark" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('flow.group')" prop="groupId">
|
||||
<el-select v-model="form.groupId" :placeholder="$t('flow.groupTips')">
|
||||
<el-option v-for="item in groupList" :key="item.id" :label="item.groupName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('flow.admin')" prop="adminList">
|
||||
<select-show v-model:orgList="form.adminList" type="user" :multiple="false"></select-show>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type {FormRules} from 'element-plus';
|
||||
import selectShow from '/@/components/OrgSelector/index.vue';
|
||||
import {queryGroupList} from '/@/api/flow/group';
|
||||
import {useRoute} from 'vue-router';
|
||||
import {useFlowStore} from '../workflow/stores/flow';
|
||||
import {GroupVO} from '/@/api/flow/group/types';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const validate = (f) => {
|
||||
proxy.$refs.ruleForm.validate((valid, fields) => {
|
||||
var arr = [];
|
||||
if (!valid) {
|
||||
for (var err in fields) {
|
||||
arr.push(fields[err][0].message);
|
||||
}
|
||||
}
|
||||
|
||||
f(valid, arr);
|
||||
});
|
||||
};
|
||||
|
||||
// 暴露方法和属性给父组件
|
||||
defineExpose({ validate });
|
||||
const rules = reactive<FormRules>({
|
||||
name: [
|
||||
{ required: true, message: '请填写名称', trigger: 'blur' },
|
||||
{ min: 2, max: 10, message: '2-10个字符', trigger: 'blur' },
|
||||
],
|
||||
remark: [
|
||||
{ required: false, message: '请填写描述', trigger: 'blur' },
|
||||
{ min: 2, max: 20, message: '2-20个字符', trigger: 'blur' },
|
||||
],
|
||||
groupId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择分组',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
logo: [
|
||||
{
|
||||
required: true,
|
||||
message: '请上传图标',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
adminList: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择管理员',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let props = defineProps({
|
||||
groupId: {
|
||||
type: Number,
|
||||
default: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const groupList = ref<GroupVO[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
queryGroupList().then(({ data }) => {
|
||||
groupList.value = data;
|
||||
});
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.groupId,
|
||||
(val) => {
|
||||
if (!!val) {
|
||||
form.value.groupId = parseInt(val);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const flowStore = useFlowStore();
|
||||
|
||||
const form = computed(() => {
|
||||
return flowStore.step1;
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.container-div {
|
||||
width: 800px;
|
||||
height: 100vh; /* Set the container height to 100% of the viewport height */
|
||||
margin-left: calc(50% - 400px);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<flow-form-designer ref="flowFormDesignerRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import FlowFormDesigner from '/@/views/flow/form/index.vue';
|
||||
|
||||
const flowFormDesignerRef = ref();
|
||||
|
||||
const validate = (f) => {
|
||||
flowFormDesignerRef.value.validate(f);
|
||||
};
|
||||
|
||||
defineExpose({ validate });
|
||||
</script>
|
||||
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 流程节点绘制 -->
|
||||
<div class="fd-nav-content">
|
||||
<el-scrollbar style="height: 600px">
|
||||
<section class="dingflow-design">
|
||||
<div class="zoom">
|
||||
<div class="zoom-out" :class="nowVal === 50 && 'disabled'" @click="zoomSize(1)"></div>
|
||||
<span>{{ nowVal }}%</span>
|
||||
<div class="zoom-in" :class="nowVal === 300 && 'disabled'" @click="zoomSize(2)"></div>
|
||||
</div>
|
||||
<div class="box-scale" :style="`transform: scale(${nowVal / 100});`">
|
||||
<nodeWrap v-model:nodeConfig="nodeConfig"/>
|
||||
<div class="end-node">
|
||||
<div class="end-node-circle"></div>
|
||||
<div class="end-node-text">{{ $t('flow.end') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<!-- 发起人 -->
|
||||
<promoterDrawer/>
|
||||
<!-- 审批人 -->
|
||||
<approverDrawer/>
|
||||
<!-- 抄送人 -->
|
||||
<copyerDrawer/>
|
||||
<!-- 条件分支 -->
|
||||
<conditionDrawer/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import nodeWrap from '../workflow/components/nodeWrap.vue';
|
||||
import promoterDrawer from '../workflow/components/drawer/promoterDrawer.vue';
|
||||
import approverDrawer from '../workflow/components/drawer/approverDrawer.vue';
|
||||
import copyerDrawer from '../workflow/components/drawer/copyerDrawer.vue';
|
||||
import conditionDrawer from '../workflow/components/drawer/conditionDrawer.vue';
|
||||
import {useI18n} from 'vue-i18n';
|
||||
import {useFlowStore} from "../workflow/stores/flow";
|
||||
|
||||
let store = useFlowStore();
|
||||
|
||||
const {t} = useI18n();
|
||||
|
||||
let tipList = ref([]);
|
||||
let nowVal = ref(100);
|
||||
let nodeConfig = ref({
|
||||
nodeName: t('flow.initiator'),
|
||||
type: 0,
|
||||
id: 'root',
|
||||
formPerms: {},
|
||||
eventConfig: '',
|
||||
nodeUserList: [],
|
||||
childNode: {},
|
||||
});
|
||||
|
||||
let props = defineProps({
|
||||
nodeConfigObj: {
|
||||
type: Object,
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.nodeConfigObj,
|
||||
(val) => {
|
||||
nodeConfig.value = val;
|
||||
}
|
||||
);
|
||||
|
||||
const reErr = ({childNode}) => {
|
||||
if (childNode) {
|
||||
let {type, error, nodeName, conditionNodes} = childNode;
|
||||
if (type == 1 || type == 2) {
|
||||
if (error) {
|
||||
tipList.value.push(nodeName + ' 未设置人员');
|
||||
}
|
||||
reErr(childNode);
|
||||
} else if (type == 3) {
|
||||
reErr(childNode);
|
||||
} else if (type == 4) {
|
||||
reErr(childNode);
|
||||
for (var i = 0; i < conditionNodes.length; i++) {
|
||||
if (conditionNodes[i].error) {
|
||||
tipList.value.push('请设置' + conditionNodes[i].nodeName + '的条件');
|
||||
}
|
||||
reErr(conditionNodes[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
childNode = null;
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => nodeConfig.value, (v) => {
|
||||
store.setStep3(v)
|
||||
}, {deep: true})
|
||||
const getProcessData = async () => {
|
||||
return nodeConfig.value;
|
||||
};
|
||||
const zoomSize = (type) => {
|
||||
if (type == 1) {
|
||||
if (nowVal.value == 50) {
|
||||
return;
|
||||
}
|
||||
nowVal.value -= 10;
|
||||
} else {
|
||||
if (nowVal.value == 300) {
|
||||
return;
|
||||
}
|
||||
nowVal.value += 10;
|
||||
}
|
||||
};
|
||||
const validate = (f) => {
|
||||
tipList.value = [];
|
||||
|
||||
if (nodeConfig.value.childNode == undefined || nodeConfig.value.childNode.id === undefined) {
|
||||
tipList.value = ['请完善流程节点'];
|
||||
}
|
||||
|
||||
reErr(nodeConfig.value);
|
||||
if (tipList.value.length != 0) {
|
||||
f(false, tipList.value);
|
||||
return;
|
||||
}
|
||||
f(true);
|
||||
};
|
||||
defineExpose({validate, getProcessData});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@import '../workflow/css/workflow.css';
|
||||
|
||||
.error-modal-list {
|
||||
width: 455px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user