|
|
@ -9,21 +9,10 @@ |
|
|
</el-button> |
|
|
</el-button> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<div class="flex items-center"> |
|
|
<el-input |
|
|
<el-input v-model="state.searchParams.config_name" class="w-200px mr-15px" placeholder="请输入配置名称" |
|
|
v-model="state.searchParams.config_name" |
|
|
clearable @keyup.enter="handleSearch" @clear="handleSearch" /> |
|
|
class="w-200px mr-15px" |
|
|
<el-select v-model="state.searchParams.status" class="w-150px mr-15px" placeholder="请选择状态" clearable |
|
|
placeholder="请输入配置名称" |
|
|
@change="handleSearch"> |
|
|
clearable |
|
|
|
|
|
@keyup.enter="handleSearch" |
|
|
|
|
|
@clear="handleSearch" |
|
|
|
|
|
/> |
|
|
|
|
|
<el-select |
|
|
|
|
|
v-model="state.searchParams.status" |
|
|
|
|
|
class="w-150px mr-15px" |
|
|
|
|
|
placeholder="请选择状态" |
|
|
|
|
|
clearable |
|
|
|
|
|
@change="handleSearch" |
|
|
|
|
|
> |
|
|
|
|
|
<el-option label="启用" :value="1" /> |
|
|
<el-option label="启用" :value="1" /> |
|
|
<el-option label="禁用" :value="0" /> |
|
|
<el-option label="禁用" :value="0" /> |
|
|
</el-select> |
|
|
</el-select> |
|
|
@ -38,23 +27,15 @@ |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<el-table |
|
|
<el-table v-loading="state.loading" class="mt-15px" :data="state.configList" |
|
|
v-loading="state.loading" |
|
|
:header-cell-style="{ background: '#fafafa', color: '#606266' }"> |
|
|
class="mt-15px" |
|
|
|
|
|
:data="state.configList" |
|
|
|
|
|
:header-cell-style="{ background: '#fafafa', color: '#606266' }" |
|
|
|
|
|
> |
|
|
|
|
|
<el-table-column label="ID" prop="id" width="80" /> |
|
|
<el-table-column label="ID" prop="id" width="80" /> |
|
|
<el-table-column label="配置名称" prop="config_name" min-width="180" /> |
|
|
<el-table-column label="配置名称" prop="config_name" min-width="180" /> |
|
|
<el-table-column label="配置描述" prop="description" min-width="200" show-overflow-tooltip /> |
|
|
<el-table-column label="配置描述" prop="description" min-width="200" show-overflow-tooltip /> |
|
|
<el-table-column label="状态" prop="status" width="100"> |
|
|
<el-table-column label="状态" prop="status" width="100"> |
|
|
<template #default="{ row }"> |
|
|
<template #default="{ row }"> |
|
|
<el-switch |
|
|
<el-switch v-model="row.status" :active-value="1" :inactive-value="0" |
|
|
v-model="row.status" |
|
|
@change="handleStatusChange(row)" /> |
|
|
:active-value="1" |
|
|
|
|
|
:inactive-value="0" |
|
|
|
|
|
@change="handleStatusChange(row)" |
|
|
|
|
|
/> |
|
|
|
|
|
</template> |
|
|
</template> |
|
|
</el-table-column> |
|
|
</el-table-column> |
|
|
<el-table-column label="创建时间" prop="created_at" width="180" /> |
|
|
<el-table-column label="创建时间" prop="created_at" width="180" /> |
|
|
@ -74,132 +55,100 @@ |
|
|
</el-table> |
|
|
</el-table> |
|
|
|
|
|
|
|
|
<div class="flex justify-end mt-15px"> |
|
|
<div class="flex justify-end mt-15px"> |
|
|
<el-pagination |
|
|
<el-pagination v-model:current-page="state.searchParams.page" |
|
|
v-model:current-page="state.searchParams.page" |
|
|
v-model:page-size="state.searchParams.limit" :page-sizes="[10, 20, 50, 100]" :total="state.total" |
|
|
v-model:page-size="state.searchParams.limit" |
|
|
layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" |
|
|
:page-sizes="[10, 20, 50, 100]" |
|
|
@current-change="handleCurrentChange" /> |
|
|
:total="state.total" |
|
|
|
|
|
layout="total, sizes, prev, pager, next, jumper" |
|
|
|
|
|
@size-change="handleSizeChange" |
|
|
|
|
|
@current-change="handleCurrentChange" |
|
|
|
|
|
/> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</el-card> |
|
|
</el-card> |
|
|
|
|
|
|
|
|
<!-- 新增/编辑弹窗 --> |
|
|
<!-- 新增/编辑弹窗 --> |
|
|
<el-dialog |
|
|
<el-dialog v-model="state.dialog.visible" :title="state.dialog.title" width="800px" |
|
|
v-model="state.dialog.visible" |
|
|
:close-on-click-modal="false" :destroy-on-close="true"> |
|
|
:title="state.dialog.title" |
|
|
<el-form ref="formRef" :model="state.dialog.form" :rules="state.dialog.rules" label-width="120px"> |
|
|
width="800px" |
|
|
|
|
|
:close-on-click-modal="false" |
|
|
|
|
|
:destroy-on-close="true" |
|
|
|
|
|
> |
|
|
|
|
|
<el-form |
|
|
|
|
|
ref="formRef" |
|
|
|
|
|
:model="state.dialog.form" |
|
|
|
|
|
:rules="state.dialog.rules" |
|
|
|
|
|
label-width="120px" |
|
|
|
|
|
> |
|
|
|
|
|
<el-form-item label="配置名称" prop="config_name"> |
|
|
<el-form-item label="配置名称" prop="config_name"> |
|
|
<el-input v-model="state.dialog.form.config_name" placeholder="请输入配置名称" /> |
|
|
<el-input v-model="state.dialog.form.config_name" placeholder="请输入配置名称" /> |
|
|
</el-form-item> |
|
|
</el-form-item> |
|
|
<el-form-item label="配置描述" prop="description"> |
|
|
<el-form-item label="配置描述" prop="description"> |
|
|
<el-input |
|
|
<el-input v-model="state.dialog.form.description" type="textarea" :rows="3" placeholder="请输入配置描述" /> |
|
|
v-model="state.dialog.form.description" |
|
|
|
|
|
type="textarea" |
|
|
|
|
|
:rows="3" |
|
|
|
|
|
placeholder="请输入配置描述" |
|
|
|
|
|
/> |
|
|
|
|
|
</el-form-item> |
|
|
</el-form-item> |
|
|
<el-form-item label="状态" prop="status"> |
|
|
<el-form-item label="状态" prop="status"> |
|
|
<el-switch |
|
|
<el-switch v-model="state.dialog.form.status" :active-value="1" :inactive-value="0" /> |
|
|
v-model="state.dialog.form.status" |
|
|
|
|
|
:active-value="1" |
|
|
|
|
|
:inactive-value="0" |
|
|
|
|
|
/> |
|
|
|
|
|
</el-form-item> |
|
|
</el-form-item> |
|
|
<el-form-item label="审批节点" prop="nodes"> |
|
|
<el-form-item label="审批节点" prop="nodes"> |
|
|
<div class="mb-10px"> |
|
|
<!-- 添加节点按钮 --> |
|
|
<el-button type="primary" @click="handleAddNode"> |
|
|
<div class="mb-4"> |
|
|
<icon name="add" class="mr-5px" /> |
|
|
<el-button type="primary" @click="handleAddNode" size="small"> |
|
|
|
|
|
<icon name="add" class="mr-1" /> |
|
|
添加节点 |
|
|
添加节点 |
|
|
</el-button> |
|
|
</el-button> |
|
|
</div> |
|
|
</div> |
|
|
<div v-if="state.dialog.form.nodes.length === 0" class="text-gray-400 text-center py-20px border border-dashed rounded"> |
|
|
|
|
|
|
|
|
<!-- 无节点提示 --> |
|
|
|
|
|
<div v-if="state.dialog.form.nodes.length === 0" |
|
|
|
|
|
class="text-gray-400 text-center py-6 border border-dashed rounded bg-gray-50"> |
|
|
暂无审批节点,请点击添加 |
|
|
暂无审批节点,请点击添加 |
|
|
</div> |
|
|
</div> |
|
|
<div v-else class="node-list"> |
|
|
|
|
|
<div |
|
|
<!-- 节点列表 --> |
|
|
v-for="(element, index) in state.dialog.form.nodes" |
|
|
<div v-else class="space-y-4"> |
|
|
:key="index" |
|
|
<div v-for="(element, index) in state.dialog.form.nodes" :key="index" |
|
|
class="node-item p-15px mb-15px border border-gray-200 rounded" |
|
|
class="p-4 border border-gray-300 rounded-md bg-white shadow-sm"> |
|
|
> |
|
|
<!-- 节点头部 --> |
|
|
<div class="flex justify-between items-center mb-10px"> |
|
|
<div class="flex justify-between items-center mb-4"> |
|
|
<div class="flex items-center"> |
|
|
<div class="flex items-center text-gray-800 font-medium"> |
|
|
<icon name="rank" class="drag-handle mr-5px cursor-move" /> |
|
|
<icon name="rank" class="drag-handle mr-2 text-gray-500 cursor-move" /> |
|
|
<span class="font-bold">节点 {{ index + 1 }}</span> |
|
|
节点 {{ index + 1 }} |
|
|
</div> |
|
|
</div> |
|
|
<el-button type="danger" link @click="handleRemoveNode(index)"> |
|
|
<el-button type="danger" link @click="handleRemoveNode(index)"> |
|
|
删除 |
|
|
删除 |
|
|
</el-button> |
|
|
</el-button> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex items-center mb-10px"> |
|
|
|
|
|
<span class="w-100px">节点名称:</span> |
|
|
<!-- 节点名称 --> |
|
|
<el-input |
|
|
<div class="flex items-center mb-3"> |
|
|
v-model="element.node_name" |
|
|
<span class="w-28 text-gray-600">节点名称:</span> |
|
|
placeholder="请输入节点名称" |
|
|
<el-input v-model="element.node_name" placeholder="请输入节点名称" size="small" style="width: 73%;"/> |
|
|
/> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
<div class="flex items-center mb-10px"> |
|
|
|
|
|
<span class="w-100px">审批人类型:</span> |
|
|
<!-- 审批人类型 --> |
|
|
<el-select |
|
|
<div class="flex items-center mb-3"> |
|
|
v-model="element.approver_type" |
|
|
<span class="w-28 text-gray-600">审批人类型:</span> |
|
|
class="flex-1" |
|
|
<el-select v-model="element.approver_type" class="flex-1" placeholder="请选择审批人类型" |
|
|
placeholder="请选择审批人类型" |
|
|
size="small"> |
|
|
> |
|
|
|
|
|
<el-option label="指定用户" value="user" /> |
|
|
<el-option label="指定用户" value="user" /> |
|
|
<el-option label="指定角色" value="role" /> |
|
|
<el-option label="指定角色" value="role" /> |
|
|
<el-option label="指定部门" value="department" /> |
|
|
<el-option label="指定部门" value="department" /> |
|
|
</el-select> |
|
|
</el-select> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex items-center mb-10px"> |
|
|
|
|
|
<span class="w-100px">审批人:</span> |
|
|
<!-- 审批 --> |
|
|
<el-select |
|
|
<div class="flex items-center mb-3"> |
|
|
v-model="element.approver_ids" |
|
|
<span class="w-28 text-gray-600">审批:</span> |
|
|
class="flex-1" |
|
|
<el-select v-model="element.approver_ids" class="flex-1" multiple placeholder="请选择审批" |
|
|
multiple |
|
|
size="small"> |
|
|
placeholder="请选择审批人" |
|
|
<!-- 用户 --> |
|
|
> |
|
|
|
|
|
<!-- 这里根据 approver_type 不同显示不同的选项 --> |
|
|
|
|
|
<template v-if="element.approver_type === 'user'"> |
|
|
<template v-if="element.approver_type === 'user'"> |
|
|
<el-option |
|
|
<el-option v-for="item in state.userOptions" :key="item.id" :label="item.name" |
|
|
v-for="item in state.userOptions" |
|
|
:value="String(item.id)" /> |
|
|
:key="item.value" |
|
|
|
|
|
:label="item.label" |
|
|
|
|
|
:value="item.value" |
|
|
|
|
|
/> |
|
|
|
|
|
</template> |
|
|
</template> |
|
|
|
|
|
<!-- 角色 --> |
|
|
<template v-else-if="element.approver_type === 'role'"> |
|
|
<template v-else-if="element.approver_type === 'role'"> |
|
|
<el-option |
|
|
<el-option v-for="item in state.roleOptions" :key="item.role_id" |
|
|
v-for="item in state.roleOptions" |
|
|
:label="item.role_name" :value="String(item.role_id)" /> |
|
|
:key="item.value" |
|
|
|
|
|
:label="item.label" |
|
|
|
|
|
:value="item.value" |
|
|
|
|
|
/> |
|
|
|
|
|
</template> |
|
|
</template> |
|
|
|
|
|
<!-- 部门 --> |
|
|
<template v-else-if="element.approver_type === 'department'"> |
|
|
<template v-else-if="element.approver_type === 'department'"> |
|
|
<el-option |
|
|
<el-option v-for="item in state.departmentOptions" :key="item.id" |
|
|
v-for="item in state.departmentOptions" |
|
|
:label="item.department_name" :value="String(item.id)" /> |
|
|
:key="item.value" |
|
|
|
|
|
:label="item.label" |
|
|
|
|
|
:value="item.value" |
|
|
|
|
|
/> |
|
|
|
|
|
</template> |
|
|
</template> |
|
|
</el-select> |
|
|
</el-select> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 审批类型 --> |
|
|
<div class="flex items-center"> |
|
|
<div class="flex items-center"> |
|
|
<span class="w-100px">审批类型:</span> |
|
|
<span class="w-28 text-gray-600">审批类型:</span> |
|
|
<el-radio-group v-model="element.sign_type"> |
|
|
<el-radio-group v-model="element.sign_type" size="small"> |
|
|
<el-radio label="or_sign">或签(一人通过即可)</el-radio> |
|
|
<el-radio label="or_sign">或签(一人通过即可)</el-radio> |
|
|
<el-radio label="and_sign">会签(需全部通过)</el-radio> |
|
|
<el-radio label="and_sign">会签(需全部通过)</el-radio> |
|
|
</el-radio-group> |
|
|
</el-radio-group> |
|
|
@ -207,6 +156,7 @@ |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</el-form-item> |
|
|
</el-form-item> |
|
|
|
|
|
|
|
|
</el-form> |
|
|
</el-form> |
|
|
<template #footer> |
|
|
<template #footer> |
|
|
<el-button @click="state.dialog.visible = false">取消</el-button> |
|
|
<el-button @click="state.dialog.visible = false">取消</el-button> |
|
|
@ -217,12 +167,7 @@ |
|
|
</el-dialog> |
|
|
</el-dialog> |
|
|
|
|
|
|
|
|
<!-- 详情弹窗 --> |
|
|
<!-- 详情弹窗 --> |
|
|
<el-dialog |
|
|
<el-dialog v-model="state.detailDialog.visible" title="审批流配置详情" width="800px" :destroy-on-close="true"> |
|
|
v-model="state.detailDialog.visible" |
|
|
|
|
|
title="审批流配置详情" |
|
|
|
|
|
width="800px" |
|
|
|
|
|
:destroy-on-close="true" |
|
|
|
|
|
> |
|
|
|
|
|
<el-descriptions :column="1" border> |
|
|
<el-descriptions :column="1" border> |
|
|
<el-descriptions-item label="ID"> |
|
|
<el-descriptions-item label="ID"> |
|
|
{{ state.detailDialog.info?.id || '-' }} |
|
|
{{ state.detailDialog.info?.id || '-' }} |
|
|
@ -246,19 +191,17 @@ |
|
|
<div class="mt-20px"> |
|
|
<div class="mt-20px"> |
|
|
<div class="font-bold text-16px mb-10px">审批节点列表</div> |
|
|
<div class="font-bold text-16px mb-10px">审批节点列表</div> |
|
|
<el-timeline> |
|
|
<el-timeline> |
|
|
<el-timeline-item |
|
|
<el-timeline-item v-for="(node, index) in state.detailDialog.info?.nodes || []" :key="index" |
|
|
v-for="(node, index) in state.detailDialog.info?.nodes || []" |
|
|
:type="getNodeType(node.sign_type)" :color="getNodeColor(node.sign_type)"> |
|
|
:key="index" |
|
|
|
|
|
:type="getNodeType(node.sign_type)" |
|
|
|
|
|
:color="getNodeColor(node.sign_type)" |
|
|
|
|
|
> |
|
|
|
|
|
<div class="font-bold mb-5px">{{ node.node_name }}</div> |
|
|
<div class="font-bold mb-5px">{{ node.node_name }}</div> |
|
|
<div class="text-gray-500"> |
|
|
<div class="text-gray-500"> |
|
|
审批人类型:{{ getApproverTypeText(node.approver_type) }} |
|
|
审批人类型:{{ getApproverTypeText(node.approver_type) }} |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="text-gray-500"> |
|
|
<div class="text-gray-500"> |
|
|
审批人:{{ node.approver_ids }} |
|
|
审批人:{{ getApproverNames(node.approver_ids,node.approver_type)}} |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="text-gray-500"> |
|
|
<div class="text-gray-500"> |
|
|
审批类型:{{ node.sign_type === 'or_sign' ? '或签' : '会签' }} |
|
|
审批类型:{{ node.sign_type === 'or_sign' ? '或签' : '会签' }} |
|
|
</div> |
|
|
</div> |
|
|
@ -270,45 +213,51 @@ |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script lang="ts" setup> |
|
|
<script lang="ts" setup> |
|
|
import { reactive, ref, onMounted } from 'vue' |
|
|
import { reactive, ref, onMounted } from 'vue' |
|
|
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus' |
|
|
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus' |
|
|
import { getConfigList, getConfigInfo, addConfig, editConfig, deleteConfig, changeConfigStatus } from '@/app/api/school_approval/config' |
|
|
import { getConfigList, getConfigInfo, addConfig, editConfig, deleteConfig, changeConfigStatus } from '@/app/api/school_approval/config' |
|
|
|
|
|
|
|
|
// 移除draggable导入,暂时不使用拖拽功能 |
|
|
import { |
|
|
// import draggable from 'vuedraggable' |
|
|
person_all, |
|
|
// 移除i18n导入 |
|
|
role_all, |
|
|
// import { useI18n } from 'vue-i18n' |
|
|
departments_all |
|
|
// const { t } = useI18n() |
|
|
} from '@/app/api/sys' |
|
|
|
|
|
|
|
|
// 表单引用 |
|
|
// 移除draggable导入,暂时不使用拖拽功能 |
|
|
const formRef = ref<FormInstance>() |
|
|
// import draggable from 'vuedraggable' |
|
|
|
|
|
// 移除i18n导入 |
|
|
// 定义详情对话框信息的类型 |
|
|
// import { useI18n } from 'vue-i18n' |
|
|
interface DetailInfo { |
|
|
// const { t } = useI18n() |
|
|
id?: number; |
|
|
|
|
|
config_name?: string; |
|
|
// 表单引用 |
|
|
description?: string; |
|
|
const formRef = ref<FormInstance>() |
|
|
status?: number; |
|
|
|
|
|
created_at?: string; |
|
|
// 定义详情对话框信息的类型 |
|
|
nodes?: Array<{ |
|
|
interface DetailInfo { |
|
|
node_name: string; |
|
|
id ?: number; |
|
|
approver_type: string; |
|
|
config_name ?: string; |
|
|
approver_ids: string; |
|
|
description ?: string; |
|
|
sign_type: string; |
|
|
status ?: number; |
|
|
|
|
|
created_at ?: string; |
|
|
|
|
|
nodes ?: Array<{ |
|
|
|
|
|
node_name : string; |
|
|
|
|
|
approver_type : string; |
|
|
|
|
|
approver_ids : string; |
|
|
|
|
|
sign_type : string; |
|
|
}>; |
|
|
}>; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 定义节点类型 |
|
|
// 定义节点类型 |
|
|
interface ApprovalNode { |
|
|
interface ApprovalNode { |
|
|
key: string; |
|
|
key : string; |
|
|
node_name: string; |
|
|
node_name : string; |
|
|
approver_type: string; |
|
|
approver_type : string; |
|
|
approver_ids: string[]; |
|
|
approver_ids : string[]; |
|
|
sign_type: string; |
|
|
sign_type : string; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 状态 |
|
|
// 状态 |
|
|
const state = reactive({ |
|
|
const state = reactive({ |
|
|
loading: false, |
|
|
loading: false, |
|
|
configList: [], |
|
|
configList: [], |
|
|
total: 0, |
|
|
total: 0, |
|
|
@ -319,19 +268,9 @@ const state = reactive({ |
|
|
status: '' |
|
|
status: '' |
|
|
}, |
|
|
}, |
|
|
// 模拟数据,实际应该从API获取 |
|
|
// 模拟数据,实际应该从API获取 |
|
|
userOptions: [ |
|
|
userOptions: [], |
|
|
{ label: '用户1', value: '1' }, |
|
|
roleOptions: [], |
|
|
{ label: '用户2', value: '2' }, |
|
|
departmentOptions: [], |
|
|
{ label: '用户3', value: '3' } |
|
|
|
|
|
], |
|
|
|
|
|
roleOptions: [ |
|
|
|
|
|
{ label: '角色1', value: '1' }, |
|
|
|
|
|
{ label: '角色2', value: '2' } |
|
|
|
|
|
], |
|
|
|
|
|
departmentOptions: [ |
|
|
|
|
|
{ label: '部门1', value: '1' }, |
|
|
|
|
|
{ label: '部门2', value: '2' } |
|
|
|
|
|
], |
|
|
|
|
|
dialog: { |
|
|
dialog: { |
|
|
visible: false, |
|
|
visible: false, |
|
|
title: '', |
|
|
title: '', |
|
|
@ -357,10 +296,48 @@ const state = reactive({ |
|
|
visible: false, |
|
|
visible: false, |
|
|
info: {} as DetailInfo |
|
|
info: {} as DetailInfo |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const setPersonIdList = async () => { |
|
|
|
|
|
state.userOptions = await (await person_all()).data |
|
|
|
|
|
} |
|
|
|
|
|
setPersonIdList() |
|
|
|
|
|
|
|
|
|
|
|
const setRoleIdList = async () => { |
|
|
|
|
|
state.roleOptions = await (await role_all()).data |
|
|
|
|
|
} |
|
|
|
|
|
setRoleIdList() |
|
|
|
|
|
|
|
|
// 校验节点 |
|
|
const setDepartmentsIdList = async () => { |
|
|
function validateNodes(rule: any, value: any, callback: any) { |
|
|
state.departmentOptions = await (await departments_all()).data |
|
|
|
|
|
} |
|
|
|
|
|
setDepartmentsIdList() |
|
|
|
|
|
|
|
|
|
|
|
const getApproverNames = (ids : string | string[], type : string) => { |
|
|
|
|
|
if (!ids) return ''; |
|
|
|
|
|
const idArray = typeof ids === 'string' ? ids.split(',') : ids; |
|
|
|
|
|
|
|
|
|
|
|
let options = []; |
|
|
|
|
|
if (type === 'user') { |
|
|
|
|
|
options = state.userOptions; |
|
|
|
|
|
} else if (type === 'role') { |
|
|
|
|
|
options = state.roleOptions; |
|
|
|
|
|
} else if (type === 'department') { |
|
|
|
|
|
options = state.departmentOptions; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log(options); |
|
|
|
|
|
|
|
|
|
|
|
return idArray |
|
|
|
|
|
.map(id => { |
|
|
|
|
|
const match = options.find(item => String(item.id || item.role_id) === String(id)); |
|
|
|
|
|
return match ? (match.name || match.role_name || match.department_name) : ''; |
|
|
|
|
|
}) |
|
|
|
|
|
.filter(name => name !== '') |
|
|
|
|
|
.join(', '); |
|
|
|
|
|
}; |
|
|
|
|
|
// 校验节点 |
|
|
|
|
|
function validateNodes(rule : any, value : any, callback : any) { |
|
|
if (!value || value.length === 0) { |
|
|
if (!value || value.length === 0) { |
|
|
callback(new Error('请至少添加一个审批节点')) |
|
|
callback(new Error('请至少添加一个审批节点')) |
|
|
} else { |
|
|
} else { |
|
|
@ -380,10 +357,10 @@ function validateNodes(rule: any, value: any, callback: any) { |
|
|
} |
|
|
} |
|
|
callback() |
|
|
callback() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取列表数据 |
|
|
// 获取列表数据 |
|
|
async function getList() { |
|
|
async function getList() { |
|
|
state.loading = true |
|
|
state.loading = true |
|
|
try { |
|
|
try { |
|
|
const res = await getConfigList(state.searchParams) |
|
|
const res = await getConfigList(state.searchParams) |
|
|
@ -394,16 +371,16 @@ async function getList() { |
|
|
} finally { |
|
|
} finally { |
|
|
state.loading = false |
|
|
state.loading = false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 搜索 |
|
|
// 搜索 |
|
|
function handleSearch() { |
|
|
function handleSearch() { |
|
|
state.searchParams.page = 1 |
|
|
state.searchParams.page = 1 |
|
|
getList() |
|
|
getList() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 重置 |
|
|
// 重置 |
|
|
function handleReset() { |
|
|
function handleReset() { |
|
|
state.searchParams = { |
|
|
state.searchParams = { |
|
|
page: 1, |
|
|
page: 1, |
|
|
limit: 10, |
|
|
limit: 10, |
|
|
@ -411,23 +388,23 @@ function handleReset() { |
|
|
status: '' |
|
|
status: '' |
|
|
} |
|
|
} |
|
|
getList() |
|
|
getList() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 页码变化 |
|
|
// 页码变化 |
|
|
function handleCurrentChange(page: number) { |
|
|
function handleCurrentChange(page : number) { |
|
|
state.searchParams.page = page |
|
|
state.searchParams.page = page |
|
|
getList() |
|
|
getList() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 每页条数变化 |
|
|
// 每页条数变化 |
|
|
function handleSizeChange(size: number) { |
|
|
function handleSizeChange(size : number) { |
|
|
state.searchParams.limit = size |
|
|
state.searchParams.limit = size |
|
|
state.searchParams.page = 1 |
|
|
state.searchParams.page = 1 |
|
|
getList() |
|
|
getList() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 添加 |
|
|
// 添加 |
|
|
function handleAdd() { |
|
|
function handleAdd() { |
|
|
state.dialog.type = 'add' |
|
|
state.dialog.type = 'add' |
|
|
state.dialog.title = '添加审批流配置' |
|
|
state.dialog.title = '添加审批流配置' |
|
|
state.dialog.form = { |
|
|
state.dialog.form = { |
|
|
@ -438,10 +415,10 @@ function handleAdd() { |
|
|
nodes: [] |
|
|
nodes: [] |
|
|
} |
|
|
} |
|
|
state.dialog.visible = true |
|
|
state.dialog.visible = true |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 编辑 |
|
|
// 编辑 |
|
|
async function handleEdit(row: any) { |
|
|
async function handleEdit(row : any) { |
|
|
state.dialog.type = 'edit' |
|
|
state.dialog.type = 'edit' |
|
|
state.dialog.title = '编辑审批流配置' |
|
|
state.dialog.title = '编辑审批流配置' |
|
|
state.dialog.loading = true |
|
|
state.dialog.loading = true |
|
|
@ -450,7 +427,7 @@ async function handleEdit(row: any) { |
|
|
state.dialog.form = { ...res.data } |
|
|
state.dialog.form = { ...res.data } |
|
|
// 处理节点数据,确保每个节点都有唯一的key |
|
|
// 处理节点数据,确保每个节点都有唯一的key |
|
|
if (state.dialog.form.nodes && Array.isArray(state.dialog.form.nodes)) { |
|
|
if (state.dialog.form.nodes && Array.isArray(state.dialog.form.nodes)) { |
|
|
state.dialog.form.nodes = state.dialog.form.nodes.map((node: any, index: number) => { |
|
|
state.dialog.form.nodes = state.dialog.form.nodes.map((node : any, index : number) => { |
|
|
// 确保approver_ids是字符串才进行split操作 |
|
|
// 确保approver_ids是字符串才进行split操作 |
|
|
const approverIds = typeof node.approver_ids === 'string' |
|
|
const approverIds = typeof node.approver_ids === 'string' |
|
|
? node.approver_ids.split(',') |
|
|
? node.approver_ids.split(',') |
|
|
@ -472,10 +449,10 @@ async function handleEdit(row: any) { |
|
|
} finally { |
|
|
} finally { |
|
|
state.dialog.loading = false |
|
|
state.dialog.loading = false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 查看详情 |
|
|
// 查看详情 |
|
|
async function handleDetail(row: any) { |
|
|
async function handleDetail(row : any) { |
|
|
try { |
|
|
try { |
|
|
const res = await getConfigInfo({ id: row.id }) |
|
|
const res = await getConfigInfo({ id: row.id }) |
|
|
state.detailDialog.info = res.data |
|
|
state.detailDialog.info = res.data |
|
|
@ -483,10 +460,10 @@ async function handleDetail(row: any) { |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error(error) |
|
|
console.error(error) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 删除 |
|
|
// 删除 |
|
|
function handleDelete(row: any) { |
|
|
function handleDelete(row : any) { |
|
|
ElMessageBox.confirm('确定要删除此项吗?', '警告', { |
|
|
ElMessageBox.confirm('确定要删除此项吗?', '警告', { |
|
|
confirmButtonText: '确定', |
|
|
confirmButtonText: '确定', |
|
|
cancelButtonText: '取消', |
|
|
cancelButtonText: '取消', |
|
|
@ -501,11 +478,11 @@ function handleDelete(row: any) { |
|
|
console.error(error) |
|
|
console.error(error) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
.catch(() => {}) |
|
|
.catch(() => { }) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 修改状态 |
|
|
// 修改状态 |
|
|
async function handleStatusChange(row: any) { |
|
|
async function handleStatusChange(row : any) { |
|
|
try { |
|
|
try { |
|
|
await changeConfigStatus({ id: row.id, status: row.status }) |
|
|
await changeConfigStatus({ id: row.id, status: row.status }) |
|
|
ElMessage.success( |
|
|
ElMessage.success( |
|
|
@ -517,10 +494,10 @@ async function handleStatusChange(row: any) { |
|
|
console.error(error) |
|
|
console.error(error) |
|
|
row.status = row.status ? 0 : 1 // 失败时恢复原状态 |
|
|
row.status = row.status ? 0 : 1 // 失败时恢复原状态 |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 添加节点 |
|
|
// 添加节点 |
|
|
function handleAddNode() { |
|
|
function handleAddNode() { |
|
|
state.dialog.form.nodes.push({ |
|
|
state.dialog.form.nodes.push({ |
|
|
key: `node_${state.dialog.form.nodes.length}_${Date.now()}`, |
|
|
key: `node_${state.dialog.form.nodes.length}_${Date.now()}`, |
|
|
node_name: '', |
|
|
node_name: '', |
|
|
@ -528,15 +505,15 @@ function handleAddNode() { |
|
|
approver_ids: [], |
|
|
approver_ids: [], |
|
|
sign_type: 'or_sign' |
|
|
sign_type: 'or_sign' |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 移除节点 |
|
|
// 移除节点 |
|
|
function handleRemoveNode(index: number) { |
|
|
function handleRemoveNode(index : number) { |
|
|
state.dialog.form.nodes.splice(index, 1) |
|
|
state.dialog.form.nodes.splice(index, 1) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 提交表单 |
|
|
// 提交表单 |
|
|
async function handleSubmit() { |
|
|
async function handleSubmit() { |
|
|
if (!formRef.value) return |
|
|
if (!formRef.value) return |
|
|
|
|
|
|
|
|
await formRef.value.validate(async (valid) => { |
|
|
await formRef.value.validate(async (valid) => { |
|
|
@ -548,7 +525,7 @@ async function handleSubmit() { |
|
|
const formData = { ...state.dialog.form } |
|
|
const formData = { ...state.dialog.form } |
|
|
|
|
|
|
|
|
// 确保所有节点数据都有有效结构 |
|
|
// 确保所有节点数据都有有效结构 |
|
|
formData.nodes = formData.nodes.map((node: any, index: number) => { |
|
|
formData.nodes = formData.nodes.map((node : any, index : number) => { |
|
|
// 清理无效的key字段,防止API不接受 |
|
|
// 清理无效的key字段,防止API不接受 |
|
|
const { key, ...nodeWithoutKey } = node; |
|
|
const { key, ...nodeWithoutKey } = node; |
|
|
|
|
|
|
|
|
@ -585,54 +562,54 @@ async function handleSubmit() { |
|
|
state.dialog.loading = false |
|
|
state.dialog.loading = false |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取节点类型 |
|
|
// 获取节点类型 |
|
|
function getNodeType(signType: string) { |
|
|
function getNodeType(signType : string) { |
|
|
return signType === 'or_sign' ? 'primary' : 'success' |
|
|
return signType === 'or_sign' ? 'primary' : 'success' |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取节点颜色 |
|
|
// 获取节点颜色 |
|
|
function getNodeColor(signType: string) { |
|
|
function getNodeColor(signType : string) { |
|
|
return signType === 'or_sign' ? '#409EFF' : '#67C23A' |
|
|
return signType === 'or_sign' ? '#409EFF' : '#67C23A' |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取审批人类型文本 |
|
|
// 获取审批人类型文本 |
|
|
function getApproverTypeText(type: string) { |
|
|
function getApproverTypeText(type : string) { |
|
|
const map: Record<string, string> = { |
|
|
const map : Record<string, string> = { |
|
|
user: '指定用户', |
|
|
user: '指定用户', |
|
|
role: '指定角色', |
|
|
role: '指定角色', |
|
|
department: '指定部门' |
|
|
department: '指定部门' |
|
|
} |
|
|
} |
|
|
return map[type] || type |
|
|
return map[type] || type |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
onMounted(() => { |
|
|
onMounted(() => { |
|
|
getList() |
|
|
getList() |
|
|
}) |
|
|
}) |
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
<style lang="scss" scoped> |
|
|
.node-item { |
|
|
.node-item { |
|
|
background-color: #f9f9f9; |
|
|
background-color: #f9f9f9; |
|
|
transition: all 0.3s; |
|
|
transition: all 0.3s; |
|
|
|
|
|
|
|
|
&:hover { |
|
|
&:hover { |
|
|
background-color: #f2f2f2; |
|
|
background-color: #f2f2f2; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.ghost { |
|
|
.ghost { |
|
|
opacity: 0.5; |
|
|
opacity: 0.5; |
|
|
background: #c8ebfb; |
|
|
background: #c8ebfb; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.drag-handle { |
|
|
.drag-handle { |
|
|
cursor: move; |
|
|
cursor: move; |
|
|
color: #909399; |
|
|
color: #909399; |
|
|
|
|
|
|
|
|
&:hover { |
|
|
&:hover { |
|
|
color: #409eff; |
|
|
color: #409eff; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
</style> |
|
|
</style> |