Merge branch 'dev' of https://gitee.com/yudaocode/yudao-ui-admin-vue3 into dev
This commit is contained in:
@ -185,7 +185,7 @@ const { push } = useRouter()
|
||||
const permissionStore = usePermissionStore()
|
||||
const loginLoading = ref(false)
|
||||
const verify = ref()
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字 pictureWord 文字验证码
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)
|
||||
|
||||
|
||||
@ -143,7 +143,7 @@ const iconCircleCheck = useIcon({ icon: 'ep:circle-check' })
|
||||
const { validForm } = useFormValid(formSmsResetPassword)
|
||||
const { handleBackLogin, getLoginState, setLoginState } = useLoginState()
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.RESET_PASSWORD)
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字 pictureWord 文字验证码
|
||||
|
||||
const validatePass2 = (_rule, value, callback) => {
|
||||
if (value === '') {
|
||||
|
||||
@ -47,10 +47,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col
|
||||
:span="24"
|
||||
class="px-10px mt-[-20px] mb-[-20px]"
|
||||
>
|
||||
<el-col :span="24" class="px-10px mt-[-20px] mb-[-20px]">
|
||||
<el-form-item>
|
||||
<el-row justify="space-between" style="width: 100%">
|
||||
<el-col :span="6">
|
||||
@ -177,7 +174,7 @@ const permissionStore = usePermissionStore()
|
||||
const redirect = ref<string>('')
|
||||
const loginLoading = ref(false)
|
||||
const verify = ref()
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字 pictureWord 文字验证码
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)
|
||||
|
||||
|
||||
@ -119,7 +119,7 @@ const permissionStore = usePermissionStore()
|
||||
const redirect = ref<string>('')
|
||||
const loginLoading = ref(false)
|
||||
const verify = ref()
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字
|
||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字 pictureWord 文字验证码
|
||||
|
||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.REGISTER)
|
||||
|
||||
|
||||
@ -11,6 +11,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item class="mb-20px">
|
||||
<template #label>
|
||||
<el-text size="large" tag="b">审批人权限</el-text>
|
||||
</template>
|
||||
<div class="flex flex-col">
|
||||
<el-checkbox v-model="modelData.allowWithdrawTask" label="允许审批人撤回任务" />
|
||||
<div class="ml-22px">
|
||||
<el-text type="info"> 审批人可撤回正在审批节点的前一节点 </el-text>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modelData.processIdRule" class="mb-20px">
|
||||
<template #label>
|
||||
<el-text size="large" tag="b">流程编码</el-text>
|
||||
@ -422,6 +433,9 @@ const initData = () => {
|
||||
if (modelData.value.taskAfterTriggerSetting) {
|
||||
taskAfterTriggerEnable.value = true
|
||||
}
|
||||
if (modelData.value.allowWithdrawTask) {
|
||||
modelData.value.allowWithdrawTask = false
|
||||
}
|
||||
}
|
||||
defineExpose({ initData })
|
||||
|
||||
|
||||
@ -173,7 +173,8 @@ const formData: any = ref({
|
||||
summarySetting: {
|
||||
enable: false,
|
||||
summary: []
|
||||
}
|
||||
},
|
||||
allowWithdrawTask: false
|
||||
})
|
||||
|
||||
// 流程数据
|
||||
|
||||
@ -51,8 +51,10 @@
|
||||
>
|
||||
<div class="ml-10px -mt-15px -mb-35px">
|
||||
<ProcessInstanceTimeline
|
||||
ref="nextAssigneesTimelineRef"
|
||||
:activity-nodes="nextAssigneesActivityNode"
|
||||
:show-status-icon="false"
|
||||
:enable-approve-user-select="true"
|
||||
@select-user-confirm="selectNextAssigneesConfirm"
|
||||
/>
|
||||
</div>
|
||||
@ -571,6 +573,7 @@ const approveFormRef = ref<FormInstance>()
|
||||
const signRef = ref()
|
||||
const approveSignFormRef = ref()
|
||||
const nextAssigneesActivityNode = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([]) // 下一个审批节点信息
|
||||
const nextAssigneesTimelineRef = ref() // 下一个节点审批人时间线组件的引用
|
||||
const approveReasonForm = reactive({
|
||||
reason: '',
|
||||
signPicUrl: '',
|
||||
@ -717,6 +720,10 @@ const closePopover = (type: string, formRef: FormInstance | undefined) => {
|
||||
}
|
||||
popOverVisible.value[type] = false
|
||||
nextAssigneesActivityNode.value = []
|
||||
// 清理 Timeline 组件中的自定义审批人数据
|
||||
if (nextAssigneesTimelineRef.value) {
|
||||
nextAssigneesTimelineRef.value.batchSetCustomApproveUsers({})
|
||||
}
|
||||
}
|
||||
|
||||
/** 流程通过时,根据表单变量查询新的流程节点,判断下一个节点类型是否为自选审批人 */
|
||||
@ -729,6 +736,7 @@ const initNextAssigneesFormField = async () => {
|
||||
processVariablesStr: JSON.stringify(variables)
|
||||
})
|
||||
if (data && data.length > 0) {
|
||||
const customApproveUsersData: Record<string, any[]> = {} // 用于收集需要设置到 Timeline 组件的自定义审批人数据
|
||||
data.forEach((node: any) => {
|
||||
if (
|
||||
// 情况一:当前节点没有审批人,并且是发起人自选
|
||||
@ -740,7 +748,18 @@ const initNextAssigneesFormField = async () => {
|
||||
) {
|
||||
nextAssigneesActivityNode.value.push(node)
|
||||
}
|
||||
|
||||
// 如果节点有 candidateUsers,设置到 customApproveUsers 中
|
||||
if (node.candidateUsers && node.candidateUsers.length > 0) {
|
||||
customApproveUsersData[node.id] = node.candidateUsers
|
||||
}
|
||||
})
|
||||
|
||||
// 将 candidateUsers 设置到 Timeline 组件中
|
||||
await nextTick() // 等待下一个 tick,确保 Timeline 组件已经渲染
|
||||
if (nextAssigneesTimelineRef.value && Object.keys(customApproveUsersData).length > 0) {
|
||||
nextAssigneesTimelineRef.value.batchSetCustomApproveUsers(customApproveUsersData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -803,6 +822,10 @@ const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) =>
|
||||
await TaskApi.approveTask(data)
|
||||
popOverVisible.value.approve = false
|
||||
nextAssigneesActivityNode.value = []
|
||||
// 清理 Timeline 组件中的自定义审批人数据
|
||||
if (nextAssigneesTimelineRef.value) {
|
||||
nextAssigneesTimelineRef.value.batchSetCustomApproveUsers({})
|
||||
}
|
||||
message.success('审批通过成功')
|
||||
} else {
|
||||
// 审批不通过数据
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
>
|
||||
<img class="w-full h-full" :src="getApprovalNodeImg(activity.nodeType)" alt="" />
|
||||
<div
|
||||
v-if="showStatusIcon"
|
||||
v-if="props.showStatusIcon"
|
||||
class="position-absolute top-17px left-17px rounded-full flex items-center p-1px border-2 border-white border-solid"
|
||||
:style="{ backgroundColor: getApprovalNodeColor(activity.status) }"
|
||||
>
|
||||
@ -28,7 +28,8 @@
|
||||
<div class="flex flex-col items-start gap2" :id="`activity-task-${activity.id}-${index}`">
|
||||
<!-- 第一行:节点名称、时间 -->
|
||||
<div class="flex w-full">
|
||||
<div class="font-bold"> {{ activity.name }} <span v-if="activity.status === TaskStatusEnum.SKIP">【跳过】</span>
|
||||
<div class="font-bold">
|
||||
{{ activity.name }} <span v-if="activity.status === TaskStatusEnum.SKIP">【跳过】</span>
|
||||
</div>
|
||||
<!-- 信息:时间 -->
|
||||
<div
|
||||
@ -54,13 +55,13 @@
|
||||
class="flex flex-wrap gap2 items-center"
|
||||
v-if="
|
||||
isEmpty(activity.tasks) &&
|
||||
isEmpty(activity.candidateUsers) &&
|
||||
(CandidateStrategy.START_USER_SELECT === activity.candidateStrategy ||
|
||||
CandidateStrategy.APPROVE_USER_SELECT === activity.candidateStrategy)
|
||||
((CandidateStrategy.START_USER_SELECT === activity.candidateStrategy &&
|
||||
isEmpty(activity.candidateUsers)) ||
|
||||
(props.enableApproveUserSelect &&
|
||||
CandidateStrategy.APPROVE_USER_SELECT === activity.candidateStrategy))
|
||||
"
|
||||
>
|
||||
<!-- && activity.nodeType === NodeType.USER_TASK_NODE -->
|
||||
|
||||
<el-tooltip content="添加用户" placement="left">
|
||||
<el-button
|
||||
class="!px-6px"
|
||||
@ -118,7 +119,7 @@
|
||||
</template>
|
||||
<!-- 信息:任务 ICON -->
|
||||
<div
|
||||
v-if="showStatusIcon && onlyStatusIconShow.includes(task.status)"
|
||||
v-if="props.showStatusIcon && onlyStatusIconShow.includes(task.status)"
|
||||
class="position-absolute top-19px left-23px rounded-full flex items-center p-1px border-2 border-white border-solid"
|
||||
:style="{ backgroundColor: statusIconMap2[task.status]?.color }"
|
||||
>
|
||||
@ -164,7 +165,7 @@
|
||||
|
||||
<!-- 信息:任务 ICON -->
|
||||
<div
|
||||
v-if="showStatusIcon"
|
||||
v-if="props.showStatusIcon"
|
||||
class="position-absolute top-20px left-24px rounded-full flex items-center p-1px border-2 border-white border-solid"
|
||||
:style="{ backgroundColor: statusIconMap2['-1']?.color }"
|
||||
>
|
||||
@ -197,13 +198,15 @@ import transactorSvg from '@/assets/svgs/bpm/transactor.svg'
|
||||
import childProcessSvg from '@/assets/svgs/bpm/child-process.svg'
|
||||
|
||||
defineOptions({ name: 'BpmProcessInstanceTimeline' })
|
||||
withDefaults(
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
activityNodes: ProcessInstanceApi.ApprovalNodeInfo[] // 审批节点信息
|
||||
showStatusIcon?: boolean // 是否显示头像右下角状态图标
|
||||
enableApproveUserSelect?: boolean // 是否开启审批人自选功能
|
||||
}>(),
|
||||
{
|
||||
showStatusIcon: true // 默认值为 true
|
||||
showStatusIcon: true, // 默认值为 true
|
||||
enableApproveUserSelect: false // 默认值为 false
|
||||
}
|
||||
)
|
||||
const { push } = useRouter() // 路由
|
||||
@ -234,7 +237,7 @@ const statusIconMap2 = {
|
||||
|
||||
const statusIconMap = {
|
||||
// 跳过
|
||||
'-2': { color: '#909398', icon: ArrowDown},
|
||||
'-2': { color: '#909398', icon: ArrowDown },
|
||||
// 审批未开始
|
||||
'-1': { color: '#909398', icon: Clock },
|
||||
'0': { color: '#00b32a', icon: Clock },
|
||||
@ -340,4 +343,19 @@ const handleChildProcess = (activity: any) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 设置自定义审批人 */
|
||||
const setCustomApproveUsers = (activityId: string, users: any[]) => {
|
||||
customApproveUsers.value[activityId] = users || []
|
||||
}
|
||||
|
||||
/** 批量设置多个节点的自定义审批人 */
|
||||
const batchSetCustomApproveUsers = (data: Record<string, any[]>) => {
|
||||
Object.keys(data).forEach((activityId) => {
|
||||
customApproveUsers.value[activityId] = data[activityId] || []
|
||||
})
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers })
|
||||
</script>
|
||||
|
||||
@ -184,8 +184,9 @@
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column align="center" label="任务编号" prop="id" :show-overflow-tooltip="true" />
|
||||
<el-table-column align="center" label="操作" fixed="right" width="80">
|
||||
<el-table-column align="center" label="操作" fixed="right" width="130">
|
||||
<template #default="scope">
|
||||
<el-button link type="warning" @click="handleWithdraw(scope.row)">撤回</el-button>
|
||||
<el-button link type="primary" @click="handleAudit(scope.row)">历史</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -209,6 +210,7 @@ import * as DefinitionApi from '@/api/bpm/definition'
|
||||
defineOptions({ name: 'BpmDoneTask' })
|
||||
|
||||
const { push } = useRouter() // 路由
|
||||
const message = useMessage()
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
@ -262,6 +264,14 @@ const handleAudit = (row: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
/** 测回按钮 */
|
||||
const handleWithdraw = (row: any) => {
|
||||
TaskApi.withdrawTask(row.id).then(() => {
|
||||
message.success('撤回成功')
|
||||
getList()
|
||||
})
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
await getList()
|
||||
|
||||
@ -144,7 +144,7 @@
|
||||
show-overflow-tooltip
|
||||
min-width="300"
|
||||
>
|
||||
<template #defaul="{ row }">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
:src="row.picUrl"
|
||||
class="mr-5px h-30px w-30px align-middle"
|
||||
|
||||
@ -13,12 +13,34 @@
|
||||
<el-descriptions-item label="模版发送人名称">
|
||||
{{ detailData.templateNickname }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="用户信息">
|
||||
{{ detailData.toMail }}
|
||||
<el-descriptions-item label="接收用户">
|
||||
<span v-if="detailData.userType && detailData.userId">
|
||||
<dict-tag :type="DICT_TYPE.USER_TYPE" :value="detailData.userType" />
|
||||
({{ detailData.userId }})
|
||||
</span>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="接收信息">
|
||||
<div>
|
||||
<div v-if="detailData.toMails && detailData.toMails.length > 0">
|
||||
收件:
|
||||
<span v-for="(mail, index) in detailData.toMails" :key="mail">
|
||||
{{ mail }}<span v-if="index < detailData.toMails.length - 1">、</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="detailData.ccMails && detailData.ccMails.length > 0">
|
||||
抄送:
|
||||
<span v-for="(mail, index) in detailData.ccMails" :key="mail">
|
||||
{{ mail }}<span v-if="index < detailData.ccMails.length - 1">、</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="detailData.bccMails && detailData.bccMails.length > 0">
|
||||
密送:
|
||||
<span v-for="(mail, index) in detailData.bccMails" :key="mail">
|
||||
{{ mail }}<span v-if="index < detailData.bccMails.length - 1">、</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="邮件标题">
|
||||
{{ detailData.templateTitle }}
|
||||
@ -58,7 +80,7 @@ defineOptions({ name: 'SystemMailLogDetail' })
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const detailLoading = ref(false) // 表单的加载中
|
||||
const detailData = ref() // 详情数据
|
||||
const accountList = ref([]) // 邮箱账号列表
|
||||
const accountList = ref<MailAccountApi.MailAccountVO[]>([]) // 邮箱账号列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (data: MailLogApi.MailLogVO) => {
|
||||
|
||||
@ -119,12 +119,36 @@
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<el-table-column label="接收邮箱" align="center" prop="toMail" width="200">
|
||||
<el-table-column label="接收用户" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.toMail }}</div>
|
||||
<div v-if="scope.row.userType && scope.row.userId">
|
||||
<dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" />
|
||||
{{ '(' + scope.row.userId + ')' }}
|
||||
<div>{{ '(' + scope.row.userId + ')' }}</div>
|
||||
</div>
|
||||
<div v-else>-</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="接收信息" align="center" width="300">
|
||||
<template #default="scope">
|
||||
<div class="text-left">
|
||||
<div v-if="scope.row.toMails && scope.row.toMails.length > 0">
|
||||
收件:
|
||||
<span v-for="(mail, index) in scope.row.toMails" :key="mail">
|
||||
{{ mail }}<span v-if="index < scope.row.toMails.length - 1">、</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="scope.row.ccMails && scope.row.ccMails.length > 0">
|
||||
抄送:
|
||||
<span v-for="(mail, index) in scope.row.ccMails" :key="mail">
|
||||
{{ mail }}<span v-if="index < scope.row.ccMails.length - 1">、</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="scope.row.bccMails && scope.row.bccMails.length > 0">
|
||||
密送:
|
||||
<span v-for="(mail, index) in scope.row.bccMails" :key="mail">
|
||||
{{ mail }}<span v-if="index < scope.row.bccMails.length - 1">、</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -185,15 +209,15 @@ const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
toMail: '',
|
||||
accountId: null,
|
||||
templateId: null,
|
||||
sendStatus: null,
|
||||
userId: null,
|
||||
userType: null,
|
||||
accountId: undefined,
|
||||
templateId: undefined,
|
||||
sendStatus: undefined,
|
||||
userId: undefined,
|
||||
userType: undefined,
|
||||
sendTime: []
|
||||
})
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
const accountList = ref([]) // 邮箱账号列表
|
||||
const accountList = ref<MailAccountApi.MailAccountVO[]>([]) // 邮箱账号列表
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
|
||||
@ -10,8 +10,26 @@
|
||||
<el-form-item label="模板内容" prop="content">
|
||||
<Editor :model-value="formData.content" height="150px" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="收件邮箱" prop="mail">
|
||||
<el-input v-model="formData.mail" placeholder="请输入收件邮箱" />
|
||||
<el-form-item label="收件邮箱" prop="toMails">
|
||||
<el-input-tag
|
||||
v-model="formData.toMails"
|
||||
placeholder="请输入收件邮箱,多个邮箱用回车分隔"
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="抄送邮箱" prop="ccMails">
|
||||
<el-input-tag
|
||||
v-model="formData.ccMails"
|
||||
placeholder="请输入抄送邮箱,多个邮箱用回车分隔"
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="密送邮箱" prop="bccMails">
|
||||
<el-input-tag
|
||||
v-model="formData.bccMails"
|
||||
placeholder="请输入密送邮箱,多个邮箱用回车分隔"
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-for="param in formData.params"
|
||||
@ -43,12 +61,13 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
|
||||
const formData = ref({
|
||||
content: '',
|
||||
params: {},
|
||||
mail: '',
|
||||
toMails: [],
|
||||
ccMails: [],
|
||||
bccMails: [],
|
||||
templateCode: '',
|
||||
templateParams: new Map()
|
||||
})
|
||||
const formRules = reactive({
|
||||
mail: [{ required: true, message: '邮箱不能为空', trigger: 'blur' }],
|
||||
templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }],
|
||||
templateParams: {}
|
||||
})
|
||||
@ -105,7 +124,9 @@ const resetForm = () => {
|
||||
formData.value = {
|
||||
content: '',
|
||||
params: {},
|
||||
mail: '',
|
||||
toMails: [],
|
||||
ccMails: [],
|
||||
bccMails: [],
|
||||
templateCode: '',
|
||||
templateParams: new Map()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user