Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
B
binfast-admin-view
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
binfast
binfast-admin-view
Commits
a336722d
Commit
a336722d
authored
Nov 02, 2025
by
刘斌
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 增加人事审批流程
parent
3905e5fc
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1560 additions
and
71 deletions
+1560
-71
employeeFlow.ts
apps/web-antd/src/api/hr/employeeFlow.ts
+148
-0
employeeInfo.ts
apps/web-antd/src/api/hr/employeeInfo.ts
+62
-2
hr.ts
apps/web-antd/src/router/routes/modules/hr.ts
+13
-0
apply-entry-model.vue
.../web-antd/src/views/hr/employeeInfo/apply-entry-model.vue
+125
-0
apply-resign-model.vue
...web-antd/src/views/hr/employeeInfo/apply-resign-model.vue
+138
-0
apply-transfer-model.vue
...b-antd/src/views/hr/employeeInfo/apply-transfer-model.vue
+172
-0
employee-detail-drawer.vue
...antd/src/views/hr/employeeInfo/employee-detail-drawer.vue
+297
-0
list.vue
apps/web-antd/src/views/hr/employeeInfo/list.vue
+52
-68
flow-preview.vue
apps/web-antd/src/views/workflow/components/flow-preview.vue
+1
-1
data.ts
apps/web-antd/src/views/workflow/hrFlow/data.ts
+109
-0
form.vue
apps/web-antd/src/views/workflow/hrFlow/form.vue
+138
-0
hr-description.vue
apps/web-antd/src/views/workflow/hrFlow/hr-description.vue
+91
-0
list.vue
apps/web-antd/src/views/workflow/hrFlow/list.vue
+208
-0
category-tree.vue
...td/src/views/workflow/processDefinition/category-tree.vue
+1
-0
register.ts
apps/web-antd/src/views/workflow/register.ts
+5
-0
No files found.
apps/web-antd/src/api/hr/employeeFlow.ts
0 → 100644
View file @
a336722d
import
type
{
BaseModel
,
PageQuery
}
from
'#/api/baseModel'
;
import
{
commonExport
}
from
'#/api/helper'
;
import
{
requestClient
}
from
'#/api/request'
;
export
namespace
EmployeeFlowApi
{
export
interface
EmployeeFlow
extends
BaseModel
{
/**
* 申请编号
*/
applyCode
?:
string
;
/**
* 审批类型
*/
flowType
?:
string
;
/**
* 员工信息ID
*/
employeeId
?:
number
;
/**
* 开始时间
*/
startDate
?:
string
;
/**
* 结束时间
*/
endDate
?:
string
;
/**
* 状态
*/
status
?:
string
;
/**
* 备注
*/
remark
?:
string
;
}
export
interface
EmployeeFlowVo
{
/**
* 序号
*/
id
?:
number
;
/**
* 申请编号
*/
applyCode
?:
string
;
/**
* 审批类型
*/
flowType
?:
string
;
/**
* 员工信息ID
*/
employeeId
?:
number
;
/**
* 审计内容
*/
auditLogList
?:
Array
<
AuditLogVo
>
;
/**
* 状态
*/
status
?:
string
;
/**
* 备注
*/
remark
?:
string
;
}
export
interface
AuditLogVo
{
/**
* 审计名称(入职、调职、离职)
*/
auditName
?:
string
;
/**
* 字段名称
*/
auditField
?:
string
;
/**
* 字段注释名称
*/
auditFieldName
?:
string
;
/**
* 变更前值
*/
beforeVal
?:
string
;
/**
* 变更后值
*/
afterVal
?:
string
;
}
}
/**
* 查询人事审批对象列表
* @param params
* @returns {*} page
*/
export
function
apiPage
(
params
:
PageQuery
)
{
return
requestClient
.
get
(
'/employee/flow/page'
,
{
params
});
}
/**
* 查询人事审批对象详细
* @param id
*/
export
function
apiDetail
(
id
:
number
)
{
return
requestClient
.
get
(
`/employee/flow/
${
id
}
`
);
}
/**
* 新增人事审批对象
* @param data
*/
export
function
apiAdd
(
data
:
EmployeeFlowApi
.
EmployeeFlow
)
{
return
requestClient
.
post
(
'/employee/flow'
,
data
);
}
/**
* 修改人事审批对象
* @param data
*/
export
function
apiUpdate
(
data
:
EmployeeFlowApi
.
EmployeeFlow
)
{
return
requestClient
.
put
(
'/employee/flow'
,
data
);
}
/**
* 删除人事审批对象
* @param id
*/
export
function
apiDelete
(
id
:
Array
<
number
>
|
number
)
{
return
requestClient
.
delete
(
`/employee/flow/
${
id
}
`
);
}
/**
* 导出人事审批对象
* @param params
*/
export
function
apiExport
(
params
:
PageQuery
)
{
return
commonExport
(
'/employee/flow/export'
,
params
);
}
/**
* 提交 & 发起流程(后端发起)
* @param data data
* @returns void
*/
export
function
submitAndStartWorkflow
(
data
:
EmployeeFlowApi
.
EmployeeFlow
)
{
return
requestClient
.
post
(
'/employee/flow/submitAndFlowStart'
,
data
,
{
successMessageMode
:
'message'
,
});
}
apps/web-antd/src/api/hr/employeeInfo.ts
View file @
a336722d
...
...
@@ -46,6 +46,7 @@ export namespace EmployeeInfoApi {
* 性别
*/
gender
?:
string
;
genderName
?:
string
;
/**
* 身份证号码
*/
...
...
@@ -76,10 +77,12 @@ export namespace EmployeeInfoApi {
* 婚姻状况
*/
maritalStatus
?:
string
;
maritalStatusName
?:
string
;
/**
* 政治面貌
*/
politicalStatus
?:
string
;
politicalStatusName
?:
string
;
/**
* 手机号码
*/
...
...
@@ -117,6 +120,7 @@ export namespace EmployeeInfoApi {
* 工龄段
*/
yearsOfServiceSegment
?:
string
;
yearsOfServiceSegmentName
?:
string
;
/**
* 学历
*/
...
...
@@ -141,6 +145,7 @@ export namespace EmployeeInfoApi {
* 员工类型
*/
employeeType
?:
string
;
employeeTypeName
?:
string
;
/**
* 职称情况
*/
...
...
@@ -153,6 +158,7 @@ export namespace EmployeeInfoApi {
* 用工形式
*/
employmentForm
?:
string
;
employmentFormName
?:
string
;
/**
* 劳动合同期限
*/
...
...
@@ -202,6 +208,39 @@ export namespace EmployeeInfoApi {
*/
resignationReason
?:
string
;
}
export
interface
EmployeeApplyBo
{
/**
* 序号
*/
id
?:
number
;
/**
* 备注
*/
remark
?:
string
;
}
export
interface
EmployeeTransferApplyBo
extends
EmployeeApplyBo
{
/**
* 一级部门
*/
firstLevelDepartment
?:
string
;
/**
* 二级部门
*/
secondLevelDepartment
?:
string
;
}
export
interface
EmployeeResignApplyBo
extends
EmployeeApplyBo
{
/**
* 离职时间
*/
resignDate
?:
string
;
/**
* 离职原因
*/
resignReason
?:
string
;
}
}
/**
...
...
@@ -219,6 +258,13 @@ export function apiPage(params: PageQuery) {
export
function
apiDetail
(
id
:
number
)
{
return
requestClient
.
get
(
`/employee/info/
${
id
}
`
);
}
/**
* 展示员工信息详细
* @param id
*/
export
function
apiInfoDetail
(
id
:
number
)
{
return
requestClient
.
get
(
`/employee/info/detail/
${
id
}
`
);
}
/**
* 新增员工信息
* @param data
...
...
@@ -248,12 +294,26 @@ export function apiExport(id: number) {
return
commonExport
(
`/employee/info/export/
${
id
}
`
,
{});
}
/**
* 申请员工入职
* @param data
*/
export
function
applyEntry
(
data
:
EmployeeInfoApi
.
EmployeeApplyBo
)
{
return
requestClient
.
post
(
'/employee/info/applyEntry'
,
data
);
}
/**
* 申请员工离职
* @param data
*/
export
function
applyResign
(
data
:
EmployeeInfoApi
.
EmployeeResignApplyBo
)
{
return
requestClient
.
post
(
'/employee/info/applyResign'
,
data
);
}
/**
* 申请员工调职
* @param id
*/
export
function
apply
Resign
(
id
:
number
)
{
return
requestClient
.
p
ut
(
`/employee/info/applyResign/
${
id
}
`
);
export
function
apply
Transfer
(
data
:
EmployeeInfoApi
.
EmployeeTransferApplyBo
)
{
return
requestClient
.
p
ost
(
'/employee/info/applyTransfer'
,
data
);
}
/**
...
...
apps/web-antd/src/router/routes/modules/hr.ts
View file @
a336722d
...
...
@@ -24,6 +24,19 @@ const routes: RouteRecordRaw[] = [
componentPath
:
'#/views/hr/employeeInfo/list.vue'
,
},
},
{
name
:
'EmployeeFlowList'
,
path
:
'/hr/employee/flow'
,
// hidden: false,
component
:
()
=>
import
(
'#/views/workflow/hrFlow/list.vue'
),
meta
:
{
title
:
'人事申请'
,
icon
:
'fluent-mdl2:leave-user'
,
noCache
:
false
,
componentPath
:
'#/views/workflow/hrFlow/list.vue'
,
// link: null,
},
},
],
},
];
...
...
apps/web-antd/src/views/hr/employeeInfo/apply-entry-model.vue
0 → 100644
View file @
a336722d
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
EmployeeInfoApi
}
from
'#/api/hr/employeeInfo'
;
import
{
ref
}
from
'vue'
;
import
{
useVbenModal
}
from
'@vben/common-ui'
;
import
{
useVbenForm
}
from
'#/adapter/form'
;
import
{
applyEntry
}
from
'#/api/hr/employeeInfo'
;
import
{
defaultFormValueGetter
,
useBeforeCloseDiff
}
from
'#/utils/popup'
;
const
emit
=
defineEmits
<
{
success
:
[];
}
>
();
const
formData
=
ref
<
EmployeeInfoApi
.
EmployeeApplyBo
>
();
const
formSchema
:
VbenFormSchema
[]
=
[
{
label
:
'主键'
,
fieldName
:
'id'
,
component
:
'Input'
,
dependencies
:
{
show
:
()
=>
false
,
triggerFields
:
[
''
],
},
},
{
component
:
'Input'
,
fieldName
:
'name'
,
label
:
'姓名'
,
disabled
:
true
,
},
// {
// component: 'Input',
// fieldName: 'dictType',
// label: '字典类型',
// rules: 'required',
// },
// {
// component: 'Input',
// fieldName: 'description',
// label: '描述',
// rules: 'required',
// },
{
component
:
'Textarea'
,
fieldName
:
'remark'
,
label
:
'入职申请备注'
,
formItemClass
:
'items-start'
,
},
];
const
[
BasicForm
,
formApi
]
=
useVbenForm
({
commonConfig
:
{
componentProps
:
{
class
:
'w-full'
,
},
formItemClass
:
'col-span-2'
,
labelWidth
:
90
,
},
schema
:
formSchema
,
showDefaultActions
:
false
,
wrapperClass
:
'grid-cols-2'
,
});
const
{
onBeforeClose
,
markInitialized
,
resetInitialized
}
=
useBeforeCloseDiff
(
{
initializedGetter
:
defaultFormValueGetter
(
formApi
),
currentGetter
:
defaultFormValueGetter
(
formApi
),
},
);
const
[
BasicModal
,
modalApi
]
=
useVbenModal
({
fullscreenButton
:
false
,
onBeforeClose
,
onClosed
:
handleClosed
,
onConfirm
:
onSubmit
,
onOpenChange
:
async
(
isOpen
)
=>
{
if
(
!
isOpen
)
{
return
null
;
}
modalApi
.
modalLoading
(
true
);
const
data
=
modalApi
.
getData
()
as
{
id
?:
number
;
name
?:
string
};
if
(
data
)
{
formData
.
value
=
data
;
await
formApi
.
setValues
(
formData
.
value
);
}
await
markInitialized
();
modalApi
.
modalLoading
(
false
);
},
});
async
function
onSubmit
()
{
const
{
valid
}
=
await
formApi
.
validate
();
if
(
valid
)
{
modalApi
.
lock
();
const
data
=
await
formApi
.
getValues
<
EmployeeInfoApi
.
EmployeeApplyBo
>
();
try
{
await
applyEntry
(
data
);
resetInitialized
();
emit
(
'success'
);
modalApi
.
close
();
}
finally
{
modalApi
.
unlock
();
}
}
}
async
function
handleClosed
()
{
await
formApi
.
resetForm
();
resetInitialized
();
}
// const getModalTitle = computed(() =>
// formData.value?.id ? '修改字典类型' : '新增字典类型',
// );
</
script
>
<
template
>
<BasicModal
title=
"入职申请"
>
<BasicForm
class=
"mx-4"
/>
</BasicModal>
</
template
>
apps/web-antd/src/views/hr/employeeInfo/apply-resign-model.vue
0 → 100644
View file @
a336722d
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
EmployeeInfoApi
}
from
'#/api/hr/employeeInfo'
;
import
{
ref
}
from
'vue'
;
import
{
useVbenModal
}
from
'@vben/common-ui'
;
import
{
getVxePopupContainer
}
from
'@vben/utils'
;
import
{
useVbenForm
}
from
'#/adapter/form'
;
import
{
applyResign
}
from
'#/api/hr/employeeInfo'
;
import
{
defaultFormValueGetter
,
useBeforeCloseDiff
}
from
'#/utils/popup'
;
const
emit
=
defineEmits
<
{
success
:
[];
}
>
();
const
formData
=
ref
<
EmployeeInfoApi
.
EmployeeResignApplyBo
>
();
const
formSchema
:
VbenFormSchema
[]
=
[
{
label
:
'主键'
,
fieldName
:
'id'
,
component
:
'Input'
,
dependencies
:
{
show
:
()
=>
false
,
triggerFields
:
[
''
],
},
},
{
component
:
'Input'
,
fieldName
:
'name'
,
label
:
'姓名'
,
disabled
:
true
,
},
{
component
:
'DatePicker'
,
componentProps
:
{
format
:
'YYYY-MM-DD'
,
valueFormat
:
'YYYY-MM-DD'
,
getVxePopupContainer
,
},
fieldName
:
'resignDate'
,
label
:
'离职日期'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'resignReason'
,
label
:
'离职原因'
,
// rules: 'required',
},
// {
// component: 'Input',
// fieldName: 'description',
// label: '描述',
// rules: 'required',
// },
{
component
:
'Textarea'
,
fieldName
:
'remark'
,
label
:
'离职申请备注'
,
formItemClass
:
'items-start'
,
},
];
const
[
BasicForm
,
formApi
]
=
useVbenForm
({
commonConfig
:
{
componentProps
:
{
class
:
'w-full'
,
},
formItemClass
:
'col-span-2'
,
labelWidth
:
90
,
},
schema
:
formSchema
,
showDefaultActions
:
false
,
wrapperClass
:
'grid-cols-2'
,
});
const
{
onBeforeClose
,
markInitialized
,
resetInitialized
}
=
useBeforeCloseDiff
(
{
initializedGetter
:
defaultFormValueGetter
(
formApi
),
currentGetter
:
defaultFormValueGetter
(
formApi
),
},
);
const
[
BasicModal
,
modalApi
]
=
useVbenModal
({
fullscreenButton
:
false
,
onBeforeClose
,
onClosed
:
handleClosed
,
onConfirm
:
onSubmit
,
onOpenChange
:
async
(
isOpen
)
=>
{
if
(
!
isOpen
)
{
return
null
;
}
modalApi
.
modalLoading
(
true
);
const
data
=
modalApi
.
getData
()
as
{
id
?:
number
;
name
?:
string
};
if
(
data
)
{
formData
.
value
=
data
;
await
formApi
.
setValues
(
formData
.
value
);
}
await
markInitialized
();
modalApi
.
modalLoading
(
false
);
},
});
async
function
onSubmit
()
{
const
{
valid
}
=
await
formApi
.
validate
();
if
(
valid
)
{
modalApi
.
lock
();
const
data
=
await
formApi
.
getValues
<
EmployeeInfoApi
.
EmployeeResignApplyBo
>
();
try
{
await
applyResign
(
data
);
resetInitialized
();
emit
(
'success'
);
modalApi
.
close
();
}
finally
{
modalApi
.
unlock
();
}
}
}
async
function
handleClosed
()
{
await
formApi
.
resetForm
();
resetInitialized
();
}
// const getModalTitle = computed(() =>
// formData.value?.id ? '修改字典类型' : '新增字典类型',
// );
</
script
>
<
template
>
<BasicModal
title=
"离职申请"
>
<BasicForm
class=
"mx-4"
/>
</BasicModal>
</
template
>
apps/web-antd/src/views/hr/employeeInfo/apply-transfer-model.vue
0 → 100644
View file @
a336722d
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
EmployeeInfoApi
}
from
'#/api/hr/employeeInfo'
;
import
{
ref
}
from
'vue'
;
import
{
useVbenModal
}
from
'@vben/common-ui'
;
import
{
getVxePopupContainer
}
from
'@vben/utils'
;
import
{
useVbenForm
}
from
'#/adapter/form'
;
import
{
selectDeptNamesByLevel
,
selectDeptNamesByParent
,
}
from
'#/api/hr/employeeDept'
;
import
{
applyTransfer
}
from
'#/api/hr/employeeInfo'
;
import
{
defaultFormValueGetter
,
useBeforeCloseDiff
}
from
'#/utils/popup'
;
const
emit
=
defineEmits
<
{
success
:
[];
}
>
();
const
formData
=
ref
<
EmployeeInfoApi
.
EmployeeTransferApplyBo
>
();
const
formSchema
:
VbenFormSchema
[]
=
[
{
label
:
'主键'
,
fieldName
:
'id'
,
component
:
'Input'
,
dependencies
:
{
show
:
()
=>
false
,
triggerFields
:
[
''
],
},
},
{
component
:
'Input'
,
fieldName
:
'name'
,
label
:
'姓名'
,
disabled
:
true
,
},
{
component
:
'ApiSelect'
,
componentProps
:
(
formModel
)
=>
({
api
:
async
()
=>
{
const
data
:
string
[]
=
await
selectDeptNamesByLevel
(
1
);
return
data
.
map
((
item
)
=>
({
label
:
item
,
value
:
item
,
}));
},
async
onSelect
(
name
:
string
)
{
/** 根据部门ID加载岗位 */
await
setupDeptLevel2Options
(
name
);
/** 变化后需要重新选择岗位 */
formModel
.
secondLevelDepartment
=
[];
},
getVxePopupContainer
,
}),
fieldName
:
'firstLevelDepartment'
,
label
:
'一级部门'
,
rules
:
'required'
,
},
{
component
:
'Select'
,
componentProps
:
{
getVxePopupContainer
,
placeholder
:
'请先选择一级部门'
,
},
fieldName
:
'secondLevelDepartment'
,
label
:
'二级部门'
,
rules
:
'required'
,
},
// {
// component: 'Input',
// fieldName: 'description',
// label: '描述',
// rules: 'required',
// },
{
component
:
'Textarea'
,
fieldName
:
'remark'
,
label
:
'调配申请备注'
,
formItemClass
:
'items-start'
,
},
];
const
[
BasicForm
,
formApi
]
=
useVbenForm
({
commonConfig
:
{
componentProps
:
{
class
:
'w-full'
,
},
formItemClass
:
'col-span-2'
,
labelWidth
:
90
,
},
schema
:
formSchema
,
showDefaultActions
:
false
,
wrapperClass
:
'grid-cols-2'
,
});
const
{
onBeforeClose
,
markInitialized
,
resetInitialized
}
=
useBeforeCloseDiff
(
{
initializedGetter
:
defaultFormValueGetter
(
formApi
),
currentGetter
:
defaultFormValueGetter
(
formApi
),
},
);
const
[
BasicModal
,
modalApi
]
=
useVbenModal
({
fullscreenButton
:
false
,
onBeforeClose
,
onClosed
:
handleClosed
,
onConfirm
:
onSubmit
,
onOpenChange
:
async
(
isOpen
)
=>
{
if
(
!
isOpen
)
{
return
null
;
}
modalApi
.
modalLoading
(
true
);
const
data
=
modalApi
.
getData
()
as
{
id
?:
number
;
name
?:
string
};
if
(
data
)
{
formData
.
value
=
data
;
await
formApi
.
setValues
(
formData
.
value
);
}
await
markInitialized
();
modalApi
.
modalLoading
(
false
);
},
});
async
function
onSubmit
()
{
const
{
valid
}
=
await
formApi
.
validate
();
if
(
valid
)
{
modalApi
.
lock
();
const
data
=
await
formApi
.
getValues
<
EmployeeInfoApi
.
EmployeeTransferApplyBo
>
();
try
{
await
applyTransfer
(
data
);
resetInitialized
();
emit
(
'success'
);
modalApi
.
close
();
}
finally
{
modalApi
.
unlock
();
}
}
}
async
function
setupDeptLevel2Options
(
name
:
string
)
{
const
deptNameList
:
string
[]
=
await
selectDeptNamesByParent
(
name
);
const
options
=
deptNameList
.
map
((
item
)
=>
({
label
:
item
,
value
:
item
,
}));
const
placeholder
=
options
.
length
>
0
?
'请选择'
:
'该部门下暂无岗位'
;
formApi
.
updateSchema
([
{
componentProps
:
{
options
,
placeholder
},
fieldName
:
'secondLevelDepartment'
,
},
]);
}
async
function
handleClosed
()
{
await
formApi
.
resetForm
();
resetInitialized
();
}
// const getModalTitle = computed(() =>
// formData.value?.id ? '修改字典类型' : '新增字典类型',
// );
</
script
>
<
template
>
<BasicModal
title=
"调配申请"
>
<BasicForm
class=
"mx-4"
/>
</BasicModal>
</
template
>
apps/web-antd/src/views/hr/employeeInfo/employee-detail-drawer.vue
0 → 100644
View file @
a336722d
<
script
setup
lang=
"ts"
>
import
type
{
EmployeeInfoApi
}
from
'#/api/hr/employeeInfo'
;
import
{
ref
,
shallowRef
}
from
'vue'
;
import
{
useVbenDrawer
}
from
'@vben/common-ui'
;
import
{
Descriptions
,
DescriptionsItem
,
Skeleton
}
from
'ant-design-vue'
;
import
{
apiInfoDetail
}
from
'#/api/hr/employeeInfo'
;
const
[
BasicDrawer
,
drawerApi
]
=
useVbenDrawer
({
onOpenChange
:
handleOpenChange
,
onClosed
()
{
currentEmployee
.
value
=
null
;
},
});
const
currentEmployee
=
shallowRef
<
EmployeeInfoApi
.
Employee
|
null
>
(
null
);
const
loading
=
ref
(
false
);
async
function
handleOpenChange
(
open
:
boolean
)
{
if
(
!
open
)
{
return
null
;
}
const
{
id
}
=
drawerApi
.
getData
()
as
{
id
?:
number
};
if
(
!
id
)
{
return
null
;
}
const
data
=
await
apiInfoDetail
(
id
);
currentEmployee
.
value
=
data
;
}
// const actionInfo = computed(() => {
// if (!currentLog.value) {
// return '-';
// }
// const data = currentLog.value;
// // return `账号: ${data.operName} / ${data.deptName} / ${data.ip} / ${data.operLocation}`;
// return `账号: ${data.operName} / ${data.ip}`;
// });
</
script
>
<
template
>
<BasicDrawer
:footer=
"false"
class=
"w-[900px]"
title=
"员工信息"
>
<Skeleton
v-if=
"loading"
active
/>
<Descriptions
v-show=
"!loading"
v-if=
"currentEmployee"
size=
"small"
bordered
:column=
"2"
class=
"mb-1"
:label-style=
"
{
width: '140px',
fontWeight: 500,
backgroundColor: '#75e0e0',
}"
>
<template
#
title
>
<div
class=
"text-center"
>
部门信息
</div>
</
template
>
<DescriptionsItem
label=
"板块"
>
{{ currentEmployee.plate }}
</DescriptionsItem>
<DescriptionsItem
label=
"项目"
>
{{ currentEmployee.project }}
</DescriptionsItem>
<DescriptionsItem
label=
"一级部门"
>
{{ currentEmployee.firstLevelDepartment }}
</DescriptionsItem>
<DescriptionsItem
label=
"二级部门"
>
{{ currentEmployee.secondLevelDepartment }}
</DescriptionsItem>
<DescriptionsItem
label=
"工号"
>
{{ currentEmployee.employeeId }}
</DescriptionsItem>
<DescriptionsItem
label=
"职级"
>
{{ currentEmployee.jobLevel }}
</DescriptionsItem>
<DescriptionsItem
label=
"岗位"
>
{{ currentEmployee.position }}
</DescriptionsItem>
<DescriptionsItem
label=
"职务"
>
{{ currentEmployee.post }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show=
"!loading"
v-if=
"currentEmployee"
size=
"small"
bordered
:column=
"2"
class=
"mb-1"
:label-style=
"{
width: '140px',
fontWeight: 500,
backgroundColor: '#75e0e0',
}"
>
<
template
#
title
>
<div
class=
"text-center"
>
员工信息
</div>
</
template
>
<DescriptionsItem
label=
"姓名"
>
{{ currentEmployee.name }}
</DescriptionsItem>
<DescriptionsItem
label=
"性别"
>
{{ currentEmployee.genderName }}
</DescriptionsItem>
<DescriptionsItem
label=
"身份证号码"
>
{{ currentEmployee.idCardNumber }}
</DescriptionsItem>
<DescriptionsItem
label=
"手机号"
>
{{ currentEmployee.phoneNumber }}
</DescriptionsItem>
<DescriptionsItem
label=
"出生日期"
>
{{ currentEmployee.birthDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"年龄"
>
{{ currentEmployee.age }}
</DescriptionsItem>
<DescriptionsItem
label=
"籍贯"
>
{{ currentEmployee.nativePlace }}
</DescriptionsItem>
<DescriptionsItem
label=
"民族"
>
{{ currentEmployee.ethnicity }}
</DescriptionsItem>
<DescriptionsItem
label=
"婚姻状况"
>
{{ currentEmployee.maritalStatusName }}
</DescriptionsItem>
<DescriptionsItem
label=
"政治面貌"
>
{{ currentEmployee.politicalStatusName }}
</DescriptionsItem>
<DescriptionsItem
label=
"紧急联系人"
>
{{ currentEmployee.emergencyContact }}
</DescriptionsItem>
<DescriptionsItem
label=
"紧急联系人电话"
>
{{ currentEmployee.emergencyContactPhone }}
</DescriptionsItem>
<DescriptionsItem
label=
"家庭地址"
>
{{ currentEmployee.homeAddress }}
</DescriptionsItem>
<DescriptionsItem
label=
"户口所在地"
>
{{ currentEmployee.householdRegistrationAddress }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show=
"!loading"
v-if=
"currentEmployee"
size=
"small"
bordered
:column=
"2"
class=
"mb-1"
:label-style=
"{
width: '140px',
fontWeight: 500,
backgroundColor: '#75e0e0',
}"
>
<
template
#
title
>
<div
class=
"text-center"
>
教育信息
</div>
</
template
>
<DescriptionsItem
label=
"学历"
>
{{ currentEmployee.education }}
</DescriptionsItem>
<DescriptionsItem
label=
"学位"
>
{{ currentEmployee.degree }}
</DescriptionsItem>
<DescriptionsItem
label=
"毕业时间"
>
{{ currentEmployee.graduationDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"专业"
>
{{ currentEmployee.major }}
</DescriptionsItem>
<DescriptionsItem
label=
"毕业院校"
>
{{ currentEmployee.graduateSchool }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show=
"!loading"
v-if=
"currentEmployee"
size=
"small"
bordered
:column=
"2"
class=
"mb-1"
:label-style=
"{
width: '140px',
fontWeight: 500,
backgroundColor: '#75e0e0',
}"
>
<
template
#
title
>
<div
class=
"text-center"
>
职业信息
</div>
</
template
>
<DescriptionsItem
label=
"参加工作时间"
>
{{ currentEmployee.workStartDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"入职时间"
>
{{ currentEmployee.entryDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"转正时间"
>
{{ currentEmployee.regularizationDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"工龄"
>
{{ currentEmployee.yearsOfService }}
</DescriptionsItem>
<DescriptionsItem
label=
"工龄段"
>
{{ currentEmployee.yearsOfServiceSegmentName }}
</DescriptionsItem>
<DescriptionsItem
label=
"员工类型"
>
{{ currentEmployee.employeeTypeName }}
</DescriptionsItem>
<DescriptionsItem
label=
"用工形式"
>
{{ currentEmployee.employmentFormName }}
</DescriptionsItem>
<DescriptionsItem
label=
"职称情况"
>
{{ currentEmployee.professionalTitle }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show=
"!loading"
v-if=
"currentEmployee"
size=
"small"
bordered
:column=
"2"
class=
"mb-1"
:label-style=
"{
width: '150px',
fontWeight: 500,
backgroundColor: '#75e0e0',
}"
>
<
template
#
title
>
<div
class=
"text-center"
>
合同信息
</div>
</
template
>
<DescriptionsItem
label=
"劳动合同期限"
>
{{ currentEmployee.contractTerm }}
</DescriptionsItem>
<DescriptionsItem
label=
"劳动合同开始时间"
>
{{ currentEmployee.contractStartDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"劳动合同截止时间"
>
{{ currentEmployee.contractEndDate }}
</DescriptionsItem>
<DescriptionsItem
label=
"合同到期提醒"
>
{{ currentEmployee.contractExpirationReminder }}
</DescriptionsItem>
<DescriptionsItem
label=
"合同主体"
>
{{ currentEmployee.contractEntity }}
</DescriptionsItem>
<DescriptionsItem
label=
"劳动合同签订情况"
>
{{ currentEmployee.contractSigningStatus }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show=
"!loading"
v-if=
"currentEmployee"
size=
"small"
bordered
:column=
"1"
class=
"mb-1"
:label-style=
"{
width: '140px',
fontWeight: 500,
backgroundColor: '#75e0e0',
}"
>
<
template
#
title
>
<div
class=
"text-center"
>
其他信息
</div>
</
template
>
<DescriptionsItem
label=
"异动情况"
>
{{ currentEmployee.transferStatus }}
</DescriptionsItem>
<DescriptionsItem
label=
"奖惩情况"
>
{{ currentEmployee.rewardPunishmentStatus }}
</DescriptionsItem>
<DescriptionsItem
label=
"备注"
>
{{ currentEmployee.remarks }}
</DescriptionsItem>
<!-- <DescriptionsItem label="请求参数">
<div class="max-h-[300px] overflow-y-auto">
<component :is="renderJsonPreview(currentLog.params)" />
</div>
</DescriptionsItem>
<DescriptionsItem v-if="currentLog.result" label="响应参数">
<div class="max-h-[300px] overflow-y-auto">
<component :is="renderJsonPreview(currentLog.result)" />
</div>
</DescriptionsItem>
<DescriptionsItem label="请求耗时">
{{ `${currentLog.costTime} ms` }}
</DescriptionsItem>
<DescriptionsItem label="操作时间">
{{ `${currentLog.createTime}` }}
</DescriptionsItem> -->
</Descriptions>
</BasicDrawer>
</template>
apps/web-antd/src/views/hr/employeeInfo/list.vue
View file @
a336722d
...
...
@@ -6,16 +6,19 @@ import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import
{
Page
,
useVbenDrawer
,
useVbenModal
}
from
'@vben/common-ui'
;
import
{
Plus
}
from
'@vben/icons'
;
import
{
getVxePopupContainer
}
from
'@vben/utils'
;
import
{
Button
,
message
,
Popconfirm
,
Space
}
from
'ant-design-vue'
;
import
{
Button
,
Space
}
from
'ant-design-vue'
;
import
{
useVbenVxeGrid
}
from
'#/adapter/vxe-table'
;
import
{
apiExport
,
apiPage
,
applyResign
}
from
'#/api/hr/employeeInfo'
;
import
{
apiExport
,
apiPage
}
from
'#/api/hr/employeeInfo'
;
import
{
GhostButton
}
from
'#/components/global/button'
;
import
{
commonDownloadExcel
}
from
'#/utils/file/download'
;
import
applyEntryModel
from
'./apply-entry-model.vue'
;
import
applyResignModel
from
'./apply-resign-model.vue'
;
import
applyTransferModel
from
'./apply-transfer-model.vue'
;
import
{
querySchema
,
useColumns
}
from
'./data'
;
import
employeeDetailDrawer
from
'./employee-detail-drawer.vue'
;
import
employeeImportModal
from
'./employee-import-modal.vue'
;
import
Form
from
'./form.vue'
;
...
...
@@ -29,6 +32,16 @@ function handleImport() {
employeeImportModalApi
.
open
();
}
const
[
ApplyEntryModel
,
applyEntryModelApi
]
=
useVbenModal
({
connectedComponent
:
applyEntryModel
,
});
const
[
ApplyTransferModel
,
applyTransferModelApi
]
=
useVbenModal
({
connectedComponent
:
applyTransferModel
,
});
const
[
ApplyResignModel
,
applyResignModelApi
]
=
useVbenModal
({
connectedComponent
:
applyResignModel
,
});
const
formOptions
:
VbenFormProps
=
{
commonConfig
:
{
labelWidth
:
80
,
...
...
@@ -51,6 +64,9 @@ const formOptions: VbenFormProps = {
const
[
FormDrawer
,
formDrawerApi
]
=
useVbenDrawer
({
connectedComponent
:
Form
,
});
const
[
EmployeeDetailDrawer
,
employeeDetailDrawerApi
]
=
useVbenDrawer
({
connectedComponent
:
employeeDetailDrawer
,
});
const
[
Grid
,
gridApi
]
=
useVbenVxeGrid
({
formOptions
,
...
...
@@ -80,55 +96,26 @@ const [Grid, gridApi] = useVbenVxeGrid({
}
as
VxeTableGridOptions
,
});
// function onActionClick({
// code,
// row,
// }: OnActionClickParams
<
EmployeeInfoApi
.
Employee
>
)
{
// switch (code) {
// case 'delete': {
// onResign(row);
// break;
// }
// case 'edit': {
// onEdit(row);
// break;
// }
// case 'export': {
// handleDownloadExcel(row);
// break;
// }
// default: {
// break;
// }
// }
// }
function
onRefresh
()
{
gridApi
.
query
();
}
function
onEdit
(
row
:
EmployeeInfoApi
.
Employee
)
{
formDrawerApi
.
setData
({
id
:
row
.
id
}).
open
();
// formDrawerApi.setData({ id: row.id }).open();
employeeDetailDrawerApi
.
setData
({
id
:
row
.
id
}).
open
();
}
function
onCreate
()
{
formDrawerApi
.
setData
({}).
open
();
}
function
onEntryApply
(
row
:
EmployeeInfoApi
.
Employee
)
{
applyEntryModelApi
.
setData
({
id
:
row
.
id
,
name
:
row
.
name
}).
open
();
}
function
onResign
(
row
:
EmployeeInfoApi
.
Employee
)
{
const
hideLoading
=
message
.
loading
({
content
:
`正在处理
${
row
.
name
}
的离职...`
,
duration
:
0
,
key
:
'action_process_msg'
,
});
applyResign
(
row
.
id
||
0
)
.
then
(()
=>
{
message
.
success
({
content
:
`
${
row
.
name
}
离职申请成功`
,
key
:
'action_process_msg'
,
});
onRefresh
();
})
.
catch
(()
=>
{
hideLoading
();
});
applyResignModelApi
.
setData
({
id
:
row
.
id
,
name
:
row
.
name
}).
open
();
}
function
onTransfer
(
row
:
EmployeeInfoApi
.
Employee
)
{
applyTransferModelApi
.
setData
({
id
:
row
.
id
,
name
:
row
.
name
}).
open
();
}
function
handleDownloadExcel
(
row
:
EmployeeInfoApi
.
Employee
)
{
commonDownloadExcel
(
apiExport
,
'员工信息'
,
row
.
id
);
...
...
@@ -137,6 +124,7 @@ function handleDownloadExcel(row: EmployeeInfoApi.Employee) {
<
template
>
<Page
auto-content-height
>
<FormDrawer
@
success=
"onRefresh"
/>
<EmployeeDetailDrawer
/>
<Grid
table-title=
"员工信息列表"
>
<template
#
toolbar-tools
>
<Space>
...
...
@@ -146,12 +134,6 @@ function handleDownloadExcel(row: EmployeeInfoApi.Employee) {
>
导入
</Button>
<!--
<Button
v-access:code=
"['employee:info:export']"
@
click=
"handleDownloadExcel"
>
导出
</Button>
-->
<Button
v-access:code=
"['employee:info:add']"
type=
"primary"
...
...
@@ -180,32 +162,34 @@ function handleDownloadExcel(row: EmployeeInfoApi.Employee) {
v-access:code=
"['employee:info:edit']"
@
click
.
stop=
"onEdit(row)"
>
编辑
查看
</GhostButton>
<GhostButton
v-access:code=
"['employee:info:add']"
@
click
.
stop=
"onEntryApply(row)"
>
申请入职
</GhostButton>
<
!--
<
GhostButton
v-access:code=
"['
auth:role
:edit']"
@
click
.
stop=
"on
AssignRole
(row)"
<GhostButton
v-access:code=
"['
employee:info
:edit']"
@
click
.
stop=
"on
Transfer
(row)"
>
分配
</GhostButton>
-->
<Popconfirm
:get-popup-container=
"getVxePopupContainer"
placement=
"left"
:title=
"`确认申请离职【$
{row.name}】?`"
@confirm="onResign(row)"
申请调配
</GhostButton>
<GhostButton
danger
v-access:code=
"['employee:info:resign']"
@
click
.
stop=
"onResign(row)"
>
<GhostButton
danger
v-access:code=
"['employee:info:resign']"
@
click
.
stop=
""
>
申请离职
</GhostButton>
</Popconfirm>
申请离职
</GhostButton>
</Space>
<!--
</
template
>
-->
</template>
</Grid>
<EmployeeImportModal
@
reload=
"onRefresh"
/>
<ApplyEntryModel
@
reload=
"onRefresh"
/>
<ApplyTransferModel
@
reload=
"onRefresh"
/>
<ApplyResignModel
@
reload=
"onRefresh"
/>
</Page>
</template>
apps/web-antd/src/views/workflow/components/flow-preview.vue
View file @
a336722d
...
...
@@ -7,7 +7,7 @@ import { useWarmflowIframe } from './hook';
defineOptions
({
name
:
'FlowPreview'
});
const
props
=
defineProps
<
{
instanceId
:
string
}
>
();
const
props
=
defineProps
<
{
instanceId
:
number
}
>
();
const
{
clientId
}
=
useAppConfig
(
import
.
meta
.
env
,
import
.
meta
.
env
.
PROD
);
...
...
apps/web-antd/src/views/workflow/hrFlow/data.ts
0 → 100644
View file @
a336722d
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
VxeTableGridOptions
}
from
'#/adapter/vxe-table'
;
import
type
{
EmployeeFlowApi
}
from
'#/api/hr/employeeFlow'
;
import
{
DictEnum
}
from
'@vben/constants'
;
import
{
getTagDicts
}
from
'#/utils/dict'
;
export
const
flowTypeOptions
=
[
{
label
:
'入职'
,
value
:
'1'
},
{
label
:
'离职'
,
value
:
'2'
},
{
label
:
'调配'
,
value
:
'3'
},
];
export
const
querySchema
:
VbenFormSchema
[]
=
[
{
component
:
'Input'
,
fieldName
:
'applyCode'
,
label
:
'申请编号'
,
},
{
component
:
'Select'
,
componentProps
:
{
options
:
flowTypeOptions
,
},
fieldName
:
'flowType'
,
label
:
'审批类型'
,
},
// {
// component: 'DatePicker',
// fieldName: 'startDate',
// label: '开始时间',
// },
// {
// component: 'DatePicker',
// fieldName: 'endDate',
// label: '结束时间',
// },
];
export
function
useColumns
():
VxeTableGridOptions
<
EmployeeFlowApi
.
EmployeeFlow
>
[
'columns'
]
{
// onActionClick: OnActionClickFn<EmployeeFlowApi.EmployeeFlow>,
return
[
{
title
:
'申请编号'
,
field
:
'applyCode'
,
},
{
title
:
'审批类型'
,
field
:
'flowType'
,
cellRender
:
{
name
:
'CellTag'
,
options
:
flowTypeOptions
},
},
// {
// title: '员工信息ID',
// field: 'employeeId',
// },
{
title
:
'开始时间'
,
field
:
'startDate'
,
formatter
:
'formatDateTime'
,
},
{
title
:
'结束时间'
,
field
:
'endDate'
,
formatter
:
'formatDateTime'
,
},
{
title
:
'状态'
,
field
:
'status'
,
cellRender
:
{
name
:
'CellTag'
,
options
:
[
getTagDicts
(
DictEnum
.
WF_BUSINESS_STATUS
)],
},
},
{
title
:
'备注'
,
field
:
'remark'
,
},
{
align
:
'right'
,
slots
:
{
default
:
'action'
},
// cellRender: {
// attrs: {
// nameField: 'name',
// nameTitle: '人事审批对象',
// onClick: onActionClick,
// },
// name: 'CellOperation',
// options: [
// {
// code: 'edit',
// accessCode: ['employee:flow:edit'],
// }, // 默认的编辑按钮
// {
// code: 'delete',
// accessCode: ['employee:flow:remove'],
// }, // 默认的删除按钮
// ],
// },
field
:
'action'
,
fixed
:
'right'
,
headerAlign
:
'center'
,
resizable
:
false
,
showOverflow
:
false
,
title
:
'操作'
,
width
:
'auto'
,
},
];
}
apps/web-antd/src/views/workflow/hrFlow/form.vue
0 → 100644
View file @
a336722d
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
EmployeeFlowApi
}
from
'#/api/hr/employeeFlow'
;
import
{
computed
,
ref
}
from
'vue'
;
import
{
useVbenDrawer
}
from
'@vben/common-ui'
;
import
{
useVbenForm
}
from
'#/adapter/form'
;
import
{
apiAdd
,
apiUpdate
}
from
'#/api/hr/employeeFlow'
;
import
{
defaultFormValueGetter
,
useBeforeCloseDiff
}
from
'#/utils/popup'
;
const
emit
=
defineEmits
<
{
success
:
[];
}
>
();
const
formData
=
ref
<
EmployeeFlowApi
.
EmployeeFlow
>
();
const
formSchema
:
VbenFormSchema
[]
=
[
{
component
:
'Input'
,
fieldName
:
'applyCode'
,
label
:
'申请编号'
,
rules
:
'required'
,
},
{
component
:
'Select'
,
componentProps
:
{},
fieldName
:
'flowType'
,
label
:
'审批类型'
,
rules
:
'selectRequired'
,
},
{
component
:
'Input'
,
fieldName
:
'employeeId'
,
label
:
'员工信息ID'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'startDate'
,
label
:
'开始时间'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'endDate'
,
label
:
'结束时间'
,
rules
:
'required'
,
},
{
component
:
'RadioGroup'
,
componentProps
:
{
buttonStyle
:
'solid'
,
optionType
:
'button'
,
},
fieldName
:
'status'
,
label
:
'状态'
,
rules
:
'required'
,
},
{
component
:
'Textarea'
,
fieldName
:
'remark'
,
label
:
'备注'
,
rules
:
'required'
,
},
];
const
[
BasicForm
,
formApi
]
=
useVbenForm
({
commonConfig
:
{
componentProps
:
{
class
:
'w-full'
,
},
formItemClass
:
'col-span-2'
,
labelWidth
:
90
,
},
schema
:
formSchema
,
showDefaultActions
:
false
,
wrapperClass
:
'grid-cols-2'
,
});
const
{
onBeforeClose
,
markInitialized
,
resetInitialized
}
=
useBeforeCloseDiff
(
{
initializedGetter
:
defaultFormValueGetter
(
formApi
),
currentGetter
:
defaultFormValueGetter
(
formApi
),
},
);
const
[
Drawer
,
drawerApi
]
=
useVbenDrawer
({
onBeforeClose
,
onClosed
:
handleClosed
,
onConfirm
:
onSubmit
,
async
onOpenChange
(
isOpen
)
{
if
(
!
isOpen
)
{
return
null
;
}
const
data
=
drawerApi
.
getData
<
EmployeeFlowApi
.
EmployeeFlow
>
();
if
(
data
)
{
formData
.
value
=
data
;
await
formApi
.
setValues
(
formData
.
value
);
}
else
{
formApi
.
resetForm
();
}
await
markInitialized
();
},
});
async
function
onSubmit
()
{
const
{
valid
}
=
await
formApi
.
validate
();
if
(
valid
)
{
drawerApi
.
lock
();
const
data
=
await
formApi
.
getValues
<
EmployeeFlowApi
.
EmployeeFlow
>
();
try
{
await
(
formData
.
value
?.
id
?
apiUpdate
({
id
:
formData
.
value
.
id
,
...
data
})
:
apiAdd
(
data
));
resetInitialized
();
emit
(
'success'
);
drawerApi
.
close
();
}
finally
{
drawerApi
.
unlock
();
}
}
}
async
function
handleClosed
()
{
await
formApi
.
resetForm
();
resetInitialized
();
}
const
getDrawerTitle
=
computed
(()
=>
formData
.
value
?.
id
?
'修改人事审批对象'
:
'新增人事审批对象'
,
);
</
script
>
<
template
>
<Drawer
class=
"w-full max-w-[800px]"
:title=
"getDrawerTitle"
>
<BasicForm
class=
"mx-4"
/>
</Drawer>
</
template
>
apps/web-antd/src/views/workflow/hrFlow/hr-description.vue
0 → 100644
View file @
a336722d
<
script
setup
lang=
"ts"
>
import
type
{
EmployeeFlowApi
}
from
'#/api/hr/employeeFlow'
;
import
{
computed
,
onMounted
,
shallowRef
}
from
'vue'
;
import
{
useVbenDrawer
}
from
'@vben/common-ui'
;
import
{
Button
,
Descriptions
,
DescriptionsItem
,
Skeleton
,
}
from
'ant-design-vue'
;
import
{
apiDetail
}
from
'#/api/hr/employeeFlow'
;
import
employeeDetailDrawer
from
'#/views/hr/employeeInfo/employee-detail-drawer.vue'
;
import
{
flowTypeOptions
}
from
'./data'
;
defineOptions
({
name
:
'HrDescription'
,
inheritAttrs
:
false
,
});
const
props
=
defineProps
<
{
businessId
:
number
|
string
}
>
();
const
data
=
shallowRef
<
EmployeeFlowApi
.
EmployeeFlowVo
>
();
onMounted
(
async
()
=>
{
const
resp
=
await
apiDetail
(
props
.
businessId
);
data
.
value
=
resp
;
});
const
[
EmployeeDetailDrawer
,
employeeDetailDrawerApi
]
=
useVbenDrawer
({
connectedComponent
:
employeeDetailDrawer
,
});
const
flowType
=
computed
(()
=>
{
return
(
flowTypeOptions
.
find
((
item
)
=>
item
.
value
===
data
.
value
?.
flowType
)
?.
label
??
'未知'
);
});
function
showEmployeeDetail
()
{
// formDrawerApi.setData({ id: row.id }).open();
employeeDetailDrawerApi
.
setData
({
id
:
data
.
value
?.
employeeId
}).
open
();
}
// function formatDate(date: string) {
// return dayjs(date).format('YYYY-MM-DD');
// }
</
script
>
<
template
>
<div
class=
"rounded-[6px] border p-2"
>
<EmployeeDetailDrawer
/>
<Descriptions
v-if=
"data"
:column=
"1"
bordered
size=
"middle"
:label-style=
"
{ width: '150px' }"
>
<DescriptionsItem
label=
"审批类型"
>
{{
flowType
}}
</DescriptionsItem>
<!--
<DescriptionsItem
label=
"请假时间"
>
{{
formatDate
(
data
.
startDate
)
}}
-
{{
formatDate
(
data
.
endDate
)
}}
</DescriptionsItem>
-->
<DescriptionsItem
label=
"员工信息详情"
>
<Button
type=
"link"
@
click=
"showEmployeeDetail()"
>
点击查看员工信息
</Button>
</DescriptionsItem>
<template
v-if=
"data.auditLogList"
>
<DescriptionsItem
v-for=
"(auditLog, index) in data.auditLogList"
:label=
"auditLog.auditFieldName"
:key=
"index"
>
{{
auditLog
.
afterVal
}}
</DescriptionsItem>
</
template
>
<DescriptionsItem
label=
"内容"
>
{{ data.remark || '无' }}
</DescriptionsItem>
</Descriptions>
<Skeleton
active
v-else
/>
</div>
</template>
apps/web-antd/src/views/workflow/hrFlow/list.vue
0 → 100644
View file @
a336722d
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormProps
}
from
'@vben/common-ui'
;
import
type
{
VxeTableGridOptions
}
from
'#/adapter/vxe-table'
;
import
type
{
EmployeeFlowApi
}
from
'#/api/hr/employeeFlow'
;
import
{
Page
,
useVbenDrawer
,
useVbenModal
}
from
'@vben/common-ui'
;
import
{
Plus
}
from
'@vben/icons'
;
import
{
getVxePopupContainer
}
from
'@vben/utils'
;
import
{
Button
,
message
,
Popconfirm
,
Space
}
from
'ant-design-vue'
;
import
{
useVbenVxeGrid
}
from
'#/adapter/vxe-table'
;
import
{
apiDelete
,
apiExport
,
apiPage
}
from
'#/api/hr/employeeFlow'
;
import
{
cancelProcessApply
}
from
'#/api/workflow/instance/index'
;
import
{
commonDownloadExcel
}
from
'#/utils/file/download'
;
import
{
applyModal
,
flowInfoModal
}
from
'../components'
;
import
{
querySchema
,
useColumns
}
from
'./data'
;
import
Form
from
'./form.vue'
;
const
formOptions
:
VbenFormProps
=
{
commonConfig
:
{
labelWidth
:
80
,
componentProps
:
{
allowClear
:
true
,
},
},
schema
:
querySchema
,
wrapperClass
:
'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'
,
};
const
[
ApplyModal
,
applyModalApi
]
=
useVbenModal
({
connectedComponent
:
applyModal
,
});
const
[
FlowInfoModal
,
flowInfoModalApi
]
=
useVbenModal
({
connectedComponent
:
flowInfoModal
,
});
const
[
FormDrawer
,
formDrawerApi
]
=
useVbenDrawer
({
connectedComponent
:
Form
,
});
const
[
Grid
,
gridApi
]
=
useVbenVxeGrid
({
formOptions
,
gridOptions
:
{
columns
:
useColumns
(),
height
:
'auto'
,
keepSource
:
true
,
pagerConfig
:
{
enabled
:
true
,
},
proxyConfig
:
{
ajax
:
{
query
:
async
({
page
},
formValues
=
{})
=>
{
return
await
apiPage
({
pageNo
:
page
.
currentPage
,
pageSize
:
page
.
pageSize
,
...
formValues
,
});
},
},
},
rowConfig
:
{
keyField
:
'id'
,
// 高亮当前行
isCurrent
:
true
,
},
}
as
VxeTableGridOptions
,
gridEvents
:
{
cellClick
:
({
row
,
column
})
=>
{
// 草稿状态 不做处理
// 操作列 不做处理
if
(
row
.
status
===
'draft'
||
column
.
field
===
'action'
)
{
return
;
}
// 查看详情
handleInfo
(
row
);
},
},
});
function
onRefresh
()
{
gridApi
.
query
();
}
function
onEdit
(
row
:
EmployeeFlowApi
.
EmployeeFlow
)
{
formDrawerApi
.
setData
(
row
).
open
();
}
function
onCreate
()
{
formDrawerApi
.
setData
({}).
open
();
}
function
onDelete
(
row
:
EmployeeFlowApi
.
EmployeeFlow
)
{
const
hideLoading
=
message
.
loading
({
content
:
`正在删除
${
row
.
applyCode
}
...`
,
duration
:
0
,
key
:
'action_process_msg'
,
});
apiDelete
(
row
.
id
||
0
)
.
then
(()
=>
{
message
.
success
({
content
:
`
${
row
.
applyCode
}
删除成功`
,
key
:
'action_process_msg'
,
});
onRefresh
();
})
.
catch
(()
=>
{
hideLoading
();
});
}
function
handleDownloadExcel
()
{
commonDownloadExcel
(
apiExport
,
'人事审批列表'
,
gridApi
.
formApi
.
form
.
values
);
}
async
function
handleRevoke
(
row
:
Required
<
EmployeeFlowApi
.
EmployeeFlow
>
)
{
await
cancelProcessApply
({
businessId
:
row
.
id
,
message
:
'申请人撤销流程!'
,
});
await
gridApi
.
query
();
}
async
function
handleCompleteOrCancel
()
{
formDrawerApi
.
close
();
gridApi
.
query
();
}
function
handleInfo
(
row
:
Required
<
EmployeeFlowApi
.
EmployeeFlow
>
)
{
flowInfoModalApi
.
setData
({
businessId
:
row
.
id
});
flowInfoModalApi
.
open
();
}
</
script
>
<
template
>
<Page
auto-content-height
>
<FormDrawer
@
success=
"onRefresh"
/>
<Grid
table-title=
"人事审批列表"
>
<template
#
toolbar-tools
>
<Space>
<Button
v-access:code=
"['employee:flow:export']"
@
click=
"handleDownloadExcel"
>
导出
</Button>
<Button
v-access:code=
"['employee:flow:add']"
type=
"primary"
@
click=
"onCreate"
>
<Plus
class=
"size-5"
/>
新增
</Button>
</Space>
</
template
>
<
template
#
action=
"{ row }"
>
<Button
size=
"small"
type=
"link"
:disabled=
"!['draft', 'cancel', 'back'].includes(row.status)"
v-access:code=
"['employee:flow:edit']"
@
click
.
stop=
"onEdit(row)"
>
修改
</Button>
<Popconfirm
:get-popup-container=
"getVxePopupContainer"
placement=
"left"
title=
"确认撤销?"
:disabled=
"!['waiting'].includes(row.status)"
@
confirm
.
stop=
"handleRevoke(row)"
@
cancel
.
stop=
""
>
<Button
size=
"small"
type=
"link"
:disabled=
"!['waiting'].includes(row.status)"
v-access:code=
"['employee:flow:edit']"
@
click
.
stop=
""
>
撤销
</Button>
</Popconfirm>
<Popconfirm
:get-popup-container=
"getVxePopupContainer"
placement=
"left"
title=
"确认删除?"
:disabled=
"!['draft', 'cancel', 'back'].includes(row.status)"
@
confirm
.
stop=
"onDelete(row)"
@
cancel
.
stop=
""
>
<Button
size=
"small"
type=
"link"
:disabled=
"!['draft', 'cancel', 'back'].includes(row.status)"
danger
v-access:code=
"['employee:flow:remove']"
@
click
.
stop=
""
>
删除
</Button>
</Popconfirm>
</
template
>
</Grid>
<FlowInfoModal
/>
<ApplyModal
@
complete=
"handleCompleteOrCancel"
@
cancel=
"handleCompleteOrCancel"
/>
</Page>
</template>
apps/web-antd/src/views/workflow/processDefinition/category-tree.vue
View file @
a336722d
...
...
@@ -45,6 +45,7 @@ async function loadTree() {
const
treeData
=
await
categoryTree
();
categoryTreeArray
.
value
=
treeData
;
console
.
log
(
'[categoryTreeArray]'
,
categoryTreeArray
);
showTreeSkeleton
.
value
=
false
;
}
...
...
apps/web-antd/src/views/workflow/register.ts
View file @
a336722d
...
...
@@ -8,6 +8,10 @@ const LeaveDescription = defineAsyncComponent(
()
=>
import
(
'#/views/workflow/leave/leave-description.vue'
),
);
const
EmployeeDescription
=
defineAsyncComponent
(
()
=>
import
(
'#/views/workflow/hrFlow/hr-description.vue'
),
);
/**
* key为流程的路径(task.formPath) value为要显示的组件
*/
...
...
@@ -16,6 +20,7 @@ export const flowComponentsMap = {
* 请假申请 详情
*/
'/workflow/leaveEdit/index'
:
markRaw
(
LeaveDescription
),
'/hr/employee/flow'
:
markRaw
(
EmployeeDescription
),
};
export
type
FlowComponentsMapMapKey
=
keyof
typeof
flowComponentsMap
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment