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
bf1ac72a
Commit
bf1ac72a
authored
Oct 30, 2025
by
刘斌
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 增加人事管理-预览
parent
3ed4afd8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1645 additions
and
1 deletion
+1645
-1
employeeInfo.ts
apps/web-antd/src/api/hr/employeeInfo.ts
+276
-0
access.ts
apps/web-antd/src/router/access.ts
+1
-1
hr.ts
apps/web-antd/src/router/routes/modules/hr.ts
+31
-0
dict-enum.ts
apps/web-antd/src/views/hr/dict-enum.ts
+21
-0
data.ts
apps/web-antd/src/views/hr/employeeInfo/data.ts
+497
-0
employee-import-modal.vue
...-antd/src/views/hr/employeeInfo/employee-import-modal.vue
+115
-0
form.vue
apps/web-antd/src/views/hr/employeeInfo/form.vue
+493
-0
list.vue
apps/web-antd/src/views/hr/employeeInfo/list.vue
+211
-0
No files found.
apps/web-antd/src/api/hr/employeeInfo.ts
0 → 100644
View file @
bf1ac72a
import
type
{
BaseModel
,
PageQuery
}
from
'#/api/baseModel'
;
import
{
commonExport
}
from
'#/api/helper'
;
import
{
requestClient
}
from
'#/api/request'
;
export
namespace
EmployeeInfoApi
{
export
interface
Employee
extends
BaseModel
{
/**
* 板块
*/
plate
?:
string
;
/**
* 项目
*/
project
?:
string
;
/**
* 一级部门
*/
firstLevelDepartment
?:
string
;
/**
* 二级部门
*/
secondLevelDepartment
?:
string
;
/**
* 工号
*/
employeeId
?:
number
;
/**
* 职级
*/
jobLevel
?:
string
;
/**
* 岗位
*/
position
?:
string
;
/**
* 职务
*/
post
?:
string
;
/**
* 姓名
*/
name
?:
string
;
/**
* 性别
*/
gender
?:
string
;
/**
* 身份证号码
*/
idCardNumber
?:
number
;
/**
* 出生日期
*/
birthDate
?:
string
;
/**
* 年龄
*/
age
?:
number
;
/**
* 年龄段
*/
ageGroup
?:
string
;
/**
* 籍贯
*/
nativePlace
?:
string
;
/**
* 民族
*/
ethnicity
?:
string
;
/**
* 婚姻状况
*/
maritalStatus
?:
string
;
/**
* 政治面貌
*/
politicalStatus
?:
string
;
/**
* 手机号码
*/
phoneNumber
?:
string
;
/**
* 紧急联系人
*/
emergencyContact
?:
string
;
/**
* 紧急联系人电话
*/
emergencyContactPhone
?:
string
;
/**
* 家庭地址
*/
homeAddress
?:
string
;
/**
* 户口所在地
*/
householdRegistrationAddress
?:
string
;
/**
* 参加工作时间
*/
workStartDate
?:
string
;
/**
* 入职时间
*/
entryDate
?:
string
;
/**
* 工龄
*/
yearsOfService
?:
number
;
/**
* 工龄段
*/
yearsOfServiceSegment
?:
string
;
/**
* 学历
*/
education
?:
string
;
/**
* 学位
*/
degree
?:
string
;
/**
* 毕业时间
*/
graduationDate
?:
string
;
/**
* 专业
*/
major
?:
string
;
/**
* 毕业院校
*/
graduateSchool
?:
string
;
/**
* 员工类型
*/
employeeType
?:
string
;
/**
* 职称情况
*/
professionalTitle
?:
string
;
/**
* 简历
*/
resume
?:
string
;
/**
* 用工形式
*/
employmentForm
?:
string
;
/**
* 劳动合同期限
*/
contractTerm
?:
string
;
/**
* 劳动合同开始时间
*/
contractStartDate
?:
string
;
/**
* 劳动合同截止时间
*/
contractEndDate
?:
string
;
/**
* 合同到期提醒
*/
contractExpirationReminder
?:
string
;
/**
* 劳动合同签订情况
*/
contractSigningStatus
?:
string
;
/**
* 合同主体
*/
contractEntity
?:
string
;
/**
* 转正时间
*/
regularizationDate
?:
string
;
/**
* 异动情况
*/
transferStatus
?:
string
;
/**
* 奖惩情况
*/
rewardPunishmentStatus
?:
string
;
/**
* 备注
*/
remarks
?:
string
;
/**
* 离职时间
*/
resignationDate
?:
string
;
/**
* 离职原因
*/
resignationReason
?:
string
;
}
}
/**
* 查询员工信息列表
* @param params
* @returns {*} page
*/
export
function
apiPage
(
params
:
PageQuery
)
{
return
requestClient
.
get
(
'/employee/info/page'
,
{
params
});
}
/**
* 查询员工信息详细
* @param id
*/
export
function
apiDetail
(
id
:
number
)
{
return
requestClient
.
get
(
`/employee/info/
${
id
}
`
);
}
/**
* 新增员工信息
* @param data
*/
export
function
apiAdd
(
data
:
EmployeeInfoApi
.
Employee
)
{
return
requestClient
.
post
(
'/employee/info'
,
data
);
}
/**
* 修改员工信息
* @param data
*/
export
function
apiUpdate
(
data
:
EmployeeInfoApi
.
Employee
)
{
return
requestClient
.
put
(
'/employee/info'
,
data
);
}
/**
* 删除员工信息
* @param id
*/
export
function
apiDelete
(
id
:
Array
<
number
>
|
number
)
{
return
requestClient
.
delete
(
`/employee/info/
${
id
}
`
);
}
/**
* 导出员工信息
* @param params
*/
export
function
apiExport
(
id
:
number
)
{
return
commonExport
(
`/employee/info/export/
${
id
}
`
,
{});
}
/**
* 下载用户导入模板
* @returns blob
*/
export
function
downloadImportTemplate
()
{
return
commonExport
(
'/employee/info/importTemplate'
,
{});
}
/**
* 从excel导入用户
* @param file
* @returns void
*/
export
function
employeeImportData
(
file
:
Blob
)
{
return
requestClient
.
post
<
{
errMessage
:
string
;
success
:
boolean
}
>
(
'/employee/info/excel/import'
,
{
file
},
{
headers
:
{
'Content-Type'
:
'multipart/form-data;charset=UTF-8'
,
},
isTransformResponse
:
false
,
responseReturn
:
'body'
,
},
);
}
apps/web-antd/src/router/access.ts
View file @
bf1ac72a
...
...
@@ -79,7 +79,7 @@ function hasPermission(menuSet: Set<string>, route: RouteRecordRaw) {
async
function
generateAccess
(
options
:
GenerateMenuAndRoutesOptions
)
{
const
pageMap
:
ComponentRecordType
=
import
.
meta
.
glob
(
'../views/**/*.vue'
);
console
.
warn
(
'[pageMap]'
,
pageMap
);
//
console.warn('[pageMap]', pageMap);
const
layoutMap
:
ComponentRecordType
=
{
BasicLayout
,
...
...
apps/web-antd/src/router/routes/modules/hr.ts
0 → 100644
View file @
bf1ac72a
import
type
{
RouteRecordRaw
}
from
'vue-router'
;
const
routes
:
RouteRecordRaw
[]
=
[
// 人事管理
{
path
:
'/hr'
,
name
:
'HrManagement'
,
meta
:
{
title
:
'人事管理'
,
keepAlive
:
true
,
icon
:
'streamline-ultimate:human-resources-hierarchy-1'
,
permission
:
[
'dashboard'
],
},
children
:
[
{
path
:
'/hr/employee/list'
,
name
:
'EmployeeInfoList'
,
component
:
()
=>
import
(
'#/views/hr/employeeInfo/list.vue'
),
meta
:
{
title
:
'员工信息列表'
,
icon
:
'clarity:employee-line'
,
keepAlive
:
true
,
permission
:
[
'dashboard'
],
componentPath
:
'#/views/hr/employeeInfo/list.vue'
,
},
},
],
},
];
export
default
routes
;
apps/web-antd/src/views/hr/dict-enum.ts
0 → 100644
View file @
bf1ac72a
export
const
HrDictEnum
=
{
HR_USER_SEX
:
'hr_user_sex'
,
HR_AGE_GROUP
:
'hr_age_group'
,
HR_MARITAL_STATUS
:
'hr_marital_status'
,
// 设备类型
HR_POLITICAL_STATUS
:
'hr_political_status'
,
// 授权类型
HR_YEARS_SERVICE_SEGMENT
:
'hr_years_service_segment'
,
HR_EDUCATION
:
'hr_education'
,
// 通知状态
HR_EMPLOYEE_TYPE
:
'hr_employee_type'
,
// 通知类型
HR_EMPLOYMENT_FORM
:
'hr_employment_form'
,
// 操作类型
// SYS_JOB_TYPE: 'sys_job_type', // 定时任务类型
// SYS_JOB_STATUS: 'sys_job_status', // 定时任务状态
// SYS_OSS_ACCESS_POLICY: 'oss_access_policy', // oss权限桶类型
// SYS_SHOW_HIDE: 'sys_show_hide', // 显示状态
// SYS_USER_SEX: 'sys_user_sex', // 性别
// SYS_YES_NO: 'sys_yes_no', // 是否
// WF_BUSINESS_STATUS: 'wf_business_status', // 业务状态
// WF_FORM_TYPE: 'wf_form_type', // 表单类型
// WF_TASK_STATUS: 'wf_task_status', // 任务状态
}
as
const
;
export
type
HrDictEnumKey
=
keyof
typeof
HrDictEnum
;
apps/web-antd/src/views/hr/employeeInfo/data.ts
0 → 100644
View file @
bf1ac72a
This diff is collapsed.
Click to expand it.
apps/web-antd/src/views/hr/employeeInfo/employee-import-modal.vue
0 → 100644
View file @
bf1ac72a
<
script
setup
lang=
"ts"
>
import
type
{
UploadFile
}
from
'ant-design-vue/es/upload/interface'
;
import
{
h
,
ref
}
from
'vue'
;
import
{
useVbenModal
}
from
'@vben/common-ui'
;
import
{
ExcelIcon
,
InBoxIcon
}
from
'@vben/icons'
;
import
{
Button
,
Modal
,
Upload
}
from
'ant-design-vue'
;
import
{
downloadImportTemplate
,
employeeImportData
,
}
from
'#/api/hr/employeeInfo'
;
import
{
commonDownloadExcel
}
from
'#/utils/file/download'
;
const
emit
=
defineEmits
<
{
reload
:
[]
}
>
();
const
UploadDragger
=
Upload
.
Dragger
;
const
[
BasicModal
,
modalApi
]
=
useVbenModal
({
onCancel
:
handleCancel
,
onConfirm
:
handleSubmit
,
});
const
fileList
=
ref
<
UploadFile
[]
>
([]);
// const checked = ref(false);
async
function
handleSubmit
()
{
try
{
modalApi
.
modalLoading
(
true
);
if
(
fileList
.
value
.
length
!==
1
)
{
handleCancel
();
return
;
}
// const data = {
// file: fileList.value[0]!.originFileObj as Blob,
// updateSupport: unref(checked),
// };
const
{
success
,
errMessage
}
=
await
employeeImportData
(
fileList
.
value
[
0
]
!
.
originFileObj
as
Blob
,
);
let
modal
=
Modal
.
success
;
if
(
success
)
{
emit
(
'reload'
);
}
else
{
modal
=
Modal
.
error
;
}
handleCancel
();
modal
({
content
:
h
(
'div'
,
{
class
:
'max-h-[260px] overflow-y-auto'
,
innerHTML
:
errMessage
,
// 后台已经处理xss问题
}),
title
:
'提示'
,
});
}
catch
(
error
)
{
console
.
warn
(
error
);
modalApi
.
close
();
}
finally
{
modalApi
.
modalLoading
(
false
);
}
}
function
handleCancel
()
{
modalApi
.
close
();
fileList
.
value
=
[];
// checked.value = false;
}
</
script
>
<
template
>
<BasicModal
:close-on-click-modal=
"false"
:fullscreen-button=
"false"
title=
"员工信息导入"
>
<!-- z-index不设置会遮挡模板下载loading -->
<!-- 手动处理 而不是放入文件就上传 -->
<UploadDragger
v-model:file-list=
"fileList"
:before-upload=
"() => false"
:max-count=
"1"
:show-upload-list=
"true"
accept=
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
>
<p
class=
"ant-upload-drag-icon flex items-center justify-center"
>
<InBoxIcon
class=
"text-primary size-[48px]"
/>
</p>
<p
class=
"ant-upload-text"
>
点击或者拖拽到此处上传文件
</p>
</UploadDragger>
<div
class=
"mt-2 flex flex-col gap-2"
>
<div
class=
"flex items-center gap-2"
>
<span>
允许导入xlsx, xls文件
</span>
<Button
type=
"link"
@
click=
"
commonDownloadExcel(downloadImportTemplate, '员工信息导入模板')
"
>
<div
class=
"flex items-center gap-[4px]"
>
<ExcelIcon
/>
<span>
下载模板
</span>
</div>
</Button>
</div>
<!--
<div
class=
"flex items-center gap-2"
>
<span
:class=
"
{ 'text-red-500': checked }">
是否更新/覆盖已存在的用户数据
</span>
<Switch
v-model:checked=
"checked"
/>
</div>
-->
</div>
</BasicModal>
</
template
>
apps/web-antd/src/views/hr/employeeInfo/form.vue
0 → 100644
View file @
bf1ac72a
This diff is collapsed.
Click to expand it.
apps/web-antd/src/views/hr/employeeInfo/list.vue
0 → 100644
View file @
bf1ac72a
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormProps
}
from
'@vben/common-ui'
;
import
type
{
VxeTableGridOptions
}
from
'#/adapter/vxe-table'
;
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
{
useVbenVxeGrid
}
from
'#/adapter/vxe-table'
;
import
{
apiDelete
,
apiExport
,
apiPage
}
from
'#/api/hr/employeeInfo'
;
import
{
GhostButton
}
from
'#/components/global/button'
;
import
{
commonDownloadExcel
}
from
'#/utils/file/download'
;
import
{
querySchema
,
useColumns
}
from
'./data'
;
import
employeeImportModal
from
'./employee-import-modal.vue'
;
import
Form
from
'./form.vue'
;
/**
* 导入
*/
const
[
EmployeeImportModal
,
employeeImportModalApi
]
=
useVbenModal
({
connectedComponent
:
employeeImportModal
,
});
function
handleImport
()
{
employeeImportModalApi
.
open
();
}
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'
,
// 日期选择格式化
fieldMappingTime
:
[
[
'entryDate'
,
[
'params[entryBeginTime]'
,
'params[entryEndTime]'
],
[
'YYYY-MM-DD 00:00:00'
,
'YYYY-MM-DD 23:59:59'
],
],
],
};
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
,
});
// 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
(
row
).
open
();
}
function
onCreate
()
{
formDrawerApi
.
setData
({}).
open
();
}
function
onResign
(
row
:
EmployeeInfoApi
.
Employee
)
{
const
hideLoading
=
message
.
loading
({
content
:
`正在处理
${
row
.
name
}
的离职...`
,
duration
:
0
,
key
:
'action_process_msg'
,
});
apiDelete
(
row
.
id
||
0
)
.
then
(()
=>
{
message
.
success
({
content
:
`
${
row
.
name
}
离职申请成功`
,
key
:
'action_process_msg'
,
});
onRefresh
();
})
.
catch
(()
=>
{
hideLoading
();
});
}
function
handleDownloadExcel
(
row
:
EmployeeInfoApi
.
Employee
)
{
commonDownloadExcel
(
apiExport
,
'员工信息'
,
row
.
id
);
}
</
script
>
<
template
>
<Page
auto-content-height
>
<FormDrawer
@
success=
"onRefresh"
/>
<Grid
table-title=
"员工信息列表"
>
<template
#
toolbar-tools
>
<Space>
<Button
v-access:code=
"['employee:info:import']"
@
click=
"handleImport"
>
导入
</Button>
<!--
<Button
v-access:code=
"['employee:info:export']"
@
click=
"handleDownloadExcel"
>
导出
</Button>
-->
<Button
v-access:code=
"['employee:info:add']"
type=
"primary"
@
click=
"onCreate"
>
<Plus
class=
"size-5"
/>
入职
</Button>
</Space>
</
template
>
<
template
#
action=
"{ row }"
>
<!-- 租户管理员不可修改admin角色 防止误操作 -->
<!-- 超级管理员可通过租户切换来操作租户管理员角色 -->
<!-- -->
<!--
<template
v-if=
"!row.superAdmin && (row.roleKey !== 'admin' || isSuperAdmin)"
>
-->
<Space>
<GhostButton
v-access:code=
"['employee:info:export']"
@
click
.
stop=
"handleDownloadExcel(row)"
>
导出简历
</GhostButton>
<GhostButton
v-access:code=
"['employee:info:edit']"
@
click
.
stop=
"onEdit(row)"
>
编辑
</GhostButton>
<!--
<GhostButton
v-access:code=
"['auth:role:edit']"
@
click
.
stop=
"onAssignRole(row)"
>
分配
</GhostButton>
-->
<Popconfirm
:get-popup-container=
"getVxePopupContainer"
placement=
"left"
:title=
"`确认离职【$
{row.name}】?`"
@confirm="onResign(row)"
>
<GhostButton
danger
v-access:code=
"['employee:info:resign']"
@
click
.
stop=
""
>
离职
</GhostButton>
</Popconfirm>
</Space>
<!--
</
template
>
-->
</template>
</Grid>
<EmployeeImportModal
@
reload=
"onRefresh"
/>
</Page>
</template>
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