fix: 合并冲突
This commit is contained in:
8
src/api/home/index.js
Normal file
8
src/api/home/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
export const getHomeInfo = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/process/task',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
68
src/api/project-demand/index.js
Normal file
68
src/api/project-demand/index.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import request from '@/utils/request.js'
|
||||
//需求征集
|
||||
export const getDemandInfo = (param) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement',
|
||||
method: "get",
|
||||
params: param
|
||||
});
|
||||
};
|
||||
export const getWorkflowInfo = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement/process',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const getInfo = (requirementId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/requirement/info/${requirementId}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const getFormInfo = (requirementId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/requirement/form/${requirementId}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const agreeTask = (data) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/process/task/agree`,
|
||||
method: "post",
|
||||
data: data
|
||||
});
|
||||
};
|
||||
export const rejectTask = (data) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/process/task/reject`,
|
||||
method: "post",
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
export const addRequirement = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement',
|
||||
method: "post",
|
||||
data: data
|
||||
});
|
||||
};
|
||||
export const resubmit = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement/resubmit',
|
||||
method: "post",
|
||||
data: data
|
||||
});
|
||||
};
|
||||
export const deleteFile = (fileId) => {
|
||||
return request({
|
||||
url: `/workflow/process/file/delete/${fileId}`,
|
||||
method: "delete"
|
||||
});
|
||||
};
|
||||
export const getCompanyOption = () => {
|
||||
return request({
|
||||
url: '/admin/mosr/sub/company/companyOption',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
@@ -19,7 +19,7 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
}
|
||||
|
||||
.el-main {
|
||||
background: #F4F6F8;
|
||||
background: #EFEFEF;
|
||||
padding: 0 0 0 18px;
|
||||
position: fixed;
|
||||
left: 200px;
|
||||
@@ -27,6 +27,7 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
margin-left: 0;
|
||||
transition: margin-left .15s;
|
||||
width: calc(100vw - 200px);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
@@ -83,9 +84,11 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.el-dialog__body{
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.stateIcon {
|
||||
margin-top: 9px;
|
||||
margin-right: 7px;
|
||||
@@ -248,7 +251,8 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
justify-content: center;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
.el-icon{
|
||||
|
||||
.el-icon {
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
}
|
||||
@@ -287,9 +291,10 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
.layout {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.scrollbar-user {
|
||||
height: calc(100vh - 250px)!important;
|
||||
overflow: auto!important;
|
||||
height: calc(100vh - 250px) !important;
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
.scrollbar-dict {
|
||||
@@ -374,6 +379,7 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
margin-top: 10px;
|
||||
z-index: 666;
|
||||
position: absolute;
|
||||
//top: -20px;
|
||||
}
|
||||
|
||||
.el-overlay-dialog {
|
||||
@@ -401,6 +407,15 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
}
|
||||
|
||||
//SvgIcon组件的样式
|
||||
.home-icon {
|
||||
width: 4em;
|
||||
height: 4em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
@@ -445,10 +460,12 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
overflow: hidden;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.fen-icon{
|
||||
|
||||
.fen-icon {
|
||||
width: 1.8em;
|
||||
height: 1.7em;
|
||||
}
|
||||
|
||||
.middle-icon {
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
|
||||
6
src/assets/svg/home1.svg
Normal file
6
src/assets/svg/home1.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 229">
|
||||
<ellipse id="Ellipse 12" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#87C3ED"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M23.3174 21.8325C23.3174 20.7279 24.2128 19.8325 25.3174 19.8325H28.485V23.3688C28.485 23.9211 28.9327 24.3688 29.485 24.3688H32.7358C33.288 24.3688 33.7358 23.9211 33.7358 23.3688V19.8325H45.4049C46.5094 19.8325 47.4049 20.7279 47.4049 21.8325V44.741C47.4049 45.8456 46.5094 46.741 45.4049 46.741H25.3174C24.2128 46.741 23.3174 45.8456 23.3174 44.741V21.8325ZM32.7358 19.8325H29.485V23.3688L32.7358 23.3688V19.8325ZM28.876 29.1297H39.9933V28.1297H28.876V29.1297ZM41.8462 34.4079H28.876V33.4079H41.8462V34.4079ZM41.8462 39.6862H28.876V38.6862H41.8462V39.6862Z" fill="#0043C5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 860 B |
6
src/assets/svg/home2.svg
Normal file
6
src/assets/svg/home2.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 230">
|
||||
<ellipse id="Ellipse 13" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#B487ED"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M41.1045 20.8325C41.1045 20.2802 40.6568 19.8325 40.1045 19.8325H26.1016C24.997 19.8325 24.1016 20.7279 24.1016 21.8325V44.741C24.1016 45.8456 24.997 46.741 26.1016 46.741H46.189C47.2936 46.741 48.189 45.8456 48.189 44.741V27.5596C48.189 27.0073 47.7413 26.5596 47.189 26.5596H42.1045C41.5522 26.5596 41.1045 26.1118 41.1045 25.5596V20.8325ZM43.9383 31.0958H31.1861V30.0958H43.9383V31.0958ZM35.4369 23.0234H39.6876V22.0234H35.4369V23.0234ZM43.9383 36.4777H31.1861V35.4777H43.9383V36.4777ZM31.1861 41.8593H43.9383V40.8593H31.1861V41.8593Z" fill="#8600C5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 838 B |
6
src/assets/svg/home3.svg
Normal file
6
src/assets/svg/home3.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 231">
|
||||
<ellipse id="Ellipse 14" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#FDCB9D"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M54.4044 32.614C54.4044 40.4161 46.1575 46.741 35.9845 46.741C32.9189 46.741 30.0281 46.1666 27.4852 45.1505C27.3501 45.3211 27.1528 45.4524 26.9047 45.5078L19.6131 47.1386C18.844 47.3106 18.1654 46.6256 18.393 45.9072L20.2692 39.9868C18.5537 37.8406 17.5647 35.3159 17.5647 32.614C17.5647 24.8119 25.8115 18.4871 35.9845 18.4871C46.1575 18.4871 54.4044 24.8119 54.4044 32.614ZM28.1916 34.6321C29.3654 34.6321 30.317 33.7286 30.317 32.614C30.317 31.4994 29.3654 30.5958 28.1916 30.5958C27.0178 30.5958 26.0662 31.4994 26.0662 32.614C26.0662 33.7286 27.0178 34.6321 28.1916 34.6321ZM38.8184 32.614C38.8184 33.7286 37.8669 34.6321 36.6931 34.6321C35.5193 34.6321 34.5677 33.7286 34.5677 32.614C34.5677 31.4994 35.5193 30.5958 36.6931 30.5958C37.8669 30.5958 38.8184 31.4994 38.8184 32.614ZM45.1945 34.6321C46.3683 34.6321 47.3198 33.7286 47.3198 32.614C47.3198 31.4994 46.3683 30.5958 45.1945 30.5958C44.0207 30.5958 43.0691 31.4994 43.0691 32.614C43.0691 33.7286 44.0207 34.6321 45.1945 34.6321Z" fill="#F47D0E"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
6
src/assets/svg/home4.svg
Normal file
6
src/assets/svg/home4.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 232">
|
||||
<ellipse id="Ellipse 19" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#87EDBC"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M18.7023 20.134C18.1358 20.4872 17.7588 21.1158 17.7588 21.8325V42.0502C17.7588 43.1547 18.6542 44.0502 19.7588 44.0502H48.3477C49.4523 44.0502 50.3477 43.1547 50.3477 42.0502V21.8325C50.3477 21.1082 49.9627 20.4738 49.3861 20.1229L49.9153 20.9221L35.7553 30.2976C34.9339 30.8415 33.8697 30.8523 33.0374 30.3252L18.1997 20.9276L18.7023 20.134ZM18.7605 20.0991L33.5725 29.4804C34.0718 29.7966 34.7104 29.7902 35.2032 29.4638L49.3465 20.0993C49.0526 19.9296 48.7115 19.8325 48.3477 19.8325H19.7588C19.3952 19.8325 19.0543 19.9295 18.7605 20.0991Z" fill="#01A054"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 845 B |
88
src/components/FileUpload.vue
Normal file
88
src/components/FileUpload.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-upload :file-list="_value"
|
||||
:action="uploadFileUrl"
|
||||
:headers="headers"
|
||||
:limit="maxSize"
|
||||
with-credentials
|
||||
:multiple="maxSize > 0"
|
||||
:data="uploadParams"
|
||||
:show-file-list="false"
|
||||
:auto-upload="true"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
>
|
||||
<el-button color="#DED0B2" :loading="loading">上传文件</el-button>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ElMessage} from "element-plus";
|
||||
import {getToken} from '@/utils/auth'
|
||||
const baseURL = import.meta.env.VITE_BASE_URL
|
||||
const uploadFileUrl = ref(baseURL + "/workflow/process/file/upload")
|
||||
const headers = reactive({
|
||||
authorization: getToken()
|
||||
})
|
||||
const disabled = ref(false)
|
||||
const loading = ref(false)
|
||||
const showTable = ref(false)
|
||||
const uploadParams = ref({})
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 30
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(["input", "getFile"])
|
||||
const fileList = ref([])
|
||||
const _value = computed({
|
||||
get() {
|
||||
return props.value;
|
||||
},
|
||||
set(val) {
|
||||
emit("input", val);
|
||||
}
|
||||
})
|
||||
|
||||
const beforeUpload = (file) => {
|
||||
// const FileExt = file.name.replace(/.+\./, "");
|
||||
// if (['zip', 'rar', 'pdf', 'doc', 'docx', 'xlsx'].indexOf(FileExt.toLowerCase()) === -1) {
|
||||
// ElMessage.warning('请上传后缀名为pdf、doc、docx、xlsx、zip或rar的文件!');
|
||||
// return false;
|
||||
// } else
|
||||
// if (props.maxSize > 0 && file.size / 1024 / 1024 > props.maxSize) {
|
||||
// ElMessage.warning(`每个文件最大不超过 ${props.maxSize}MB`)
|
||||
// } else {
|
||||
loading.value = true
|
||||
return true
|
||||
// }
|
||||
}
|
||||
const handleUploadSuccess = (res, file) => {
|
||||
if (res.code !== 1000) {
|
||||
loading.value = false
|
||||
ElMessage.error("上传失败")
|
||||
} else {
|
||||
loading.value = false
|
||||
ElMessage.success("上传成功")
|
||||
}
|
||||
showTable.value = true
|
||||
let data = res.data
|
||||
fileList.value.push(data)
|
||||
emit("getFile", fileList.value)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
font-size: 14px;
|
||||
color: #2a99ff;
|
||||
}
|
||||
</style>
|
||||
@@ -60,13 +60,21 @@ const props = defineProps({
|
||||
toolbar: {
|
||||
type: [String, Array],
|
||||
default: [
|
||||
"fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat ",
|
||||
"fullscreen undo redo | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat ",
|
||||
"styleselect formatselect fontselect fontsizeselect | table image axupimgs media pagebreak insertdatetime selectall visualblocks searchreplace | code preview | indent2em lineheight formatpainter",
|
||||
],
|
||||
},
|
||||
fontFormats: {
|
||||
type: [String, Array],
|
||||
default: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;"
|
||||
},
|
||||
width:{
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
height:{
|
||||
type: Number,
|
||||
default: 450
|
||||
}
|
||||
})
|
||||
const content = ref(props.value);
|
||||
@@ -78,9 +86,10 @@ const init = reactive({
|
||||
content_css: '/skins/content/default/content.css',
|
||||
language: 'zh_CN',
|
||||
placeholder: "在这里输入文字", //textarea中的提示信息
|
||||
min_width: 320,
|
||||
min_height: 220,
|
||||
height: 500, //注:引入autoresize插件时,此属性失效
|
||||
min_width: 300,
|
||||
min_height: 200,
|
||||
width:props.width,
|
||||
height: props.height, //注:引入autoresize插件时,此属性失效
|
||||
resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
|
||||
promotion: false,
|
||||
branding: false, //tiny技术支持信息是否显示
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<template>
|
||||
<el-form
|
||||
:model="form"
|
||||
v-bind="$attrs"
|
||||
label-width="auto"
|
||||
ref="formInstance"
|
||||
class="search-form"
|
||||
:model="form"
|
||||
v-bind="$attrs"
|
||||
label-width="auto"
|
||||
ref="formInstance"
|
||||
class="search-form"
|
||||
>
|
||||
<el-row>
|
||||
<el-col
|
||||
v-for="(item, index) in filterConfig"
|
||||
:span="5"
|
||||
:offset="index == 0 || index / 4 ==1 ? 0 : 1"
|
||||
:key="item.prop"
|
||||
>
|
||||
<el-form-item
|
||||
v-bind="item"
|
||||
v-for="(item, index) in filterConfig"
|
||||
:span="5"
|
||||
:offset="index == 0 || index / 4 ==1 ? 0 : 1"
|
||||
:key="item.prop"
|
||||
>
|
||||
<el-form-item
|
||||
v-bind="item"
|
||||
:key="item.prop"
|
||||
>
|
||||
<template #default>
|
||||
<component
|
||||
:is="item.component"
|
||||
v-bind="item.props || {}"
|
||||
v-on="item.on || {}"
|
||||
v-model="form[item.prop]"
|
||||
<component
|
||||
:is="item.component"
|
||||
v-bind="item.props || {}"
|
||||
v-on="item.on || {}"
|
||||
v-model="form[item.prop]"
|
||||
>
|
||||
</component>
|
||||
</template>
|
||||
@@ -33,7 +33,7 @@
|
||||
<el-button v-if="searchConfig.length>=4" link type="primary" @click="showMore = !showMore">
|
||||
{{ showMore ? '收起' : '展开' }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="getValues" :icon="Search">搜索</el-button>
|
||||
<el-button @click="getValues" color="#DED0B2" :icon="Search">搜索</el-button>
|
||||
<el-button @click="handleReset" :icon="Refresh">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -58,22 +58,22 @@ const formInstance = ref(null)
|
||||
|
||||
const showMore = ref(false)
|
||||
|
||||
const filterConfig = computed(()=>{
|
||||
const arr = props.searchConfig.filter(item=>{
|
||||
if(item.prop) return true
|
||||
const filterConfig = computed(() => {
|
||||
const arr = props.searchConfig.filter(item => {
|
||||
if (item.prop) return true
|
||||
})
|
||||
return arr.length >= 4 && showMore.value ? arr : arr.slice(0, 3)
|
||||
})
|
||||
|
||||
// 搜索功能表单元素默认值
|
||||
const setDefaultFormValues = () => {
|
||||
filterConfig.value.forEach(item=>{
|
||||
form.value[item.prop] = item.props.defaultValue || null
|
||||
filterConfig.value.forEach(item => {
|
||||
form.value[item.prop] = item.props?.defaultValue || null
|
||||
})
|
||||
}
|
||||
|
||||
watchEffect(()=>{
|
||||
if(filterConfig.value.length) {
|
||||
watchEffect(() => {
|
||||
if (filterConfig.value.length) {
|
||||
setDefaultFormValues()
|
||||
}
|
||||
})
|
||||
@@ -90,8 +90,8 @@ const handleReset = () => {
|
||||
emits('search', form.value)
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
emits('getInstance', Object.assign({}, unref(formInstance),{
|
||||
onMounted(() => {
|
||||
emits('getInstance', Object.assign({}, unref(formInstance), {
|
||||
getValues,
|
||||
handleReset,
|
||||
}))
|
||||
@@ -103,9 +103,10 @@ onMounted(()=>{
|
||||
.search-form {
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
.btn-col {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</template>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<fvPagination
|
||||
<fvPagination
|
||||
v-if="pagination"
|
||||
:current-page="localData.query.pageNum"
|
||||
:page-size="localData.query.pageSize"
|
||||
@@ -269,7 +269,7 @@ defineExpose({ refresh, updateLoading, getQuery, tableInstance })
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -290,4 +290,4 @@ onMounted(() => {
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-popover
|
||||
:width="300"
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 10px;"
|
||||
>
|
||||
<template #reference>
|
||||
<el-badge :hidden="total===0" :value="total" class="item">
|
||||
<el-icon size="22px" style="cursor: pointer">
|
||||
<Bell/>
|
||||
</el-icon>
|
||||
</el-badge>
|
||||
</template>
|
||||
<template #default>
|
||||
<div v-if="total===0" style="height: 100px;display: flex;align-items: center;justify-content: center">
|
||||
暂无数据~
|
||||
</div>
|
||||
<ul v-else>
|
||||
<li v-for="(notice,index) in noticeList" :key="index">
|
||||
<span @click="handleToNotifyDetail(notice,index)">{{ notice.noticeTitle }}</span>
|
||||
<span v-if="notice.state==='0'" @click="handleRead(notice)">已读</span>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- <el-popover-->
|
||||
<!-- :width="300"-->
|
||||
<!-- trigger="click"-->
|
||||
<!-- placement="bottom"-->
|
||||
<!-- popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 10px;"-->
|
||||
<!-- >-->
|
||||
<!-- <template #reference>-->
|
||||
<!-- <el-badge :hidden="total===0" :value="total" class="item">-->
|
||||
<!-- <el-icon size="22px" style="cursor: pointer">-->
|
||||
<!-- <Bell/>-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- </el-badge>-->
|
||||
<!-- </template>-->
|
||||
<!-- <template #default>-->
|
||||
<!-- <div v-if="total===0" style="height: 100px;display: flex;align-items: center;justify-content: center">-->
|
||||
<!-- 暂无数据~-->
|
||||
<!-- </div>-->
|
||||
<!-- <ul v-else>-->
|
||||
<!-- <li v-for="(notice,index) in noticeList" :key="index">-->
|
||||
<!-- <span @click="handleToNotifyDetail(notice,index)">{{ notice.noticeTitle }}</span>-->
|
||||
<!-- <span v-if="notice.state==='0'" @click="handleRead(notice)">已读</span>-->
|
||||
<!-- </li>-->
|
||||
<!-- </ul>-->
|
||||
|
||||
<div class="notify-btn">
|
||||
<el-button type="primary" @click="handlePrevious" :disabled="pageInfo.pageNum===1" link>上一页</el-button>
|
||||
<span @click="handleMoreRead">本页已读</span>
|
||||
<el-button type="primary" @click="handleNext" :disabled="pageInfo.pageNum*pageInfo.pageSize>total" link>下一页
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
<!-- <div class="notify-btn">-->
|
||||
<!-- <el-button type="primary" @click="handlePrevious" :disabled="pageInfo.pageNum===1" link>上一页</el-button>-->
|
||||
<!-- <span @click="handleMoreRead">本页已读</span>-->
|
||||
<!-- <el-button type="primary" @click="handleNext" :disabled="pageInfo.pageNum*pageInfo.pageSize>total" link>下一页-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-popover>-->
|
||||
<el-dialog width="1200px" title="通知公告详情" v-model="visible" @close="visible=false">
|
||||
<el-form :model="viewForm" label-width="100px">
|
||||
<el-row>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<bell-socket/>
|
||||
<div class="user-box">
|
||||
<div>
|
||||
<img :src="userInfo.avatar" alt="" @click.stop="handleVisitedP">
|
||||
<span>{{userInfo.userName}}</span>
|
||||
<!-- <img :src="userInfo.avatar" alt="" @click.stop="handleVisitedP">-->
|
||||
<span @click.stop="handleVisitedP">欢迎回来,{{userInfo.userName}}</span>
|
||||
</div>
|
||||
<div class="person" v-if="visitedP">
|
||||
<ul>
|
||||
@@ -81,6 +81,7 @@ const handleLogout = () => {
|
||||
align-items: center;
|
||||
|
||||
.user-box{
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
>div:first-child{
|
||||
|
||||
@@ -107,7 +107,17 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
|
||||
}
|
||||
|
||||
const removeMenu = () => {
|
||||
menuList.value.length = 0
|
||||
menuList.value = [
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
icon: 'home',
|
||||
title: '首页',
|
||||
meta: {
|
||||
breadcrumb: true
|
||||
}
|
||||
}
|
||||
]
|
||||
asyncRouters.value.length = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ serveice.interceptors.response.use(response => {
|
||||
if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
|
||||
return response.data
|
||||
}
|
||||
console.log("window.location.pathname", window.location.pathname)
|
||||
console.log("windows", window.location.search)
|
||||
return response.data
|
||||
}, error => {
|
||||
let response = error.response
|
||||
|
||||
@@ -1,266 +1,318 @@
|
||||
<template>
|
||||
<div class="home-container">
|
||||
<div class="home-top">
|
||||
<el-image :src="homeImage" style="width: 380px"/>
|
||||
<div class="top-right">
|
||||
<div>Admin,欢迎回来!</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-top-right">
|
||||
<el-image :src="coffee" style="height: 100px"/>
|
||||
<span>科研管理平台</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <el-row :gutter="10" type="flex">-->
|
||||
<!-- <el-col :span="6" :xs="8" :sm="16" :md="18" :lg="20" :xl="24" >-->
|
||||
<!-- <div v-for="(item,index) in list" :key="index" class="block">-->
|
||||
<!-- <div>{{item.title}}</div>-->
|
||||
<!-- <div>-->
|
||||
<!-- <el-icon><User/></el-icon>-->
|
||||
<!-- <span>{{item.num}}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- </el-row>-->
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="6" v-for="item in 4">1</el-col>
|
||||
<!-- <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"-->
|
||||
<!-- >2<div class="grid-content ep-bg-purple-light"-->
|
||||
<!-- /></el-col>-->
|
||||
<!-- <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"-->
|
||||
<!-- >3<div class="grid-content ep-bg-purple"-->
|
||||
<!-- /></el-col>-->
|
||||
<!-- <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"-->
|
||||
<!-- >4<div class="grid-content ep-bg-purple-light"-->
|
||||
<!-- /></el-col>-->
|
||||
</el-row>
|
||||
<div class="container">
|
||||
<div id="bar1" ref="bar1"></div>
|
||||
<div id="bar2" ref="bar2"></div>
|
||||
<div id="bar3" ref="bar3"></div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div id="pie1" ref="pie1"></div>
|
||||
<div id="pie2" ref="pie2"></div>
|
||||
<div id="pie3" ref="pie3"></div>
|
||||
<div class="home-bg">
|
||||
<el-row gutter="20">
|
||||
<el-col :xs="24" :sm="24" :md="18" :lg="18" :xl="18">
|
||||
<div class="left">
|
||||
<h3>我的科创工作</h3>
|
||||
<el-row :gutter="20" class="statistics">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="(item,index) in list" :key="index">
|
||||
<div class="block" :style="{background: item.color}">
|
||||
<svg-icon :name="item.icon" :class-name="'home-icon'"/>
|
||||
<div class="block-right">
|
||||
<span>{{ item.title }}</span>
|
||||
<span :style="{color: item.textColor}">{{ item.num }}<span>个</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<h4>待办 ({{ todoNum }})</h4>
|
||||
<fvTable ref="tableIns" class="home-table" :tableConfig="tableConfig">
|
||||
<template #empty>
|
||||
<el-empty description="暂无待办"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6">
|
||||
<div class="right">
|
||||
<div class="right-top ">
|
||||
<div>
|
||||
<h3>帮助文档</h3>
|
||||
<span>查看更多</span>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<div v-for="item in helpDocList" class="help">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-top">
|
||||
<div>
|
||||
<h3>工具下载</h3>
|
||||
<span>常用网站</span>
|
||||
</div>
|
||||
<el-divider/>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as echarts from 'echarts'
|
||||
import homeImage from "@/assets/home/home.png"
|
||||
import coffee from "@/assets/home/coffee.png"
|
||||
import {useRouter} from 'vue-router';
|
||||
<script setup lang="jsx">
|
||||
import 'element-plus/theme-chalk/display.css'
|
||||
|
||||
const router = useRouter()
|
||||
const list = ref([
|
||||
{
|
||||
title: '在线用户量',
|
||||
num: 2142
|
||||
title: '待立项',
|
||||
color: '#CEE8FA',
|
||||
textColor: '#0043C5',
|
||||
icon: 'home1',
|
||||
num: 21
|
||||
},
|
||||
{
|
||||
title: '在线用户量',
|
||||
num: 2142
|
||||
title: '待评审',
|
||||
color: '#DCCEFA',
|
||||
textColor: '#8600C5',
|
||||
icon: 'home2',
|
||||
num: 2
|
||||
},
|
||||
{
|
||||
title: '在线用户量',
|
||||
num: 2142
|
||||
title: '待验收',
|
||||
color: '#FAE6CE',
|
||||
textColor: '#F47D0E',
|
||||
icon: 'home3',
|
||||
num: 4
|
||||
},
|
||||
{
|
||||
title: '在线用户量',
|
||||
num: 2142
|
||||
title: '待归档',
|
||||
color: '#CEFAD8',
|
||||
textColor: '#01A089',
|
||||
icon: 'home4',
|
||||
num: 1
|
||||
}
|
||||
])
|
||||
const barOption = {
|
||||
title: {
|
||||
text: 'World Population'
|
||||
const helpDocList = ref([
|
||||
{
|
||||
title: '业务流程'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
{
|
||||
title: '业务流程'
|
||||
},
|
||||
legend: {},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
{
|
||||
title: '业务流程'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01]
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: ['Brazil', 'Indonesia', 'USA', 'India', 'China', 'World']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
title: '业务流程'
|
||||
}
|
||||
])
|
||||
const todoNum = ref(20)
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
name: '2011',
|
||||
type: 'bar',
|
||||
data: [18203, 23489, 29034, 104970, 131744, 630230]
|
||||
prop: 'processName',
|
||||
label: '流程名称',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: '2012',
|
||||
type: 'bar',
|
||||
data: [19325, 23438, 31000, 121594, 134141, 681807]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const pieOption = {
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
left: 'center'
|
||||
},
|
||||
series: [
|
||||
prop: 'initiatorName',
|
||||
label: '发起人',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 40,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{value: 1048, name: 'Search Engine'},
|
||||
{value: 735, name: 'Direct'},
|
||||
{value: 580, name: 'Email'},
|
||||
{value: 484, name: 'Union Ads'},
|
||||
{value: 300, name: 'Video Ads'}
|
||||
]
|
||||
prop: 'targetState',
|
||||
label: '类型',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => (<Tag dictType={'todo_type'} value={row.targetState}/>)
|
||||
},
|
||||
{
|
||||
prop: 'submitTime',
|
||||
label: '提交时间',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'taskName',
|
||||
label: '当前节点',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
fixed: 'right',
|
||||
width: '150',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
return (
|
||||
<div>
|
||||
<el-button type="primary" link onClick={() => handleView(row)}>查看</el-button>
|
||||
<el-button type="primary" link onClick={() => handleEdit(row)}>已读</el-button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const data = reactive({
|
||||
barCharts: null,
|
||||
pieCharts: null,
|
||||
bar1: null,
|
||||
bar2: null,
|
||||
bar3: null,
|
||||
pie1: null,
|
||||
pie2: null,
|
||||
pie3: null,
|
||||
],
|
||||
api: '/workflow/mosr/process/task',
|
||||
params: {},
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
data.barCharts = echarts.init(document.getElementById('bar1')).setOption(barOption)
|
||||
data.barCharts = echarts.init(document.getElementById('bar2')).setOption(barOption)
|
||||
data.barCharts = echarts.init(document.getElementById('bar3')).setOption(barOption)
|
||||
data.pieCharts = echarts.init(document.getElementById('pie1')).setOption(pieOption)
|
||||
data.pieCharts = echarts.init(document.getElementById('pie2')).setOption(pieOption)
|
||||
data.pieCharts = echarts.init(document.getElementById('pie3')).setOption(pieOption)
|
||||
const handleView = (row) => {
|
||||
console.log('row', row)
|
||||
if(row.targetState=='00'&&row.taskId){
|
||||
router.push({
|
||||
path: '/projectdemand/demanddetail',
|
||||
query: {
|
||||
id: row.taskId
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const redirectView = () => {
|
||||
const toView = sessionStorage.getItem('toView')
|
||||
console.log(toView, 'toView');
|
||||
let jsonView = JSON.parse(toView)
|
||||
toView ?
|
||||
router.push({
|
||||
path: jsonView.path,
|
||||
query: {
|
||||
...jsonView.query
|
||||
}
|
||||
}) :
|
||||
null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
redirectView()
|
||||
})
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
data.bar1 = null
|
||||
data.bar2 = null
|
||||
data.bar3 = null
|
||||
data.pie1 = null
|
||||
data.pie2 = null
|
||||
data.pie3 = null
|
||||
data.barCharts = null
|
||||
data.pieCharts = null
|
||||
init()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.home-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@media only screen and (max-width: 767px) {
|
||||
.right {
|
||||
margin-top: 10px;
|
||||
}
|
||||
:deep(.el-table) {
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
.home-top {
|
||||
width: 1000px;
|
||||
height: 150px;
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.right {
|
||||
margin-top: 10px;
|
||||
}
|
||||
:deep(.el-table) {
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.home-bg {
|
||||
height: calc(100vh - 130px);
|
||||
max-height: calc(100vh - 96px);
|
||||
background-color: #EFEFEF;
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
right: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgb(239, 239, 239);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// 小滑块
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(80, 81, 82, 0.29);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.left {
|
||||
//flex: 0.8;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
|
||||
|
||||
.el-table__empty-block {
|
||||
.el-empty {
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.statistics {
|
||||
width: 99%;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #e9edf2;
|
||||
border-radius: 4px;
|
||||
padding: 25px;
|
||||
margin-top: 15px;
|
||||
|
||||
.block-right {
|
||||
margin-left: 15%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: #92969a;
|
||||
font-size: 17px;
|
||||
|
||||
> span:first-child {
|
||||
white-space: nowrap;
|
||||
color: #000000;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
> span:last-child {
|
||||
white-space: nowrap;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
|
||||
> span {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.right {
|
||||
height: calc(100vh - 130px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #e1eaf9;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.top-right {
|
||||
font-size: 16px;
|
||||
margin-left: 10px;
|
||||
letter-spacing: 1.5px;
|
||||
.right-top {
|
||||
flex: 0.5;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.right-top {
|
||||
flex: 0.48;
|
||||
|
||||
> div:first-child {
|
||||
color: #557ad2;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
h3 {
|
||||
white-space: nowrap;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
> span {
|
||||
white-space: nowrap;
|
||||
color: #927648;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-divider--horizontal {
|
||||
height: 3px;
|
||||
background: #D9D9D9;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.help {
|
||||
height: 61px;
|
||||
line-height: 61px;
|
||||
padding-left: 15px;
|
||||
|
||||
&:hover {
|
||||
background: #FBFBF7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.home-top-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.statistics {
|
||||
//display: flex;
|
||||
.block {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
height: calc((100vh / 2) - 150px);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
> div {
|
||||
height: 300px;
|
||||
flex: 0.9;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
261
src/views/projectdemand/demandcollection/add.vue
Normal file
261
src/views/projectdemand/demandcollection/add.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="add-block">
|
||||
<baseTitle title="需求征集信息录入"></baseTitle>
|
||||
<el-form :model="formData" inline class="query-form" ref="demandForm">
|
||||
<div class="left-info">
|
||||
<el-form-item label="名称" prop="requirementName">
|
||||
<el-input v-model="formData.requirementName" placeholder="请输入名称" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属公司" prop="companyIds">
|
||||
<el-tree-select v-model="formData.companyIds" :data="companyOption" style="width: 100%;"
|
||||
filterable clearable :check-strictly="true" multiple/>
|
||||
</el-form-item>
|
||||
<el-form-item label="征集类型" prop="collectType">
|
||||
<el-select v-model="formData.collectType" placeholder="征集类型" clearable filterable>
|
||||
<el-option
|
||||
v-for="item in typeOption"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="截止时间" prop="time">
|
||||
<el-config-provider>
|
||||
<el-date-picker
|
||||
v-model="formData.deadline"
|
||||
type="datetime"
|
||||
placeholder="截止时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-config-provider>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<baseTitle title="征集说明"></baseTitle>
|
||||
<Tinymce image-url="/notice/file" file-url="/notice/file" v-model:value="formData.collectExplain" height="300"/>
|
||||
<baseTitle title="申请文件"></baseTitle>
|
||||
<file-upload @getFile="getFile"/>
|
||||
<el-table :data="formData.fileList" style="width: 100%">
|
||||
<el-table-column label="序号" type="index" align="center" width="80"/>
|
||||
<el-table-column prop="fileName" label="文件名" align="center"/>
|
||||
<el-table-column prop="tag" label="标签" align="center"/>
|
||||
<el-table-column prop="size" label="文件大小" align="center">
|
||||
<template #default="scope">
|
||||
{{ parseInt(scope.row.size / 1024) }}KB
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="scope">
|
||||
<a :href="scope.row.url">
|
||||
下载
|
||||
</a>
|
||||
<el-button link type="primary" size="small" @click="beforeRemove(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="approval-record">
|
||||
<baseTitle title="流程"></baseTitle>
|
||||
<process-diagram-viewer mode="view" v-if="processDiagramViewer"/>
|
||||
<!-- <div class="process" id="approvalRecord">-->
|
||||
<!-- <process-tree ref="processTree" mode="view" id-name="approvalRecord"/>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<div class="oper-page-btn">
|
||||
<el-button color="#DED0B2" @click="handleSubmit">提交</el-button>
|
||||
<el-button color="#DED0B2" @click="handleResubmit">重新提交</el-button>
|
||||
<el-button @click="handleBack">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {useAuthStore} from '@/stores/userstore.js'
|
||||
import {useProcessStore} from '@/stores/processStore.js';
|
||||
import {getWorkflowInfo, addRequirement, getFormInfo, resubmit, deleteFile} from "@/api/project-demand/index.js";
|
||||
import FileUpload from "@/components/FileUpload.vue";
|
||||
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import {getSubCompOpt} from '@/api/user/user.js'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const dateValue = ref()
|
||||
const formData = ref({
|
||||
requirementName: '',
|
||||
companyIds: '',
|
||||
collectType: '',
|
||||
deadline: '',
|
||||
collectExplain: ''
|
||||
})
|
||||
const showTable = ref(false)
|
||||
const processDiagramViewer = ref(false)
|
||||
|
||||
const typeOption = ref([
|
||||
{
|
||||
label: "需求征集",
|
||||
value: '需求征集'
|
||||
}
|
||||
])
|
||||
const companyOption = ref([
|
||||
{
|
||||
label: "测试公司1",
|
||||
value: 22
|
||||
},
|
||||
{
|
||||
label: "测试公司2",
|
||||
value: 23
|
||||
},
|
||||
{
|
||||
label: "测试公司3",
|
||||
value: 24
|
||||
}
|
||||
])
|
||||
const form = ref(null)
|
||||
const fileList = ref(null)
|
||||
const menuTree = ref(null)
|
||||
const loading = ref(false)
|
||||
const processStore = useProcessStore()
|
||||
const processInstanceData = ref()
|
||||
|
||||
const compositeParam=(item)=>{
|
||||
return {
|
||||
fileId: item.id,
|
||||
size: item.size,
|
||||
fileName: item.fileName,
|
||||
fileType: item.fileType,
|
||||
url: item.url,
|
||||
processNodeTag: null,
|
||||
tag: formData.value.collectType,
|
||||
userId: authStore.userinfo.userId
|
||||
}
|
||||
}
|
||||
const getFile = (val) => {
|
||||
let fileObj = {}
|
||||
let newFileArray = []
|
||||
if (route.query.isAdd === undefined) {
|
||||
val.forEach(item => {
|
||||
fileObj =compositeParam(item)
|
||||
newFileArray.push(fileObj)
|
||||
formData.value.fileList.push(fileObj)
|
||||
})
|
||||
fileList.value = formData.value.fileList
|
||||
} else {
|
||||
val.forEach(item => {
|
||||
fileObj =compositeParam(item)
|
||||
newFileArray.push(fileObj)
|
||||
})
|
||||
formData.value.fileList = newFileArray
|
||||
fileList.value = newFileArray
|
||||
}
|
||||
}
|
||||
|
||||
const init = async () => {
|
||||
const res = await getSubCompOpt()
|
||||
companyOption.value = res.data
|
||||
getWorkflowInfo().then(res => {
|
||||
let data = res.data
|
||||
processInstanceData.value = data
|
||||
processStore.setDesign(data)
|
||||
processStore.runningList.value = data.runningList;
|
||||
processStore.endList.value = data.endList;
|
||||
processStore.noTakeList.value = data.noTakeList;
|
||||
processStore.refuseList.value = data.refuseList;
|
||||
processStore.passList.value = data.passList;
|
||||
nextTick(() => {
|
||||
processDiagramViewer.value = true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
let params = {
|
||||
...formData.value,
|
||||
requirementId: 0,
|
||||
files: fileList.value,
|
||||
deploymentId: processInstanceData.value.deploymentId
|
||||
}
|
||||
let res
|
||||
if (route.query.isAdd === undefined) {
|
||||
res = await resubmit(params)
|
||||
} else {
|
||||
res = await addRequirement(params)
|
||||
}
|
||||
if (res.code === 1000) {
|
||||
ElMessage.success(res.msg)
|
||||
await router.push({
|
||||
path: '/projectdemand/demandcollection'
|
||||
})
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
}
|
||||
}
|
||||
const getDetailInfo = async () => {
|
||||
getFormInfo(route.query.id).then(res => {
|
||||
if (res.code === 1000) {
|
||||
console.log(res)
|
||||
ElMessage.success(res.msg)
|
||||
formData.value = res.data
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
history.back()
|
||||
}
|
||||
const beforeRemove = (row) => {
|
||||
ElMessageBox.confirm(`确认删除名称为${row.filename}的表格吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
handleRemove(row)
|
||||
}).catch(() => {
|
||||
ElMessage.warning("用户取消删除! ");
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemove = (row) => {
|
||||
deleteFile(row.fileId).then(res => {
|
||||
if (res.code === 1000) {
|
||||
ElMessage.success("删除成功");
|
||||
fileList.value.splice(fileList.value.findIndex((item) => item.id === row.id), 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
await init()
|
||||
if (route.query.id) {
|
||||
await getDetailInfo()
|
||||
}
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.add-block {
|
||||
//display: flex;
|
||||
//justify-content: space-between;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #2a99ff;
|
||||
}
|
||||
|
||||
.approval-record {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
211
src/views/projectdemand/demandcollection/detail.vue
Normal file
211
src/views/projectdemand/demandcollection/detail.vue
Normal file
@@ -0,0 +1,211 @@
|
||||
<template>
|
||||
<div class="detail-block">
|
||||
<el-form :model="formData" label-width="auto">
|
||||
<baseTitle title="需求征集详情"></baseTitle>
|
||||
<div class="left-info">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称">
|
||||
<span>{{ formData.requirementName }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属公司">
|
||||
<span>{{ formData.companyIds }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="征集类型">
|
||||
<span>{{ formData.collectType }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="截止时间">
|
||||
<span>{{ formData.deadline }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<baseTitle title="征集说明"></baseTitle>
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-card style="width: 100%">
|
||||
<div v-html="formData.collectExplain">
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<baseTitle title="附件列表"></baseTitle>
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-table :data="formData.fileList" style="width: 100%">
|
||||
<el-table-column label="序号" type="index" align="center" width="80"/>
|
||||
<el-table-column prop="fileName" label="文件名" align="center"/>
|
||||
<el-table-column prop="tag" label="标签" align="center"/>
|
||||
<el-table-column prop="size" label="文件大小" align="center">
|
||||
<template #default="scope">
|
||||
{{ parseInt(scope.row.size / 1024) }}KB
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="scope">
|
||||
<a :href="scope.row.url">
|
||||
下载
|
||||
</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div v-if="processInstanceData.taskId">
|
||||
<baseTitle title="审核意见"></baseTitle>
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="auditOpinion"
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
placeholder="请输入审核意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="approval-record">
|
||||
<baseTitle title="审批记录"></baseTitle>
|
||||
<div class="process">
|
||||
<operation-render v-if="processDiagramViewer" :operation-list="processInstanceData.operationList"
|
||||
:state="processInstanceData.state"/>
|
||||
<process-diagram-viewer v-if="processDiagramViewer"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="oper-page-btn" v-if="processInstanceData.state === '1' && processInstanceData.taskId">
|
||||
<el-button @click="handleReject">驳回</el-button>
|
||||
<el-button color="#DED0B2" @click="handleSubmit">同意</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import OperationRender from '@/views/workflow/common/OperationRender.vue'
|
||||
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
|
||||
import {useProcessStore} from '@/stores/processStore.js';
|
||||
import {getInfo, agreeTask, rejectTask} from "@/api/project-demand/index.js";
|
||||
import {getSubCompOpt} from '@/api/user/user.js'
|
||||
|
||||
const route = useRoute()
|
||||
const form = ref();
|
||||
const processStore = useProcessStore()
|
||||
const companyOption = ref([])
|
||||
const processInstanceData = ref({})
|
||||
const processDiagramViewer = ref(false)
|
||||
const processTree = ref()
|
||||
const companyNameArray = ref([])
|
||||
const formData = ref({})
|
||||
const auditOpinion = ref('')
|
||||
const handleSubmit = () => {
|
||||
let approve = {
|
||||
taskId: processInstanceData.value.taskId,
|
||||
auditOpinion: auditOpinion.value,
|
||||
formData: formData.value
|
||||
}
|
||||
agreeTask(approve).then(res => {
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
const handleReject = () => {
|
||||
let approve = {
|
||||
taskId: processInstanceData.value.taskId,
|
||||
auditOpinion: auditOpinion.value,
|
||||
}
|
||||
rejectTask(approve).then(res => {
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
const getCompanyOption = async () => {
|
||||
const res = await getSubCompOpt()
|
||||
companyOption.value = res.data
|
||||
}
|
||||
|
||||
const matterTree = (data, id) => {
|
||||
if(id){
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].value == id) {
|
||||
companyNameArray.value.push(data[i].label);
|
||||
}
|
||||
if (data[i].children && data[i].children.length > 0) {
|
||||
matterTree(data[i].children)
|
||||
}
|
||||
}
|
||||
return companyNameArray.value;
|
||||
}
|
||||
}
|
||||
|
||||
const getDataSourceOptionItem = (val) => {
|
||||
if (val !== undefined) {
|
||||
val.forEach(item => {
|
||||
matterTree(companyOption.value,item)
|
||||
})
|
||||
}
|
||||
return companyNameArray.value.join(',');
|
||||
}
|
||||
const init = async () => {
|
||||
await getCompanyOption()
|
||||
getInfo(route.query.id).then(res => {
|
||||
let data = res.data
|
||||
formData.value = data.formData;
|
||||
data.formData.companyIds= getDataSourceOptionItem(data.formData.companyIds)
|
||||
processInstanceData.value = data
|
||||
processStore.setDesign(data)
|
||||
processStore.runningList.value = data.runningList;
|
||||
processStore.endList.value = data.endList;
|
||||
processStore.noTakeList.value = data.noTakeList;
|
||||
processStore.refuseList.value = data.refuseList;
|
||||
processStore.passList.value = data.passList;
|
||||
nextTick(() => {
|
||||
processDiagramViewer.value = true
|
||||
})
|
||||
})
|
||||
}
|
||||
init()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #2a99ff;
|
||||
}
|
||||
|
||||
.detail-block {
|
||||
overflow: hidden;
|
||||
padding-right: 10px;
|
||||
|
||||
.left-info {
|
||||
.info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> div {
|
||||
width: 350px;
|
||||
margin-bottom: 15px;
|
||||
margin-right: 10px;
|
||||
|
||||
> span:first-child {
|
||||
color: black;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.approval-record {
|
||||
padding-bottom: 30px;
|
||||
.process {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,13 +1,160 @@
|
||||
<template>
|
||||
<div>
|
||||
需求征集
|
||||
</div>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search"></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick"></fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import Tag from '@/components/Tag.vue'
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const searchConfig = reactive([
|
||||
{
|
||||
label: '需求名称',
|
||||
prop: 'requirementName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入名称查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '征集类型',
|
||||
prop: 'collectType',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {
|
||||
placeholder: '请选择征集类型',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
cacheKey: 'todo_type'
|
||||
}
|
||||
}
|
||||
])
|
||||
const tableIns = ref()
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
type: 'selection',
|
||||
prop: 'selection'
|
||||
},
|
||||
{
|
||||
prop: 'requirementName',
|
||||
label: '需求名称',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'collectType',
|
||||
label: '征集类型',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'approveName',
|
||||
label: '审批人',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'deadline',
|
||||
label: '截止时间',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'taskNode',
|
||||
label: '当前节点',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'state',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
width: 200,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => (<Tag dictType={'process_state'} value={row.state}/>)
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = [{label: '详情', func: () => handleDetail(row), type: 'primary'}]
|
||||
if (row.state === '3' || row.state === '2') {
|
||||
btn.push({label: '编辑', func: () => handleEdit(row), type: 'primary'})
|
||||
btn.push({label: '删除', func: () => handleDelete(row), type: 'danger'})
|
||||
} else if (row.state === '4') {
|
||||
btn.push({label: '上报', func: () => handleReport(row), type: 'primary'})
|
||||
}
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
btn.map(item => (
|
||||
<el-button
|
||||
type={item.type}
|
||||
// v-perm={item.auth}
|
||||
onClick={() => item.func()}
|
||||
link
|
||||
>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
],
|
||||
api: '/workflow/mosr/requirement',
|
||||
btns: [
|
||||
{name: '新增', key: 'add', color: '#DED0B2'},
|
||||
{name: '导出', key: 'add', type: ''},
|
||||
],
|
||||
params: {}
|
||||
})
|
||||
|
||||
const search = (val) => {
|
||||
tableConfig.params = {...val}
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({
|
||||
path: '/projectdemand/demandadd',
|
||||
query: {
|
||||
isAdd: 1
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleEdit = (row) => {
|
||||
router.push({
|
||||
path: '/projectdemand/demandedit',
|
||||
query: {
|
||||
id: row.requirementId
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleDetail = (row) => {
|
||||
router.push({
|
||||
path: '/projectdemand/demanddetail',
|
||||
query: {
|
||||
id: row.requirementId
|
||||
}
|
||||
})
|
||||
}
|
||||
const headBtnClick = (key) => {
|
||||
switch (key) {
|
||||
case 'add':
|
||||
handleAdd()
|
||||
break;
|
||||
case 'edit':
|
||||
handleEdit()
|
||||
break;
|
||||
case 'detail':
|
||||
handleDetail()
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,127 @@
|
||||
<template>
|
||||
<div>
|
||||
需求汇总
|
||||
</div>
|
||||
<fvSearchForm :searchConfig="searchConfig"></fvSearchForm>
|
||||
<fvTable :table-config="tableConfig"></fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import { reactive, shallowRef } from 'vue';
|
||||
import fvSelect from './../../../fvcomponents/fvSelect/index.vue'
|
||||
|
||||
const localData = reactive({
|
||||
// 表格配置
|
||||
|
||||
})
|
||||
|
||||
const searchConfig = reactive([
|
||||
{
|
||||
label: '名称',
|
||||
prop: 'name',
|
||||
component: 'el-input',
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '项目类型',
|
||||
prop: 'projectType',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {},
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '研发主体',
|
||||
prop: 'productMainBody',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {},
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '项目影响',
|
||||
prop: 'projectEffect',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {},
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '起止时间',
|
||||
prop: 'time',
|
||||
component: 'el-date-picker',
|
||||
props: {},
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '最小金额',
|
||||
prop: 'minMoney',
|
||||
component: 'el-input',
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '最大金额',
|
||||
prop: 'maxMoney',
|
||||
component: 'el-input',
|
||||
colProps: {}
|
||||
},
|
||||
])
|
||||
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
type: 'selection',
|
||||
prop: 'selection'
|
||||
},
|
||||
{
|
||||
prop: 'name',
|
||||
label: '名称',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'company',
|
||||
label: '所属公司',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'projectType',
|
||||
label: '项目类型',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'productMainBody',
|
||||
label: '研发主体',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'projectEffect',
|
||||
label: '项目影响',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'survey',
|
||||
label: '经营概况',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'time',
|
||||
label: '起止时间',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '发布状态',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => {
|
||||
return (
|
||||
<div>
|
||||
<el-button type={'primary'} link onClick={()=>{}}>详情</el-button>
|
||||
<el-button type={'primary'} link onClick={()=>{}}>上报</el-button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
<div v-loading="loading" class="initiate_process">
|
||||
<div v-if="!loading" style="min-width:30%">
|
||||
<!--渲染表单-->
|
||||
<form-render class="process-form" ref="initiateForm" :form-items="processDefinition.formItems"
|
||||
v-model:value="formData" mode="E"/>
|
||||
<!-- todo 关闭以前的表单渲染 , 此处需要根据参数来定制当前需要展示的页面信息 -->
|
||||
<!-- <form-render class="process-form" ref="initiateForm" :form-items="processDefinition.formItems"-->
|
||||
<!-- v-model:value="formData" mode="E"/>-->
|
||||
</div>
|
||||
<div v-if="!loading" id="approveTree"
|
||||
style="display: flex;justify-content: center;flex-direction: column;min-width:60%">
|
||||
@@ -18,8 +19,9 @@ import {getInitiateInfo} from "@/api/workflow/process-definition.js";
|
||||
import ProcessTree from '@/views/workflow/process/ProcessTree.vue'
|
||||
import FormRender from '@/views/workflow/form/FormRender.vue'
|
||||
import {useProcessStore} from '@/stores/processStore.js'
|
||||
|
||||
const processStore = useProcessStore()
|
||||
import {defineProps,defineExpose} from 'vue'
|
||||
import {defineProps, defineExpose} from 'vue'
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -101,6 +101,7 @@ const handleReset = () => {
|
||||
}
|
||||
|
||||
const submitForm = () => {
|
||||
// todo 重新编写表单数据, 不适用当前的动态表单
|
||||
let formData = processInstance.value.formData
|
||||
let paramsData = {
|
||||
processDefinitionId: selectItem.value.processDefinitionId,
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 15px;background:#f5f5f5;"></div>
|
||||
<form-render ref="taskViewForm" :form-items="processInstanceData.formItems"
|
||||
v-model:value="processInstanceData.formData"/>
|
||||
<!-- <form-render ref="taskViewForm" :form-items="processInstanceData.formItems"-->
|
||||
<!-- v-model:value="processInstanceData.formData"/>-->
|
||||
<div style="height: 15px;background:#f5f5f5;"></div>
|
||||
<operation-render :operation-list="processInstanceData.operationList"
|
||||
:state="instance.state"/>
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<script setup>
|
||||
import Tag from '@/components/Tag.vue'
|
||||
import FormRender from '@/views/workflow/form/FormRender.vue'
|
||||
// import FormRender from '@/views/workflow/form/FormRender.vue'
|
||||
import OperationRender from '@/views/workflow/common/OperationRender.vue'
|
||||
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
|
||||
import {getInitiatedInstanceInfo} from "@/api/workflow/process-instance.js";
|
||||
@@ -95,4 +95,4 @@ defineExpose({
|
||||
init
|
||||
})
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
:color="operation.color"
|
||||
size="large"
|
||||
placement="top">
|
||||
|
||||
<el-card>
|
||||
<div style="display: flex;">
|
||||
<div v-for="(user,index) in operation.userInfo" :key="index" class="avatar_name">
|
||||
@@ -19,34 +20,43 @@
|
||||
<component :is="user.icon"/>
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-tooltip effect="dark" :content="user.name" placement="bottom-start">
|
||||
<el-tooltip effect="dark" :content="user.name" placement="bottom-start">
|
||||
<span class="username">{{ user.name }}</span>
|
||||
</el-tooltip>
|
||||
|
||||
<template v-if="user.auditOpinion">
|
||||
<div style="margin-top: 10px;background:#f5f5f5;padding: 10px;">
|
||||
<div>
|
||||
{{ user.auditOpinion }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div style="margin-left: 10px;">
|
||||
<div style="color: #c0bebe">{{ operation.operationName }}</div>
|
||||
<div style="font-size: 14px; font-weight: bold;">{{ operation.remark }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="operation.comment">
|
||||
<div style="margin-top: 10px;background:#f5f5f5;padding: 10px;">
|
||||
<div>
|
||||
{{ operation.comment.context }}
|
||||
</div>
|
||||
<div style="margin-top: 10px;" v-if="operation.comment.attachments && operation.comment.attachments.length > 0">
|
||||
<template v-for="(item) in getAttachmentList(operation.comment.attachments,true)">
|
||||
<el-image
|
||||
style="width: 100px; height: 100px"
|
||||
:src="item.url"
|
||||
:preview-src-list="[item.url]">
|
||||
</el-image>
|
||||
</template>
|
||||
<div v-for="(file) in getAttachmentList(operation.comment.attachments,false)">
|
||||
<el-link style="color: #2a99ff" :href="file.url" icon="el-icon-document">{{ file.name }}</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- <template v-if="operation.comment">-->
|
||||
<!-- <div style="margin-top: 10px;background:#f5f5f5;padding: 10px;">-->
|
||||
<!-- <div>-->
|
||||
<!-- {{ operation.comment.context }}-->
|
||||
<!-- </div>-->
|
||||
<!-- <div style="margin-top: 10px;"-->
|
||||
<!-- v-if="operation.comment.attachments && operation.comment.attachments.length > 0">-->
|
||||
<!-- <template v-for="(item) in getAttachmentList(operation.comment.attachments,true)">-->
|
||||
<!-- <el-image-->
|
||||
<!-- style="width: 100px; height: 100px"-->
|
||||
<!-- :src="item.url"-->
|
||||
<!-- :preview-src-list="[item.url]">-->
|
||||
<!-- </el-image>-->
|
||||
<!-- </template>-->
|
||||
<!-- <div v-for="(file) in getAttachmentList(operation.comment.attachments,false)">-->
|
||||
<!-- <el-link style="color: #2a99ff" :href="file.url" icon="el-icon-document">{{ file.name }}</el-link>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-timeline-item :color="timeline.color" :icon="timeline.icon" size="large">
|
||||
@@ -60,7 +70,7 @@
|
||||
|
||||
<script setup>
|
||||
import {CircleCheckFilled, Close, Loading, MoreFilled} from "@element-plus/icons-vue";
|
||||
import {ref,defineProps} from 'vue'
|
||||
import {ref, defineProps} from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
operationList: {
|
||||
@@ -113,12 +123,12 @@ const init = () => {
|
||||
break
|
||||
}
|
||||
// let operationListNew = []
|
||||
for (let i = 0;i<props.operationList.length;i++) {
|
||||
for (let i = 0; i < props.operationList.length; i++) {
|
||||
let operationNew = initOperationFun(props.operationList[i])
|
||||
let userList = []
|
||||
if (operationNew.userInfo){
|
||||
if (operationNew.userInfo) {
|
||||
for (let user of operationNew.userInfo) {
|
||||
let userNew = initUser(user,operationNew.operation)
|
||||
let userNew = initUser(user, operationNew.operation)
|
||||
userList.push(userNew)
|
||||
}
|
||||
operationNew.userInfo = userList
|
||||
@@ -132,7 +142,7 @@ const init = () => {
|
||||
|
||||
const getAttachmentList = (attachments, image) => {
|
||||
let result = [];
|
||||
if (attachments){
|
||||
if (attachments) {
|
||||
for (let attachment of attachments) {
|
||||
if (attachment.isImage === image) {
|
||||
result.push(attachment)
|
||||
@@ -142,7 +152,7 @@ const getAttachmentList = (attachments, image) => {
|
||||
return result;
|
||||
}
|
||||
|
||||
const initUser = (user,type) => {
|
||||
const initUser = (user, type) => {
|
||||
let state = user.state
|
||||
//创建节点
|
||||
if (state === 'CREATE') {
|
||||
@@ -154,7 +164,7 @@ const initUser = (user,type) => {
|
||||
user["icon"] = 'CircleCheckFilled'
|
||||
user["color"] = "#0bbd87"
|
||||
}
|
||||
if (type === "CC"){
|
||||
if (type === "CC") {
|
||||
user["icon"] = "Promotion"
|
||||
user["color"] = "#3395f8"
|
||||
}
|
||||
@@ -169,7 +179,7 @@ const initUser = (user,type) => {
|
||||
user["icon"] = 'Close'
|
||||
user["color"] = "#f56c6c"
|
||||
}
|
||||
if (state === 'PASS'){
|
||||
if (state === 'PASS') {
|
||||
user["icon"] = 'MoreFilled'
|
||||
user["color"] = "#c0c4cc"
|
||||
}
|
||||
@@ -277,7 +287,8 @@ init()
|
||||
position: relative;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.el-timeline-item__node{
|
||||
|
||||
.el-timeline-item__node {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 1px;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div style="margin-top: 40px">
|
||||
<div :style="'transform: scale('+ scale / 100 +');'">
|
||||
<div id="previewProcess">
|
||||
<process-tree mode="preview" ref="processTreePreview" id-name="previewProcess"/>
|
||||
<process-tree :mode="mode" ref="processTreePreview" id-name="previewProcess"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -20,6 +20,12 @@ import ProcessTree from '@/views/workflow/process/ProcessTree.vue'
|
||||
|
||||
const processTreePreview = ref()
|
||||
const scale = ref(100)
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'preview'
|
||||
}
|
||||
})
|
||||
|
||||
nextTick(()=>{
|
||||
processTreePreview.value.init()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div style="margin-top: 15px">
|
||||
<el-button @click="changPan('processSetting')">流程设置</el-button>
|
||||
<el-button @click="changPan('formDesign')">表单</el-button>
|
||||
<!-- <el-button @click="changPan('formDesign')">表单</el-button>-->
|
||||
<el-button @click="changPan('processDesign')">流程</el-button>
|
||||
<el-button @click="publishProcess">发布</el-button>
|
||||
<div class="layout-body" v-if="visible">
|
||||
@@ -11,9 +11,9 @@
|
||||
<div v-show="activeSelect === 'processDesign'">
|
||||
<process-design ref="processDesign"/>
|
||||
</div>
|
||||
<div v-show="activeSelect === 'formDesign'">
|
||||
<form-design ref="formDesign"/>
|
||||
</div>
|
||||
<!-- <div v-show="activeSelect === 'formDesign'">-->
|
||||
<!-- <form-design ref="formDesign"/>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -72,7 +72,8 @@ import {ElMessage, ElMessageBox} from "element-plus";
|
||||
const processDesign = ref()
|
||||
const visible = ref(false)
|
||||
const timer = ref(null)
|
||||
const validComponents = ref(['processSetting', 'formDesign', 'processDesign'])
|
||||
// const validComponents = ref(['processSetting', 'formDesign', 'processDesign'])
|
||||
const validComponents = ref(['processSetting', 'processDesign'])
|
||||
// const activeSelect = ref('formDesign')
|
||||
// const activeSelect = ref('processSetting')
|
||||
const activeSelect = ref('processDesign')
|
||||
@@ -81,7 +82,7 @@ const validStep = ref(0)
|
||||
const validResult = ref({})
|
||||
const validOptions = ref([
|
||||
{title: '基础信息', description: '', icon: '', status: ''},
|
||||
{title: '审批表单', description: '', icon: '', status: ''},
|
||||
// {title: '审批表单', description: '', icon: '', status: ''},
|
||||
{title: '审批流程', description: '', icon: '', status: ''},
|
||||
// {title: '扩展设置', description: '', icon: '', status: ''}
|
||||
])
|
||||
@@ -118,21 +119,21 @@ const loadInitFrom = () => {
|
||||
let design = {
|
||||
processDefinitionKey: 'pro' + getRandomId(),
|
||||
deploymentName: "未命名表单",
|
||||
logo: {
|
||||
icon: "el-icon-eleme",
|
||||
background: "#1e90ff"
|
||||
},
|
||||
settings: {
|
||||
commiter: [],
|
||||
admin: [],
|
||||
sign: false,
|
||||
notify: {
|
||||
types: ["APP"],
|
||||
title: "消息通知标题"
|
||||
}
|
||||
},
|
||||
// logo: {
|
||||
// icon: "el-icon-eleme",
|
||||
// background: "#1e90ff"
|
||||
// },
|
||||
// settings: {
|
||||
// commiter: [],
|
||||
// admin: [],
|
||||
// sign: false,
|
||||
// notify: {
|
||||
// types: ["APP"],
|
||||
// title: "消息通知标题"
|
||||
// }
|
||||
// },
|
||||
groupId: 1,
|
||||
formItems: [],
|
||||
// formItems: [],
|
||||
process: [
|
||||
{
|
||||
id: "root",
|
||||
@@ -151,6 +152,27 @@ const loadInitFrom = () => {
|
||||
type: "END",
|
||||
}
|
||||
],
|
||||
processFromPerms: [{
|
||||
id: "projectName",
|
||||
title: "项目名称",
|
||||
required: true,
|
||||
perm: "R"
|
||||
}, {
|
||||
id: "projectType",
|
||||
title: "项目类型",
|
||||
required: true,
|
||||
perm: "R"
|
||||
}, {
|
||||
id: "projectDesc",
|
||||
title: "项目描述",
|
||||
required: true,
|
||||
perm: "R"
|
||||
}, {
|
||||
id: "projectManager",
|
||||
title: "项目经理",
|
||||
required: true,
|
||||
perm: "R"
|
||||
}],
|
||||
remark: "备注说明"
|
||||
}
|
||||
processStore.setDesign(design)
|
||||
|
||||
@@ -36,6 +36,7 @@ const valid = ref(true)
|
||||
let vNode = {}
|
||||
|
||||
const init = () => {
|
||||
// console.log("sdsdsdsdsdsdsd",processStore.getProcess())
|
||||
processStore.init()
|
||||
initMapping(processStore.getProcess())
|
||||
// 定义类名(可忽略)
|
||||
@@ -48,7 +49,7 @@ const init = () => {
|
||||
|
||||
// 初始化map集合,以便数据整理
|
||||
const initMapping = (node) => {
|
||||
node.forEach(nodeItem => {
|
||||
node?.forEach(nodeItem => {
|
||||
processStore.nodeMap.set(nodeItem.id, nodeItem)
|
||||
processStore.parentMap.set(nodeItem.parentId, nodeItem)
|
||||
})
|
||||
@@ -57,15 +58,15 @@ const initMapping = (node) => {
|
||||
const initHeaderBgc = (node) => {
|
||||
if (node.props && props.mode === 'preview') {
|
||||
let headerBgc = '#ff943e'
|
||||
if (processStore.runningList.value.includes(node.id)) {
|
||||
if (processStore.runningList.value?.includes(node.id)) {
|
||||
headerBgc = '#1e90ff'
|
||||
} else if (processStore.endList.value.includes(node.id)) {
|
||||
} else if (processStore.endList.value?.includes(node.id)) {
|
||||
headerBgc = '#20b2aa'
|
||||
} else if (processStore.noTakeList.value.includes(node.id)) {
|
||||
} else if (processStore.noTakeList.value?.includes(node.id)) {
|
||||
headerBgc = '#909399'
|
||||
} else if (processStore.refuseList.value.includes(node.id)) {
|
||||
} else if (processStore.refuseList.value?.includes(node.id)) {
|
||||
headerBgc = '#f56c6c'
|
||||
} else if (processStore.passList.value.includes(node.id)) {
|
||||
} else if (processStore.passList.value?.includes(node.id)) {
|
||||
headerBgc = '#ff943e'
|
||||
}
|
||||
node.props.headerBgc = headerBgc
|
||||
@@ -309,9 +310,9 @@ const insertNode = debounce((type, parentNode) => {
|
||||
case 'DELAY':
|
||||
insertDelayNode(children);
|
||||
break;
|
||||
case 'TRIGGER':
|
||||
insertTriggerNode(children);
|
||||
break;
|
||||
// case 'TRIGGER':
|
||||
// insertTriggerNode(children);
|
||||
// break;
|
||||
case 'CONDITIONS':
|
||||
insertConditionsNode(children);
|
||||
break;
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
<slot name="pre"></slot>
|
||||
<div style="display: flex;flex-wrap: wrap;">
|
||||
<div v-for="(user,index) in userInfo" :key="index" class="avatar_name">
|
||||
<el-avatar size="large"
|
||||
:src="user.avatar"></el-avatar>
|
||||
<div class="circle-user">
|
||||
<el-tooltip class="item" effect="dark" :content="user.name" placement="bottom-start">
|
||||
<span class="item_name">{{ user.name }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div v-if="user.icon"
|
||||
class="el-timeline-item__node" :style="{
|
||||
backgroundColor: user.color
|
||||
@@ -15,17 +18,15 @@
|
||||
<component :is="user.icon"/>
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-tooltip class="item" effect="dark" :content="user.name" placement="bottom-start">
|
||||
<span class="item_name">{{ user.name }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {Loading,Close,CircleCheckFilled,MoreFilled} from '@element-plus/icons-vue'
|
||||
import {Loading, Close, CircleCheckFilled, MoreFilled} from '@element-plus/icons-vue'
|
||||
import {defineProps} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
row: {
|
||||
type: Number,
|
||||
@@ -38,6 +39,10 @@ const props = defineProps({
|
||||
userInfo: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'design'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -70,7 +75,7 @@ const initUser = (user) => {
|
||||
user["icon"] = Close
|
||||
user["color"] = "#f56c6c"
|
||||
}
|
||||
if (state === 'PASS'){
|
||||
if (state === 'PASS') {
|
||||
user["icon"] = MoreFilled
|
||||
user["color"] = "#c0c4cc"
|
||||
}
|
||||
@@ -80,7 +85,27 @@ const initUser = (user) => {
|
||||
init()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style scoped lang="scss">
|
||||
.circle-user {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #ACACAC;
|
||||
position: relative;
|
||||
|
||||
.circle-icon {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
top: auto !important;
|
||||
bottom: -9px;
|
||||
right: 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar_name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -92,7 +117,7 @@ init()
|
||||
|
||||
.el-timeline-item__node {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
bottom: 0;
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
</el-icon>
|
||||
<span>延迟等待</span>
|
||||
</div>
|
||||
<div @click="addTriggerNode">
|
||||
<el-icon style="color:#15BC83;">
|
||||
<SetUp/>
|
||||
</el-icon>
|
||||
<span>触发器</span>
|
||||
</div>
|
||||
<!-- <div @click="addTriggerNode">-->
|
||||
<!-- <el-icon style="color:#15BC83;">-->
|
||||
<!-- <SetUp/>-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- <span>触发器</span>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<template #reference>
|
||||
<!-- <el-button :icon="Plus" slot="reference" type="primary" @click="visible = !visible" size="small"-->
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<el-input-number :min="1" :max="20" :step="1" size="mini"
|
||||
v-model="nodeProps.leader.level"></el-input-number>
|
||||
<span> 级主管</span>
|
||||
<div style="color: #409EFF; font-size: small;">👉 直接主管为 第 1 级主管</div>
|
||||
<div style="color: #409EFF; font-size: small;">直接主管为 第 1 级主管</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else-if="nodeProps.assignedType === 'ROLE'">
|
||||
@@ -56,12 +56,12 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="item-desc">发起人自己作为审批人进行审批</span>
|
||||
</div>
|
||||
<!-- <div v-else>-->
|
||||
<!-- <span class="item-desc">发起人自己作为审批人进行审批</span>-->
|
||||
<!-- </div>-->
|
||||
</el-form-item>
|
||||
<el-divider></el-divider>
|
||||
<el-form-item label="👤 审批人为空时" prop="text" class="line-mode">
|
||||
<el-form-item label="审批人为空时" prop="text" class="line-mode">
|
||||
<el-radio-group v-model="nodeProps.nobody.handler">
|
||||
<el-radio label="TO_PASS">自动通过</el-radio>
|
||||
<el-radio label="TO_REFUSE">自动驳回</el-radio>
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
<div v-if="showMode">
|
||||
<el-divider/>
|
||||
<el-form-item label="👩👦👦 多人审批时审批方式" prop="text" class="approve-mode">
|
||||
<el-form-item label="多人审批时审批方式" prop="text" class="approve-mode">
|
||||
<el-radio-group v-model="nodeProps.mode">
|
||||
<el-radio label="NEXT">会签 (按选择顺序审批,每个人必须同意)</el-radio>
|
||||
<el-radio label="AND">会签(可同时审批,每个人必须同意)</el-radio>
|
||||
@@ -90,13 +90,16 @@
|
||||
</div>
|
||||
|
||||
<el-divider>高级设置</el-divider>
|
||||
<el-form-item label="✍ 审批同意时是否需要签字" prop="text">
|
||||
<el-switch inactive-text="不用" active-text="需要" v-model="nodeProps.sign"></el-switch>
|
||||
<el-tooltip class="item" effect="dark" content="如果全局设置了需要签字,则此处不生效" placement="top-start">
|
||||
<i class="el-icon-question" style="margin-left: 10px; font-size: medium; color: #b0b0b1"></i>
|
||||
</el-tooltip>
|
||||
<!-- <el-form-item label="✍ 审批同意时是否需要签字" prop="text">-->
|
||||
<!-- <el-switch inactive-text="不用" active-text="需要" v-model="nodeProps.sign"></el-switch>-->
|
||||
<!-- <el-tooltip class="item" effect="dark" content="如果全局设置了需要签字,则此处不生效" placement="top-start">-->
|
||||
<!-- <i class="el-icon-question" style="margin-left: 10px; font-size: medium; color: #b0b0b1"></i>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="是否使用矩阵审批" prop="text">
|
||||
<el-switch inactive-text="不用" active-text="使用" v-model="nodeProps.matrixApproval"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="⏱ 审批期限(为 0 则不生效)" prop="timeLimit">
|
||||
<el-form-item label="审批期限(为 0 则不生效)" prop="timeLimit">
|
||||
<el-input style="width: 180px;" placeholder="时长" type="number"
|
||||
v-model="nodeProps.timeLimit.timeout.value">
|
||||
<el-select style="width: 75px;" v-model="nodeProps.timeLimit.timeout.unit" slot="append" placeholder="请选择" filterable>
|
||||
@@ -122,54 +125,54 @@
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="🙅 如果审批被驳回 👇">
|
||||
<el-radio-group v-model="nodeProps.refuse.type">
|
||||
<el-radio label="TO_INITIAL">重新开始流程</el-radio>
|
||||
<el-radio label="TO_BEFORE">驳回到上级审批节点</el-radio>
|
||||
<el-radio label="TO_NODE">驳回到指定节点</el-radio>
|
||||
</el-radio-group>
|
||||
<div v-if="nodeProps.refuse.type === 'TO_NODE'">
|
||||
<span>指定节点:</span>
|
||||
<el-select style="margin-left: 10px; width: 150px;" placeholder="选择跳转步骤" size="small"
|
||||
v-model="nodeProps.refuse.target" filterable>
|
||||
<el-option v-for="(node, index) in nodeOptions" :key="index" :label="node.name"
|
||||
:value="node.id"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="自定义监听器">
|
||||
<div slot="label">
|
||||
<span style="margin-left: 20px">使用自定义监听器: </span>
|
||||
<!-- <el-switch v-model="config.listener.state" @change="getListener"></el-switch>-->
|
||||
</div>
|
||||
<div v-if="config.listener.state">
|
||||
<div slot="label">
|
||||
<span style="margin-right: 10px">设置监听器</span>
|
||||
<el-button type="primary" @click="addListener(config.listener.list)" link> + 添加</el-button>
|
||||
</div>
|
||||
<div v-for="(listen, index) in config.listener.list" :key="index">
|
||||
<el-input v-if="listen.isSys" placeholder="监听器名称" :disabled="true" size="small" style="width: 100px;"
|
||||
v-model="listen.listenerName"/>
|
||||
<el-input v-if="!listen.isSys" placeholder="监听器名称" size="small" style="width: 100px;"
|
||||
v-model="listen.listenerName"/>
|
||||
<el-radio-group size="small" style="margin: 0 5px;" @change="typeChange(listen)" v-model="listen.isSys">
|
||||
<el-radio-button :label="true">内置</el-radio-button>
|
||||
<el-radio-button :label="false">自定义</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-select v-if="listen.isSys" style="width: 180px;" v-model="listen.listenerValue" size="small"
|
||||
@change="listenerOptionChange(listen)"
|
||||
placeholder="请选择表单字段" filterable>
|
||||
<el-option v-for="option in listenerOption" :key="option.value" :label="option.label"
|
||||
:value="option.value"/>
|
||||
</el-select>
|
||||
<!-- <el-input v-if="listen.isSys" placeholder="请设置字段值" size="small" v-model="listen.listenerValue" style="width: 180px;"/>-->
|
||||
<el-button v-if="!listen.isSys" type="primary" size="small" @click="settingListener(listen)" link>设置</el-button>
|
||||
<el-button @click="delListener(config.listener.list, index)"
|
||||
class="el-icon-delete" type="primary"
|
||||
style="margin-left: 5px; color: #c75450;" link/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="🙅 如果审批被驳回 👇">-->
|
||||
<!-- <el-radio-group v-model="nodeProps.refuse.type">-->
|
||||
<!-- <el-radio label="TO_INITIAL">重新开始流程</el-radio>-->
|
||||
<!-- <el-radio label="TO_BEFORE">驳回到上级审批节点</el-radio>-->
|
||||
<!-- <el-radio label="TO_NODE">驳回到指定节点</el-radio>-->
|
||||
<!-- </el-radio-group>-->
|
||||
<!-- <div v-if="nodeProps.refuse.type === 'TO_NODE'">-->
|
||||
<!-- <span>指定节点:</span>-->
|
||||
<!-- <el-select style="margin-left: 10px; width: 150px;" placeholder="选择跳转步骤" size="small"-->
|
||||
<!-- v-model="nodeProps.refuse.target" filterable>-->
|
||||
<!-- <el-option v-for="(node, index) in nodeOptions" :key="index" :label="node.name"-->
|
||||
<!-- :value="node.id"></el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="自定义监听器">-->
|
||||
<!-- <div slot="label">-->
|
||||
<!-- <span style="margin-left: 20px">使用自定义监听器: </span>-->
|
||||
<!-- <!– <el-switch v-model="config.listener.state" @change="getListener"></el-switch>–>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-if="config.listener.state">-->
|
||||
<!-- <div slot="label">-->
|
||||
<!-- <span style="margin-right: 10px">设置监听器</span>-->
|
||||
<!-- <el-button type="primary" @click="addListener(config.listener.list)" link> + 添加</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-for="(listen, index) in config.listener.list" :key="index">-->
|
||||
<!-- <el-input v-if="listen.isSys" placeholder="监听器名称" :disabled="true" size="small" style="width: 100px;"-->
|
||||
<!-- v-model="listen.listenerName"/>-->
|
||||
<!-- <el-input v-if="!listen.isSys" placeholder="监听器名称" size="small" style="width: 100px;"-->
|
||||
<!-- v-model="listen.listenerName"/>-->
|
||||
<!-- <el-radio-group size="small" style="margin: 0 5px;" @change="typeChange(listen)" v-model="listen.isSys">-->
|
||||
<!-- <el-radio-button :label="true">内置</el-radio-button>-->
|
||||
<!-- <el-radio-button :label="false">自定义</el-radio-button>-->
|
||||
<!-- </el-radio-group>-->
|
||||
<!-- <el-select v-if="listen.isSys" style="width: 180px;" v-model="listen.listenerValue" size="small"-->
|
||||
<!-- @change="listenerOptionChange(listen)"-->
|
||||
<!-- placeholder="请选择表单字段" filterable>-->
|
||||
<!-- <el-option v-for="option in listenerOption" :key="option.value" :label="option.label"-->
|
||||
<!-- :value="option.value"/>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- <!– <el-input v-if="listen.isSys" placeholder="请设置字段值" size="small" v-model="listen.listenerValue" style="width: 180px;"/>–>-->
|
||||
<!-- <el-button v-if="!listen.isSys" type="primary" size="small" @click="settingListener(listen)" link>设置</el-button>-->
|
||||
<!-- <el-button @click="delListener(config.listener.list, index)"-->
|
||||
<!-- class="el-icon-delete" type="primary"-->
|
||||
<!-- style="margin-left: 5px; color: #c75450;" link/>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
<!--
|
||||
<el-dialog custom-class="custom-dialog" class="border" width="600px" title="定义监听器设置"
|
||||
@@ -230,12 +233,13 @@ const showOrgSelect = ref(false)
|
||||
const orgPickerSelected = ref([])
|
||||
const approvalTypes = reactive([
|
||||
{name: "指定人员", type: "ASSIGN_USER"},
|
||||
{name: "发起人自选", type: "SELF_SELECT"},
|
||||
{name: "连续多级主管", type: "LEADER_TOP"},
|
||||
{name: "主管", type: "LEADER"},
|
||||
{name: "角色", type: "ROLE"},
|
||||
// {name: "发起人自选", type: "SELF_SELECT"},
|
||||
// {name: "连续多级主管", type: "LEADER_TOP"},
|
||||
// {name: "主管", type: "LEADER"},
|
||||
// {name: "角色", type: "ROLE"},
|
||||
{name: "发起人自己", type: "SELF"},
|
||||
{name: "表单内联系人", type: "FORM_USER"}
|
||||
// {name: "表单内联系人", type: "FORM_USER"},
|
||||
// {name: "矩阵审批", type: "MATRIX_APPROVAL"},
|
||||
])
|
||||
const listenerOption = ref([])
|
||||
const selectListen = ref({})
|
||||
|
||||
@@ -94,7 +94,9 @@
|
||||
<org-items :modelValue="users"/>
|
||||
</span>
|
||||
<span v-else-if="condition.valueType === ValueType.date"></span>
|
||||
<el-icon class="delete-icon" @click="delSubCondition(group, cindex)"><Minus /></el-icon>
|
||||
<el-icon class="delete-icon" @click="delSubCondition(group, cindex)">
|
||||
<Minus/>
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -119,7 +121,7 @@ const users = ref([])
|
||||
// const orgType = ref('user')
|
||||
const showOrgSelect = ref(false)
|
||||
const groupNames = ref(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'])
|
||||
const supportTypes = ref([ValueType.number, ValueType.string, ValueType.date, ValueType.dateRange, ValueType.dept, ValueType.user])
|
||||
const supportTypes = ref([ValueType.number, ValueType.string])
|
||||
const explains = ref(
|
||||
[
|
||||
{label: '等于', value: '='},
|
||||
@@ -140,14 +142,20 @@ const selectedNode = computed(() => {
|
||||
return processStore.getSelectedNode()
|
||||
})
|
||||
|
||||
const processFromPerms = computed(() => {
|
||||
return processStore.getDesign().processFromPerms;
|
||||
});
|
||||
|
||||
const conditionList = computed(() => {
|
||||
//条件数组
|
||||
//构造可用条件选项
|
||||
const conditionItems = []
|
||||
processStore.getDesign().formItems.forEach(item => filterCondition(item, conditionItems))
|
||||
if (conditionItems.length === 0 || conditionItems[0].id !== 'root') {
|
||||
conditionItems.unshift({id: 'root', title: '发起人', valueType: 'User'})
|
||||
}
|
||||
filterConditionMosr(conditionItems)
|
||||
// processStore.getDesign().formItems.forEach(item => filterCondition(item, conditionItems))
|
||||
// if (conditionItems.length === 0 || conditionItems[0].id !== 'root') {
|
||||
// conditionItems.unshift({id: 'root', title: '发起人', valueType: 'User'})
|
||||
// }
|
||||
// conditionItems.unshift({id: 'root', title: '发起人', valueType: 'User'})
|
||||
return conditionItems
|
||||
})
|
||||
|
||||
@@ -184,6 +192,14 @@ const selectUser = (value, orgType) => {
|
||||
users.value = value
|
||||
orgPicker.value.showUserPicker()
|
||||
}
|
||||
const filterConditionMosr = (list) => {
|
||||
processFromPerms.value.forEach((item) => {
|
||||
console.log(item)
|
||||
if (item.required && supportTypes.value.indexOf(item.valueType) > -1){
|
||||
list.push({title: item.title, id: item.id, valueType: item.valueType})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const filterCondition = (item, list) => {
|
||||
//从表单中过滤出可以选择的条件
|
||||
@@ -206,8 +222,7 @@ const selected = (selected) => {
|
||||
users.value = userInfoList
|
||||
//组织选择器的选中回调函数
|
||||
// users.value.length = 0
|
||||
// console.log('processStore.getAssignedUser()',processStore.getAssignedUser())
|
||||
processStore.getAssignedUser().forEach(u => users.value=userInfoList)
|
||||
processStore.getAssignedUser().forEach(u => users.value = userInfoList)
|
||||
}
|
||||
|
||||
const delGroup = (index) => {
|
||||
@@ -228,7 +243,6 @@ const conditionChange = (index, group) => {
|
||||
if (0 > group.conditions.findIndex(cd => cd.id === cid)) {
|
||||
//新增条件
|
||||
let condition = {...conditionList.value[index]}
|
||||
console.log('fs', condition, conditionList.value, index)
|
||||
condition.compare = '';
|
||||
condition.value = []
|
||||
group.conditions.push(condition)
|
||||
|
||||
@@ -18,24 +18,24 @@
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
<el-form-item label="条件组关系" label-width="150px">
|
||||
<el-switch v-model="selectedNode.props.groupsType" active-color="#409EFF"
|
||||
inactive-color="#c1c1c1" active-value="AND" inactive-value="OR"
|
||||
active-text="且" inactive-text="或">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="条件组表达式">
|
||||
<el-input v-model="config.expression" placeholder="输入条件组关系表达式 &为与,|为或"/>
|
||||
<span class="item-desc">使用表达式构建复杂逻辑,例如: (A & B) | C</span>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="条件组关系" label-width="150px">-->
|
||||
<!-- <el-switch v-model="selectedNode.props.groupsType" active-color="#409EFF"-->
|
||||
<!-- inactive-color="#c1c1c1" active-value="AND" inactive-value="OR"-->
|
||||
<!-- active-text="且" inactive-text="或">-->
|
||||
<!-- </el-switch>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="条件组表达式">-->
|
||||
<!-- <el-input v-model="config.expression" placeholder="输入条件组关系表达式 &为与,|为或"/>-->
|
||||
<!-- <span class="item-desc">使用表达式构建复杂逻辑,例如: (A & B) | C</span>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
<div>
|
||||
<el-button type="primary" icon="Plus" style="margin: 0 15px 15px 0" round
|
||||
@click="addConditionGroup">
|
||||
添加条件组
|
||||
</el-button>
|
||||
<span class="item-desc">只有必填选项才能作为审批条件</span>
|
||||
</div>
|
||||
<!-- <div>-->
|
||||
<!-- <el-button type="primary" icon="Plus" style="margin: 0 15px 15px 0" round-->
|
||||
<!-- @click="addConditionGroup">-->
|
||||
<!-- 添加条件组-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <span class="item-desc">只有必填选项才能作为审批条件</span>-->
|
||||
<!-- </div>-->
|
||||
<group-item/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {defineProps, watch,computed} from "vue";
|
||||
|
||||
import {defineProps, computed} from "vue";
|
||||
import {useProcessStore} from "@/stores/processStore.js";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -45,18 +44,7 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
const processStore = useProcessStore();
|
||||
|
||||
const tableData = ref([]);
|
||||
const isIndeterminate = ref(false);
|
||||
const permSelect = ref("");
|
||||
const checkStatus = reactive({
|
||||
readOnly: true,
|
||||
editable: false,
|
||||
hide: false
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
const init = () => {
|
||||
let oldPermMap = new Map()
|
||||
@@ -66,7 +54,7 @@ const init = () => {
|
||||
}
|
||||
}
|
||||
processStore.getSelectedNode().props.formPerms = [];
|
||||
formPermsLoad(oldPermMap, processStore.getDesign().formItems);
|
||||
formPermsLoadMosr(oldPermMap, processFromPerms.value);
|
||||
};
|
||||
|
||||
const formPerms = computed(() => {
|
||||
@@ -81,12 +69,39 @@ const formItems = computed(() => {
|
||||
return processStore.getDesign().formItems;
|
||||
});
|
||||
|
||||
const processFromPerms = computed(() => {
|
||||
return processStore.getDesign().processFromPerms;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const allSelect = (type) => {
|
||||
permSelect.value = type;
|
||||
formPerms.value.forEach(f => f.perm = type);
|
||||
};
|
||||
const formPermsLoadMosr = (oldPermMap, perms) => {
|
||||
|
||||
perms.forEach(perm =>{
|
||||
//刷新名称
|
||||
let old = oldPermMap.get(perm.id)
|
||||
if (old) {
|
||||
old.title = perm.title;
|
||||
old.required = perm.required;
|
||||
formPerms.value.push(old);
|
||||
} else {
|
||||
formPerms.value.push({
|
||||
id: perm.id, //todo ,id 就是字段名称
|
||||
title: perm.title,
|
||||
required: perm.required,
|
||||
perm: nowNode.value.type === "ROOT" ? "E" : "R"
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//todo 初始化表单权限的位置,表单字段信息放在config配置中心
|
||||
const formPermsLoad = (oldPermMap, forms) => {
|
||||
forms.forEach(form => {
|
||||
if (form.name === "SpanLayout") {
|
||||
@@ -100,7 +115,7 @@ const formPermsLoad = (oldPermMap, forms) => {
|
||||
formPerms.value.push(old);
|
||||
} else {
|
||||
formPerms.value.push({
|
||||
id: form.id,
|
||||
id: form.id, //todo ,id 就是字段名称
|
||||
title: form.title,
|
||||
required: form.props.required,
|
||||
perm: nowNode.type === "ROOT" ? "E" : "R"
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
<template>
|
||||
<el-tabs v-model="active" v-if="visible && name && formConfig.length > 0">
|
||||
<el-tab-pane :label="name" name="properties">
|
||||
<component :is="com" :config="selectNode.props" @initRender="emit('initRender')"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="表单权限设置" name="permissions">
|
||||
<form-authority-config :node-type="selectNode.type"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-else>
|
||||
<!-- <el-tabs v-model="active" v-if="visible && name && formConfig.length > 0">-->
|
||||
<el-tabs v-model="active" v-if="visible && name">
|
||||
<el-tab-pane :label="name" name="properties">
|
||||
<component :is="com" :config="selectNode.props" @initRender="emit('initRender')"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="表单权限设置" name="permissions">
|
||||
<form-authority-config :node-type="selectNode.type"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-else>
|
||||
<component :is="com" :config="selectNode.props" @initRender="emit('initRender')"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -21,7 +22,8 @@ import CcNode from './CcNodeConfig.vue'
|
||||
import Condition from './ConditionNodeConfig.vue'
|
||||
import Trigger from './TriggerNodeConfig.vue'
|
||||
import {useProcessStore} from '@/stores/processStore.js'
|
||||
import {computed,defineEmits} from 'vue'
|
||||
import {computed, defineEmits} from 'vue'
|
||||
|
||||
const emit = defineEmits()
|
||||
|
||||
const processStore = useProcessStore()
|
||||
@@ -31,9 +33,9 @@ const selectNode = computed(() => {
|
||||
})
|
||||
|
||||
|
||||
const formConfig = computed(() => {
|
||||
return processStore.getDesign().formItems
|
||||
})
|
||||
// const formConfig = computed(() => {
|
||||
// return processStore.getDesign().formItems
|
||||
// })
|
||||
|
||||
|
||||
const com = ref()
|
||||
@@ -41,10 +43,11 @@ const active = ref('properties')
|
||||
const visible = ref(false)
|
||||
|
||||
|
||||
const name = computed(()=>{
|
||||
const name = computed(() => {
|
||||
switch (processStore.getSelectedNode().type) {
|
||||
case 'ROOT':
|
||||
return '设置发起人';
|
||||
// return '设置发起人';
|
||||
return '节点设置';
|
||||
case 'APPROVAL':
|
||||
return '设置审批人';
|
||||
case 'CC':
|
||||
@@ -56,7 +59,6 @@ const name = computed(()=>{
|
||||
|
||||
|
||||
const init = () => {
|
||||
console.log(processStore.getSelectedNode().type)
|
||||
switch (processStore.getSelectedNode().type) {
|
||||
case 'APPROVAL' :
|
||||
com.value = Approval;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<p class="desc">选择能发起该审批的人员/部门,不选则默认开放给所有人</p>
|
||||
<el-button size="mini" @click="selectOrg" icon="el-icon-plus" type="primary" round>请选择</el-button>
|
||||
<org-items v-model="select"/>
|
||||
<org-picker title="请选择可发起本审批的人员/部门" multiple ref="orgPicker" :selected="select" @ok="selected"/>
|
||||
</div>
|
||||
<!-- <div>-->
|
||||
<!-- <p class="desc">选择能发起该审批的人员/部门,不选则默认开放给所有人</p>-->
|
||||
<!-- <el-button size="mini" @click="selectOrg" icon="el-icon-plus" type="primary" round>请选择</el-button>-->
|
||||
<!-- <org-items v-model="select"/>-->
|
||||
<!-- <org-picker title="请选择可发起本审批的人员/部门" multiple ref="orgPicker" :selected="select" @ok="selected"/>-->
|
||||
<!-- </div>-->
|
||||
无需设置
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import Node from './Node.vue'
|
||||
import {computed, defineExpose} from 'vue'
|
||||
import {Stamp} from '@element-plus/icons-vue'
|
||||
|
||||
const emit = defineEmits(['insertNode', 'selected', 'delNode'])
|
||||
const props = defineProps({
|
||||
config: {
|
||||
@@ -80,7 +81,7 @@ const content = computed(() => {
|
||||
if (text && text.title) {
|
||||
return `表单(${text.title})内的人员`
|
||||
} else {
|
||||
return '该表单已被移除😥'
|
||||
return '该表单已被移除'
|
||||
}
|
||||
}
|
||||
case "ROLE":
|
||||
@@ -91,8 +92,10 @@ const content = computed(() => {
|
||||
} else {
|
||||
return '指定角色(未设置)'
|
||||
}
|
||||
case "MATRIX_APPROVAL":
|
||||
return '矩阵审批'
|
||||
default:
|
||||
return '未知设置项😥'
|
||||
return '未知设置项'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
<component :is="headerIcon"/>
|
||||
</el-icon>
|
||||
<ellipsis class="name" hover-tip :content="title"/>
|
||||
<el-icon v-if="!isRoot && designState" size="20" style="float:right;cursor: pointer" @click.stop="emit('delNode')">
|
||||
<el-icon v-if="!isRoot && designState" size="20" style="float:right;cursor: pointer"
|
||||
@click.stop="emit('delNode')">
|
||||
<Close/>
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -16,20 +17,17 @@
|
||||
</el-icon>
|
||||
<template v-if="selectUser.show && mode === 'view'">
|
||||
<div class="avatar_button">
|
||||
<avatar-ellipsis :row="3" v-if="userInfo.length > 0" :user-info="userInfo"/>
|
||||
<avatar-ellipsis :row="3" v-if="userInfo.length > 0" :mode="mode" :user-info="userInfo"/>
|
||||
<el-button type="primary" :icon="Plus" circle/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="showAvatar">
|
||||
<span class="placeholder" v-if="userInfo.length === 0">{{ placeholder }}</span>
|
||||
<div v-else v-for="item in userInfo" class="circle-user">
|
||||
<span >{{item.name}}</span>
|
||||
</div>
|
||||
<!-- <avatar-ellipsis :row="3" :user-info="userInfo"/>-->
|
||||
<avatar-ellipsis :row="3" v-if="userInfo.length > 0" :user-info="userInfo"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="placeholder" v-if="(content || '').trim() === ''">{{ placeholder }}</span>
|
||||
<ellipsis :row="3" :content="content" v-else/>
|
||||
<ellipsis :row="3" :content="content" :mode="mode" v-else/>
|
||||
</template>
|
||||
</div>
|
||||
<div class="node-error" v-if="showError">
|
||||
@@ -43,9 +41,9 @@
|
||||
<div class="node-footer">
|
||||
<div v-if="merge" class="branch-merge">
|
||||
<svg-icon name="fenzhi" :class-name="'fen-icon'"/>
|
||||
<!-- <img data-v-1e7b1da5=""-->
|
||||
<!-- src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABXlJREFUeF7tmm2IVGUUx3/nLkQUqxmkpAVhSPUllZX8EEGhvVgZQWCU6wcpsqi2mXtnoaBwoqLCufeO9oJYUJQiFZWlZPQCfYiIXkylstTyS1oWWeYWCe6cuLsz7t3r3Ll3du6907oz35bnPM9z/r895zznmWeECf6RCa6fDoBOBExwAp0UmOAB0CmCnRTopECbCZi2nivK1CMD7FpXlH+ydqctKZBz9QyjwkqFG4HzfKK/0gpvl/ulmBWIzAHkVmlRDFY2EihwwLFkRhYQxgzAtHW2CpcBc4CpOsg26eK7yVPYVFwu/9ZzPufq2VLhQBxhAk85lvSF2Y5l/3prjQlAvqR3IjwJTKqz6DeGssQuyLfBsbyjz6PcFgeAZyOwzLFk/QnrjHH/RACYtj6ncHuUCDWYXs7Lz367XEn3inB+1NzauMLGsiW3+u1b2b9lAH22LuiCD2IJED5yTbmiZpt3dAbKT7Hmjhjtdi25oPZnK/uH7dtUCpi2vqVwQ1wRWuHhWkW3StpTEb6IO3fIThhwTemuzWll/0QA5G39FTgrtghhs2vKELA7inra6d38HXvusOEnriWXHo+iFvZvGUDfap3VdYzdzQgIHmd5W7cBc2Ovoax1C3KXZ5/E/i3VgCQciNMD+J1Ug55yXjxo7QfgOdFKCvjyeL/C9MgoEBa5przrt0ti/+C+mRVB/8amrWsU7m2Ql/c5lqwJjre9CDZ1DMFnriXzw0SatvZW4FqBW6o2vwGvCGxyLPmw3rym9g8cwy0XQV8Ix2qEgH0C1ziWNCyceVu1uvZrriVLGqVGsainHO7mRyDynlCvEWupCI7Kxcat6BFg+OwW9ohyfSMIcQF44v/sZovAlRH1I7QVTwyAt1Cjy8hfh9hYvepGQogDoI74HYbSXzHwusTYl7FEAURVcdPWN+NAiAJQTzzCda4p+6N8iDPe1CkQZ8FAtY+E0AhA2uKHszTlT1QkhAHIQnwmAKr1IjQS6gHISnxmABpBCALIUnymAMIgKHxf6wMmH6E3cNTtSLLgZXoKNOgAR6UDyqyq7esKk3znfOriM48AXzc5AmGE1EFgWvXPTMS3DcAJ6TA6XDIT31YAoRCEc5JqcuKc8Kn3AVFO+E4BryvJVHzbI8BzwAdgi2vJ4ihgSY//nyIg8jqctPi2RYBp61wV5qsyR2BFVdhBhBe0wtdisNU15VAagoNrZh4BOVsfFcVCODVUoLBn6E2hIBvShpApgLyt3nvhRXFFCWxwLOmNaz8Wu8wA5G31ntQWNOukwD2OJc80Oy+ufSYAciVdJsJLcZ0K2nV1MbuUk51jnd9oXuoACmW9eHCQj49/T+j3RtiJslPgFxXmoVxe11nhPdeUq8clANPWPoXVQef9D6e1saEHVINHUBYF7Q1lnl2QL5OGkHoE5G19GRhVyBQ+L1tyST0xoa/Iygq3IOvGI4BdwIWjHBeecE15IExM3tYfgJmBOetcU2o9Q2IcsoiAw8Gf0qhyU7kgb4QCcPRTlNGvSspmtzD81J7kJ30AJX0fYeHo2seLjiXLG0TA78CZ/nGFB8uWPJakeG+t9AE4+jjK/XGLWtgTusBix5It4w5ArqRLRTjhl14IW40KD/kre66ki0R4p57IrgozS/2yb9wByDvqhbKX07Xv/oIavMfOP6pFb0pdgcqrbkFuTlp8JingbRIaBfEUHUOYltbtMPUaUNNo2rpeYWk8zSNWqvSmeSvMDIAnybT1boWnY0I4aigL7YJ4bXRqn0wBeCqG7gYVVqFcFapKWXt0gP5nizKQmvLqwpkDqAkaanmhB4MelOkI27XCDjHY7pqyN23htfXbBiArgVH7dABEETrZxzsRcLL/h6P0/Qc1qphfvB2K3wAAAABJRU5ErkJggg=="-->
|
||||
<!-- alt="">-->
|
||||
<!-- <img data-v-1e7b1da5=""-->
|
||||
<!-- src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABXlJREFUeF7tmm2IVGUUx3/nLkQUqxmkpAVhSPUllZX8EEGhvVgZQWCU6wcpsqi2mXtnoaBwoqLCufeO9oJYUJQiFZWlZPQCfYiIXkylstTyS1oWWeYWCe6cuLsz7t3r3Ll3du6907oz35bnPM9z/r895zznmWeECf6RCa6fDoBOBExwAp0UmOAB0CmCnRTopECbCZi2nivK1CMD7FpXlH+ydqctKZBz9QyjwkqFG4HzfKK/0gpvl/ulmBWIzAHkVmlRDFY2EihwwLFkRhYQxgzAtHW2CpcBc4CpOsg26eK7yVPYVFwu/9ZzPufq2VLhQBxhAk85lvSF2Y5l/3prjQlAvqR3IjwJTKqz6DeGssQuyLfBsbyjz6PcFgeAZyOwzLFk/QnrjHH/RACYtj6ncHuUCDWYXs7Lz367XEn3inB+1NzauMLGsiW3+u1b2b9lAH22LuiCD2IJED5yTbmiZpt3dAbKT7Hmjhjtdi25oPZnK/uH7dtUCpi2vqVwQ1wRWuHhWkW3StpTEb6IO3fIThhwTemuzWll/0QA5G39FTgrtghhs2vKELA7inra6d38HXvusOEnriWXHo+iFvZvGUDfap3VdYzdzQgIHmd5W7cBc2Ovoax1C3KXZ5/E/i3VgCQciNMD+J1Ug55yXjxo7QfgOdFKCvjyeL/C9MgoEBa5przrt0ti/+C+mRVB/8amrWsU7m2Ql/c5lqwJjre9CDZ1DMFnriXzw0SatvZW4FqBW6o2vwGvCGxyLPmw3rym9g8cwy0XQV8Ix2qEgH0C1ziWNCyceVu1uvZrriVLGqVGsainHO7mRyDynlCvEWupCI7Kxcat6BFg+OwW9ohyfSMIcQF44v/sZovAlRH1I7QVTwyAt1Cjy8hfh9hYvepGQogDoI74HYbSXzHwusTYl7FEAURVcdPWN+NAiAJQTzzCda4p+6N8iDPe1CkQZ8FAtY+E0AhA2uKHszTlT1QkhAHIQnwmAKr1IjQS6gHISnxmABpBCALIUnymAMIgKHxf6wMmH6E3cNTtSLLgZXoKNOgAR6UDyqyq7esKk3znfOriM48AXzc5AmGE1EFgWvXPTMS3DcAJ6TA6XDIT31YAoRCEc5JqcuKc8Kn3AVFO+E4BryvJVHzbI8BzwAdgi2vJ4ihgSY//nyIg8jqctPi2RYBp61wV5qsyR2BFVdhBhBe0wtdisNU15VAagoNrZh4BOVsfFcVCODVUoLBn6E2hIBvShpApgLyt3nvhRXFFCWxwLOmNaz8Wu8wA5G31ntQWNOukwD2OJc80Oy+ufSYAciVdJsJLcZ0K2nV1MbuUk51jnd9oXuoACmW9eHCQj49/T+j3RtiJslPgFxXmoVxe11nhPdeUq8clANPWPoXVQef9D6e1saEHVINHUBYF7Q1lnl2QL5OGkHoE5G19GRhVyBQ+L1tyST0xoa/Iygq3IOvGI4BdwIWjHBeecE15IExM3tYfgJmBOetcU2o9Q2IcsoiAw8Gf0qhyU7kgb4QCcPRTlNGvSspmtzD81J7kJ30AJX0fYeHo2seLjiXLG0TA78CZ/nGFB8uWPJakeG+t9AE4+jjK/XGLWtgTusBix5It4w5ArqRLRTjhl14IW40KD/kre66ki0R4p57IrgozS/2yb9wByDvqhbKX07Xv/oIavMfOP6pFb0pdgcqrbkFuTlp8JingbRIaBfEUHUOYltbtMPUaUNNo2rpeYWk8zSNWqvSmeSvMDIAnybT1boWnY0I4aigL7YJ4bXRqn0wBeCqG7gYVVqFcFapKWXt0gP5nizKQmvLqwpkDqAkaanmhB4MelOkI27XCDjHY7pqyN23htfXbBiArgVH7dABEETrZxzsRcLL/h6P0/Qc1qphfvB2K3wAAAABJRU5ErkJggg=="-->
|
||||
<!-- alt="">-->
|
||||
</div>
|
||||
<div class="btn">
|
||||
<insert-button v-if="designState" @insertNode="type => emit('insertNode', type)"/>
|
||||
@@ -62,7 +60,7 @@ import InsertButton from '../common/InsertButton.vue'
|
||||
import Ellipsis from '../common/Ellipsis.vue'
|
||||
import AvatarEllipsis from '../common/AvatarEllipsis.vue'
|
||||
import SvgIcon from '@/components/svgIcon/index.vue'
|
||||
import {Close, Warning, Plus} from '@element-plus/icons-vue'
|
||||
import {Close, Warning, Plus, Check, More} from '@element-plus/icons-vue'
|
||||
|
||||
const emit = defineEmits(['insertNode'])
|
||||
const props = defineProps({
|
||||
@@ -154,7 +152,16 @@ const props = defineProps({
|
||||
const designState = computed(() => {
|
||||
return props.mode === 'design'
|
||||
})
|
||||
|
||||
const getState = (state) => {
|
||||
switch (state) {
|
||||
case 'finish':
|
||||
return 'check'
|
||||
case 'UNACTIVATED':
|
||||
return 'more'
|
||||
case 'RUNNING':
|
||||
return 'loading'
|
||||
}
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
// let userInfo = this.$store.state.selectUserMap.get(this.nodeId);
|
||||
@@ -176,15 +183,6 @@ const init = () => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.circle-user{
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #ACACAC;
|
||||
}
|
||||
.root {
|
||||
&:before {
|
||||
display: none !important;
|
||||
|
||||
@@ -18,7 +18,6 @@ export default defineConfig({
|
||||
AutoImport({
|
||||
//自动导入vue相关函数
|
||||
imports: ['vue','vue-router'],
|
||||
|
||||
resolvers: [
|
||||
ElementPlusResolver(),
|
||||
//自动导入图标组件
|
||||
@@ -69,12 +68,13 @@ export default defineConfig({
|
||||
strictPort: false,
|
||||
open: true,
|
||||
proxy: {
|
||||
// '/api/admin': {
|
||||
// target: 'http://dev-mosr.frp.feashow.cn/',
|
||||
// // target: 'http://192.168.31.175:8000',
|
||||
// changeOrigin: true,
|
||||
// rewrite: (path) => path.replace(/^\/api/, '')
|
||||
// },
|
||||
'/api/workflow': {
|
||||
target: 'http://frp.feashow.cn:31800/',
|
||||
// target: 'http://clay.frp.feashow.cn/',
|
||||
// target: 'http://192.168.31.175:8000',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '')
|
||||
},
|
||||
'/api': {
|
||||
target: 'http://mosr.feashow.cn',
|
||||
changeOrigin: true,
|
||||
|
||||
Reference in New Issue
Block a user