Merge pull request 'master' (#378) from master into prod

Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/378
This commit is contained in:
2024-06-21 10:36:16 +00:00
14 changed files with 193 additions and 140 deletions

View File

@@ -15,3 +15,17 @@ export const uploadFileList = (data) => {
data: data
});
};
export const searchImplementationFileList = (params) => {
return request({
url: '/workflow/mosr/attachment/implementation/list',
method: "get",
params: params
});
};
export const switchAttachmentState = (data) => {
return request({
url: '/workflow/mosr/project/filing/attachment/switch',
method: "post",
data
});
};

View File

@@ -3,7 +3,7 @@
<slot name="pre"></slot>
<div class="user-audit">
<div class="circle-user">
<Tooltip :content="user.name" placement="bottom-start" width="45"/>
<Tooltip :content="user.name" placement="bottom-start" width="45px"/>
<div v-if="user.icon"
class="el-timeline-item__node" :style="{
backgroundColor: user.color

View File

@@ -52,7 +52,7 @@ const props = defineProps({
},
uploadState: {
type: Boolean,
default: true
default: false
},
loading: {
type: Boolean,

View File

@@ -5,7 +5,7 @@
placement="bottom-start"
:disabled="isShow"
>
<div :class="lines?'content-lines':'content'" :style="{width: props.width+'px'}" @mouseover="isShowTooltip">
<div :class="lines?'content-lines':'content'" :style="{width: props.width}" @mouseover="isShowTooltip">
<span ref="contentRef">
<slot name="content">{{ props.content }}</slot>
</span>
@@ -17,10 +17,12 @@ const props = defineProps({
content: {
type: String,
default: ''
}, width: {
},
width: {
type: String,
default: ''
}, lines: {
default: '100%'
},
lines: {
type: Boolean,
default: false
}
@@ -40,6 +42,7 @@ const isShowTooltip = () => {
overflow: hidden;
}
.content-lines{
word-break:break-all;
overflow:hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;

View File

@@ -17,7 +17,10 @@
<ul>
<li>主次账号切换</li>
<li class="avatar-li" v-for="item in accountList" @click="accountChange(item.userId)">
<el-avatar><span>{{ item.nickName }}</span></el-avatar>
<el-badge :value="item.taskCount" v-if="item.taskCount!==0">
<el-avatar>{{ item.nickName }}</el-avatar>
</el-badge>
<el-avatar v-else>{{ item.nickName }}</el-avatar>
<div class="right-li">
<div class="name-line">
<span v-if="item.accountType==='0'" class="zhu"></span>
@@ -66,6 +69,7 @@ import {useTagsView} from '@/stores/tagsview';
import {getUserAccount} from "@/api/user/user";
import {switchAccount} from "@/api/login";
import {setToken} from "../../utils/auth";
import {ElNotification} from "element-plus";
const authStore = useAuthStore()
const permisstionStore = usePermisstionStroe()
@@ -89,7 +93,13 @@ const nullBlockClick = () => {
}
const handleVisitedP = () => {
getUserAccount().then(res => {
console.log(res)
if (res.code !== 1000) {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
}
accountList.value = res.data
nextTick(() => {
visitedP.value = !visitedP.value
@@ -129,13 +139,23 @@ const handleLogout = () => {
:deep(.el-avatar--circle) {
display: inline-block;
line-height: 40px;
margin-right: 10px;
margin-right: 14px;
background-color: #8a7243;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
:deep(.el-badge) {
padding: 0 2px;
}
:deep(.el-badge__content.is-fixed) {
position: absolute;
right: 26px;
top: 2px;
}
.navbar {
height: 65px;
padding: 0 15px 0 0;

View File

@@ -20,7 +20,7 @@ const router = useRouter()
const activeName = ref('50')
const attachment = ref({})
const loading = ref(false)
const uploadState = ref(true)
const uploadState = ref(false)
const fileList = ref([])
const projectId = ref(route.query.id)
const requirementId = ref(route.query.requirementId)

View File

@@ -10,6 +10,8 @@
<script setup lang="jsx">
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
import {toThousands} from '@/utils/changePrice.js'
import {switchAttachmentState} from "@/api/project-manage/attachment";
import {ElMessageBox} from "element-plus";
const router = useRouter()
const shortcuts = [
@@ -244,6 +246,12 @@ const tableConfig = reactive({
if (buttons.has("edit")) {
btn.push({label: '编辑', prem: ['project:management:filing:conclusion'], func: () => handleEdit(row), type: 'primary'})
}
if (buttons.has("openFileSwitch")) {
btn.push({label: '开启上传', prem: ['project:management:filing:conclusion'], func: () => handleOpenUpload(row,true), type: 'primary'})
}
if (buttons.has("closeFileSwitch")) {
btn.push({label: '关闭上传', prem: ['project:management:filing:conclusion'], func: () => handleOpenUpload(row,false), type: 'primary'})
}
return (
<div style={{width: '100%'}}>
{
@@ -316,4 +324,19 @@ const handleEdit = (row) => {
}
})
}
const handleOpenUpload=(row,flag)=>{
ElMessageBox.confirm(`是否确认${flag?'开启':'关闭'}上传文件?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let params={
open: flag,
projectId: row.projectId
}
switchAttachmentState(params).then(res=>{
tableIns.value.refresh()
})
})
}
</script>

View File

@@ -29,15 +29,14 @@
<script setup lang="jsx">
import {downloadFile} from "@/api/project-demand";
import {searchFileList} from "@/api/project-manage/attachment.js";
import {getTags} from "@/api/project-manage";
import {ElLoading, ElNotification} from "element-plus";
import {computed, ref} from "vue";
import {ElNotification} from "element-plus";
import {getBaseInfoApi} from "@/components/steps/api";
import {searchImplementationFileList} from "@/api/project-manage/attachment";
const route = useRoute()
const router = useRouter()
const uploadState = ref(true)
const uploadState = ref(false)
const attachment = reactive({
tag: ''
})
@@ -140,7 +139,7 @@ const handleSearch = () => {
})
params.tag = attachment.tag
}
searchFileList(params).then(res => {
searchImplementationFileList(params).then(res => {
showTable.value = false
if (res.code === 1000) {
otherFileList.value = res.data.fileList

View File

@@ -59,7 +59,7 @@ const getInfo = async () => {
const {code, data, msg} = await getPhaseDetail(projectId)
if (code === 1000) {
summaryData.value = data;
copyName.value= data.formData.userInfoList.map(item=>item.name).join('')
copyName.value= data.formData.userInfoList?.map(item=>item.name).join('')
loading.value = false
processStore.setDesign(data)
processStore.runningList.value = data.runningList;

View File

@@ -8,6 +8,9 @@
size="large"
placement="top">
<el-card>
<div>
当前节点: {{ operation.operationName }}
</div>
<div class="card">
<div v-for="(user,index) in operation.userInfo" :key="index" class="avatar_name">
<div>
@@ -17,15 +20,15 @@
<div>
<div class="remark">{{ operation.remark }}</div>
<div>
<div>{{ operation.operationName }}</div>
<div>审批人</div>
<div>{{ user.name }}</div>
</div>
<div v-if="user.auditOpinion">
<div style="margin-bottom: 10px;color: #909399">{{ user.operationTime }}</div>
<Tooltip :content="user.auditOpinion" placement="bottom-start" width="140" :lines="true"/>
<el-text v-text="user.auditOpinion" style="word-break: break-all">
</el-text>
</div>
</div>
</div>
</div>
</el-card>
@@ -270,9 +273,10 @@ init()
> div:first-child {
display: flex;
width: 200px;
> span {
width: 100px;
color: #2a99ff;
margin-left: 10px;
margin-right: 20px;
@@ -307,20 +311,21 @@ init()
right: 1px;
}
//.username {
// //width: 90px;
// margin-top: 10px;
// background: #f5f5f5;
// padding: 5px;
//
// .el-tooltip__trigger {
// width: 90px;
// text-align: center;
// //padding-top: 2px;
// //text-align: center;
// text-overflow: ellipsis;
// white-space: nowrap;
// overflow: hidden
// }
//}
.username {
//width: 90px;
margin-top: 10px;
background: #f5f5f5;
padding: 12px;
overflow: hidden;
//.el-tooltip__trigger {
// width: 90px;
// text-align: center;
// //padding-top: 2px;
// //text-align: center;
// text-overflow: ellipsis;
// white-space: nowrap;
// overflow: hidden
//}
}
</style>

View File

@@ -1,118 +1,119 @@
//审批节点默认属性
export const APPROVAL_PROPS = {
assignedType: "ASSIGN_USER", //审批类型
mode: "AND", //会签模式
sign: false, //是否签字
headerBgc: '#ff943e', //节点背景颜色
nobody: { //没有审批的的时候需要的操作
handler: "TO_PASS", //操作
assignedUser: [] //审批人列表
assignedType: "ASSIGN_USER", //审批类型
mode: "AND", //会签模式
sign: false, //是否签字
headerBgc: '#ff943e', //节点背景颜色
nobody: { //没有审批的的时候需要的操作
handler: "TO_PASS", //操作
assignedUser: [] //审批人列表
},
matrixApproval: true,
timeLimit: { //边界事件
timeout: { //超时提醒时间
unit: "H",
value: 0
},
timeLimit: { //边界事件
timeout: { //超时提醒时间
unit: "H",
value: 0
},
handler: { //超时提醒触发时候的操作
type: "REFUSE", //操作
notify: {
once: true, //是否循环
hour: 1
}
}
},
assignedUser: [], // 审批人列表
formPerms: [], //表单权限
selfSelect: { //用户自选
multiple: false //用户自选时是否是多选
},
leaderTop: { //领导
endCondition: "TOP",
endLevel: 1,
},
leader: { //第几级领导
level: 1
},
listener:{
state: false,
list:[]
},
roleList: [], //角色列
refuse: { //拒绝的操作
type: 'TO_END', //驳回规则 TO_END TO_NODE TO_BEFORE
target: '' //驳回到指定ID的节点
},
formUser: '' //表单用户
handler: { //超时提醒触发时候的操作
type: "REFUSE", //操作
notify: {
once: true, //是否循环
hour: 1
}
}
},
assignedUser: [], // 审批人列表
formPerms: [], //表单权限
selfSelect: { //用户自选
multiple: false //用户自选时是否是多选
},
leaderTop: { //领导
endCondition: "TOP",
endLevel: 1,
},
leader: { //第几级领导
level: 1
},
listener: {
state: false,
list: []
},
roleList: [], //角色列表
refuse: { //拒绝的操作
type: 'TO_END', //驳回规则 TO_END TO_NODE TO_BEFORE
target: '' //驳回到指定ID的节点
},
formUser: '' //表单用户
}
//根节点默认属性
export const ROOT_PROPS = {
assignedUser: [], //审批人
formPerms: [] //表单权限
assignedUser: [], //审批人
formPerms: [] //表单权限
}
//条件节点默认属性
export const CONDITION_PROPS = {
groupsType: "OR", //条件组逻辑关系 OR、AND
groups: [
{
groupType: "AND", //条件组内条件关系 OR、AND
cids: [], //条件ID集合
conditions: [] //组内子条件
}
],
expression: "" //自定义表达式,灵活构建逻辑关系
groupsType: "OR", //条件组逻辑关系 OR、AND
groups: [
{
groupType: "AND", //条件组内条件关系 OR、AND
cids: [], //条件ID集合
conditions: [] //组内子条件
}
],
expression: "" //自定义表达式,灵活构建逻辑关系
}
//抄送节点默认属性
export const CC_PROPS = {
shouldAdd: false,
assignedUser: [],
formPerms: []
shouldAdd: false,
assignedUser: [],
formPerms: []
}
//触发器节点默认属性
export const TRIGGER_PROPS = {
type: 'WEBHOOK',
http: {
method: 'GET', //请求方法 支持GET/POST
url: '', //URL地址可以直接带参数
headers: [ //http header
{
name: '',
isField: true,
value: '' //支持表达式 ${xxx} xxx为表单字段id
}
],
contentType: 'FORM', //请求参数类型
params: [ //请求参数
{
name: '',
isField: true, //是表单字段还是自定义
value: '' //支持表达式 ${xxx} xxx为表单字段id
}
],
retry: 1,
handlerByScript: false,
success: 'function handlerSuccess(res) {\n return {\n state: true, \n msg: "请求成功!" \n };\n}',
fail: 'function handlerFail(res) {\n return {\n state: true, \n msg: "请求失败!" \n };\n}'
},
email: {
subject: '',
to: [],
cc: [],
content: ''
}
type: 'WEBHOOK',
http: {
method: 'GET', //请求方法 支持GET/POST
url: '', //URL地址可以直接带参数
headers: [ //http header
{
name: '',
isField: true,
value: '' //支持表达式 ${xxx} xxx为表单字段id
}
],
contentType: 'FORM', //请求参数类型
params: [ //请求参数
{
name: '',
isField: true, //是表单字段还是自定义
value: '' //支持表达式 ${xxx} xxx为表单字段id
}
],
retry: 1,
handlerByScript: false,
success: 'function handlerSuccess(res) {\n return {\n state: true, \n msg: "请求成功!" \n };\n}',
fail: 'function handlerFail(res) {\n return {\n state: true, \n msg: "请求失败!" \n };\n}'
},
email: {
subject: '',
to: [],
cc: [],
content: ''
}
}
//延时节点默认属性
export const DELAY_PROPS = {
type: "FIXED", //延时类型 FIXED:到达当前节点后延时固定时长 、AUTO:延时到 dateTime设置的时间
time: 0, //延时时间
unit: "M", //时间单位 D天 H小时 M分钟
dateTime: "" //如果当天没有超过设置的此时间点,就延时到这个指定的时间,到了就直接跳过不延时
type: "FIXED", //延时类型 FIXED:到达当前节点后延时固定时长 、AUTO:延时到 dateTime设置的时间
time: 0, //延时时间
unit: "M", //时间单位 D天 H小时 M分钟
dateTime: "" //如果当天没有超过设置的此时间点,就延时到这个指定的时间,到了就直接跳过不延时
}
export default {
APPROVAL_PROPS, CC_PROPS, DELAY_PROPS, CONDITION_PROPS, ROOT_PROPS, TRIGGER_PROPS
APPROVAL_PROPS, CC_PROPS, DELAY_PROPS, CONDITION_PROPS, ROOT_PROPS, TRIGGER_PROPS
}

View File

@@ -191,17 +191,6 @@ const loadInitFrom = () => {
})
}
const getRandomId = () => {
let d = new Date().getTime()
// x 是 0-9 或 a-f 范围内的一个32位十六进制数
let id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0
d = Math.floor(d / 16)
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
})
return id
}
const getProcessInfo = async () => {
getProcessDefinitionInfo(params.deploymentId).then(res => {
ElNotification({

View File

@@ -7,7 +7,7 @@
<div v-for="(user,index) in userInfo" :key="index" class="avatar_name">
<div class="user">
<div class="circle-user">
<Tooltip :content="user.name" placement="bottom-start" width="45">
<Tooltip :content="user.name" placement="bottom-start" width="45px">
</Tooltip>
</div>
<div v-if="user.icon && mode === 'preview'"

View File

@@ -273,7 +273,6 @@ const props = defineProps({
const nodeProps = computed(() => {
processStore.getSelectedNode().props.matrixApproval=true
return processStore.getSelectedNode().props;
})