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
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) {
...
@@ -79,7 +79,7 @@ function hasPermission(menuSet: Set<string>, route: RouteRecordRaw) {
async
function
generateAccess
(
options
:
GenerateMenuAndRoutesOptions
)
{
async
function
generateAccess
(
options
:
GenerateMenuAndRoutesOptions
)
{
const
pageMap
:
ComponentRecordType
=
import
.
meta
.
glob
(
'../views/**/*.vue'
);
const
pageMap
:
ComponentRecordType
=
import
.
meta
.
glob
(
'../views/**/*.vue'
);
console
.
warn
(
'[pageMap]'
,
pageMap
);
//
console.warn('[pageMap]', pageMap);
const
layoutMap
:
ComponentRecordType
=
{
const
layoutMap
:
ComponentRecordType
=
{
BasicLayout
,
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
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
VxeTableGridOptions
}
from
'#/adapter/vxe-table'
;
import
type
{
EmployeeInfoApi
}
from
'#/api/hr/employeeInfo'
;
import
{
getDictOptions
}
from
'#/utils/dict'
;
import
{
HrDictEnum
}
from
'../dict-enum'
;
export
const
querySchema
:
VbenFormSchema
[]
=
[
{
component
:
'Input'
,
fieldName
:
'plate'
,
label
:
'板块'
,
},
{
component
:
'Input'
,
fieldName
:
'project'
,
label
:
'项目'
,
},
{
component
:
'Input'
,
fieldName
:
'firstLevelDepartment'
,
label
:
'一级部门'
,
},
{
component
:
'Input'
,
fieldName
:
'secondLevelDepartment'
,
label
:
'二级部门'
,
},
{
component
:
'Input'
,
fieldName
:
'employeeId'
,
label
:
'工号'
,
},
{
component
:
'Input'
,
fieldName
:
'jobLevel'
,
label
:
'职级'
,
},
{
component
:
'Input'
,
fieldName
:
'position'
,
label
:
'岗位'
,
},
{
component
:
'Input'
,
fieldName
:
'post'
,
label
:
'职务'
,
},
{
component
:
'Input'
,
fieldName
:
'name'
,
label
:
'姓名'
,
},
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_USER_SEX
),
},
fieldName
:
'gender'
,
label
:
'性别'
,
},
// {
// component: 'Input',
// fieldName: 'idCardNumber',
// label: '身份证号码',
// },
// {
// component: 'DatePicker',
// fieldName: 'birthDate',
// label: '出生日期',
// },
// {
// component: 'Input',
// fieldName: 'age',
// label: '年龄',
// },
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_AGE_GROUP
),
},
fieldName
:
'ageGroup'
,
label
:
'年龄段'
,
},
// {
// component: 'Input',
// fieldName: 'nativePlace',
// label: '籍贯',
// },
// {
// component: 'Input',
// fieldName: 'ethnicity',
// label: '民族',
// },
{
component
:
'Input'
,
fieldName
:
'phoneNumber'
,
label
:
'手机号码'
,
},
// {
// component: 'Input',
// fieldName: 'emergencyContact',
// label: '紧急联系人',
// },
// {
// component: 'Input',
// fieldName: 'emergencyContactPhone',
// label: '紧急联系人电话',
// },
// {
// component: 'Input',
// fieldName: 'homeAddress',
// label: '家庭地址',
// },
// {
// component: 'Input',
// fieldName: 'householdRegistrationAddress',
// label: '户口所在地',
// },
// {
// component: 'DatePicker',
// fieldName: 'workStartDate',
// label: '参加工作',
// },
{
component
:
'RangePicker'
,
fieldName
:
'entryDate'
,
label
:
'入职时间'
,
componentProps
:
{
valueFormat
:
'YYYY-MM-DD'
,
},
},
// {
// component: 'Input',
// fieldName: 'yearsOfService',
// label: '工龄',
// },
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_YEARS_SERVICE_SEGMENT
),
},
fieldName
:
'yearsOfServiceSegment'
,
label
:
'工龄段'
,
},
// {
// component: 'Input',
// fieldName: 'education',
// label: '学历',
// },
// {
// component: 'Input',
// fieldName: 'degree',
// label: '学位',
// },
// {
// component: 'DatePicker',
// fieldName: 'graduationDate',
// label: '毕业时间',
// },
// {
// component: 'Input',
// fieldName: 'major',
// label: '专业',
// },
// {
// component: 'Input',
// fieldName: 'graduateSchool',
// label: '毕业院校',
// },
// {
// component: 'Input',
// fieldName: 'professionalTitle',
// label: '职称情况',
// },
// {
// component: 'Input',
// fieldName: 'resume',
// label: '简历',
// },
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_EMPLOYMENT_FORM
),
},
fieldName
:
'employmentForm'
,
label
:
'用工形式'
,
},
// {
// component: 'Input',
// fieldName: 'contractTerm',
// label: '劳动合同期限',
// },
// {
// component: 'DatePicker',
// fieldName: 'contractStartDate',
// label: '劳动合同开始时间',
// },
// {
// component: 'DatePicker',
// fieldName: 'contractEndDate',
// label: '劳动合同截止时间',
// },
// {
// component: 'DatePicker',
// fieldName: 'contractExpirationReminder',
// label: '合同到期提醒',
// },
// {
// component: 'Input',
// fieldName: 'contractEntity',
// label: '合同主体',
// },
// {
// component: 'DatePicker',
// fieldName: 'regularizationDate',
// label: '转正时间',
// },
// {
// component: 'Input',
// fieldName: 'remarks',
// label: '备注',
// },
// {
// component: 'DatePicker',
// fieldName: 'resignationDate',
// label: '离职时间',
// },
// {
// component: 'Input',
// fieldName: 'resignationReason',
// label: '离职原因',
// },
];
export
function
useColumns
():
VxeTableGridOptions
<
EmployeeInfoApi
.
Employee
>
[
'columns'
]
{
// onActionClick: OnActionClickFn<EmployeeInfoApi.Employee>,
return
[
{
title
:
'板块'
,
field
:
'plate'
,
},
{
title
:
'项目'
,
field
:
'project'
,
},
{
title
:
'一级部门'
,
field
:
'firstLevelDepartment'
,
},
{
title
:
'二级部门'
,
field
:
'secondLevelDepartment'
,
},
{
title
:
'工号'
,
field
:
'employeeId'
,
},
// {
// title: '职级',
// field: 'jobLevel',
// },
{
title
:
'岗位'
,
field
:
'position'
,
},
{
title
:
'职务'
,
field
:
'post'
,
},
{
title
:
'姓名'
,
field
:
'name'
,
},
{
title
:
'性别'
,
field
:
'genderName'
,
// cellRender: {
// name: 'CellTag',
// options: [getTagDicts(HrDictEnum.HR_USER_SEX)],
// },
},
// {
// title: '身份证号码',
// field: 'idCardNumber',
// },
// {
// title: '出生日期',
// field: 'birthDate',
// formatter: 'formatDateTime',
// },
// {
// title: '年龄',
// field: 'age',
// },
// {
// title: '年龄段',
// field: 'ageGroup',
// },
// {
// title: '籍贯',
// field: 'nativePlace',
// },
// {
// title: '民族',
// field: 'ethnicity',
// },
// {
// title: '婚姻状况',
// field: 'maritalStatus',
// cellRender: { name: 'CellTag', options: [getTagDicts()] },
// },
// {
// title: '政治面貌',
// field: 'politicalStatus',
// cellRender: { name: 'CellTag', options: [getTagDicts()] },
// },
{
title
:
'手机号码'
,
field
:
'phoneNumber'
,
},
// {
// title: '紧急联系人',
// field: 'emergencyContact',
// },
// {
// title: '紧急联系人电话',
// field: 'emergencyContactPhone',
// },
// {
// title: '家庭地址',
// field: 'homeAddress',
// },
// {
// title: '户口所在地',
// field: 'householdRegistrationAddress',
// },
// {
// title: '参加工作时间',
// field: 'workStartDate',
// formatter: 'formatDateTime',
// },
// {
// title: '入职时间',
// field: 'entryDate',
// formatter: 'formatDateTime',
// },
// {
// title: '工龄',
// field: 'yearsOfService',
// },
// {
// title: '工龄段',
// field: 'yearsOfServiceSegment',
// },
{
title
:
'学历'
,
field
:
'education'
,
},
// {
// title: '学位',
// field: 'degree',
// },
// {
// title: '毕业时间',
// field: 'graduationDate',
// formatter: 'formatDateTime',
// },
// {
// title: '专业',
// field: 'major',
// },
// {
// title: '毕业院校',
// field: 'graduateSchool',
// },
{
title
:
'员工类型'
,
field
:
'employeeTypeName'
,
// cellRender: {
// name: 'CellTag',
// options: [getTagDicts(HrDictEnum.HR_EMPLOYEE_TYPE)],
// },
},
// {
// title: '职称情况',
// field: 'professionalTitle',
// },
// {
// title: '简历',
// field: 'resume',
// },
{
title
:
'用工形式'
,
field
:
'employmentFormName'
,
// cellRender: {
// name: 'CellTag',
// options: [getTagDicts(HrDictEnum.HR_EMPLOYMENT_FORM)],
// },
},
{
title
:
'劳动合同期限'
,
field
:
'contractTerm'
,
},
// {
// title: '劳动合同开始时间',
// field: 'contractStartDate',
// formatter: 'formatDateTime',
// },
// {
// title: '劳动合同截止时间',
// field: 'contractEndDate',
// formatter: 'formatDateTime',
// },
// {
// title: '合同到期提醒',
// field: 'contractExpirationReminder',
// formatter: 'formatDateTime',
// },
// {
// title: '劳动合同签订情况',
// field: 'contractSigningStatus',
// cellRender: { name: 'CellTag', options: [getTagDicts()] },
// },
// {
// title: '合同主体',
// field: 'contractEntity',
// },
// {
// title: '转正时间',
// field: 'regularizationDate',
// formatter: 'formatDateTime',
// },
// {
// title: '异动情况',
// field: 'transferStatus',
// cellRender: { name: 'CellTag', options: [getTagDicts()] },
// },
// {
// title: '奖惩情况',
// field: 'rewardPunishmentStatus',
// cellRender: { name: 'CellTag', options: [getTagDicts()] },
// },
// {
// title: '备注',
// field: 'remarks',
// },
// {
// title: '离职时间',
// field: 'resignationDate',
// formatter: 'formatDateTime',
// },
// {
// title: '离职原因',
// field: 'resignationReason',
// },
{
align
:
'right'
,
slots
:
{
default
:
'action'
},
// cellRender: {
// attrs: {
// nameField: 'name',
// nameTitle: '员工信息',
// onClick: onActionClick,
// },
// name: 'CellOperation',
// options: [
// {
// code: 'export',
// text: '导出简历',
// // disabled: (row: SysUserApi.User) => {
// // return !!(row.id === 1);
// // },
// accessCode: ['employee:info:export'],
// },
// {
// code: 'edit',
// accessCode: ['employee:info:edit'],
// }, // 默认的编辑按钮
// {
// code: 'delete',
// text: '离职',
// accessCode: ['employee:info:remove'],
// }, // 默认的删除按钮
// ],
// },
field
:
'action'
,
fixed
:
'right'
,
headerAlign
:
'center'
,
resizable
:
false
,
showOverflow
:
false
,
title
:
'操作'
,
width
:
'auto'
,
},
];
}
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
<
script
lang=
"ts"
setup
>
import
type
{
VbenFormSchema
}
from
'#/adapter/form'
;
import
type
{
EmployeeInfoApi
}
from
'#/api/hr/employeeInfo'
;
import
{
computed
,
ref
}
from
'vue'
;
import
{
useVbenDrawer
}
from
'@vben/common-ui'
;
import
{
Skeleton
}
from
'ant-design-vue'
;
import
{
useVbenForm
}
from
'#/adapter/form'
;
import
{
apiAdd
,
apiUpdate
}
from
'#/api/hr/employeeInfo'
;
import
{
getDictOptions
}
from
'#/utils/dict'
;
import
{
defaultFormValueGetter
,
useBeforeCloseDiff
}
from
'#/utils/popup'
;
import
{
HrDictEnum
}
from
'../dict-enum'
;
const
emit
=
defineEmits
<
{
success
:
[];
}
>
();
const
formData
=
ref
<
EmployeeInfoApi
.
Employee
>
();
const
loading
=
ref
(
false
);
const
formSchema
:
VbenFormSchema
[]
=
[
{
component
:
'Divider'
,
componentProps
:
{
orientation
:
'center'
,
},
fieldName
:
'divider1'
,
formItemClass
:
'col-span-2'
,
hideLabel
:
true
,
renderComponentContent
:
()
=>
({
default
:
()
=>
'部门信息'
,
}),
},
{
component
:
'Input'
,
fieldName
:
'plate'
,
label
:
'板块'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'project'
,
label
:
'项目'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'firstLevelDepartment'
,
label
:
'一级部门'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'secondLevelDepartment'
,
label
:
'二级部门'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'employeeId'
,
label
:
'工号'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'jobLevel'
,
label
:
'职级'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'position'
,
label
:
'岗位'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'post'
,
label
:
'职务'
,
rules
:
'required'
,
},
{
component
:
'Divider'
,
componentProps
:
{
orientation
:
'center'
,
},
fieldName
:
'divider1'
,
formItemClass
:
'col-span-2'
,
hideLabel
:
true
,
renderComponentContent
:
()
=>
({
default
:
()
=>
'员工信息'
,
}),
},
{
component
:
'Input'
,
fieldName
:
'name'
,
label
:
'姓名'
,
rules
:
'required'
,
},
{
component
:
'RadioGroup'
,
componentProps
:
{
buttonStyle
:
'solid'
,
optionType
:
'button'
,
options
:
getDictOptions
(
HrDictEnum
.
HR_USER_SEX
),
},
defaultValue
:
'1'
,
fieldName
:
'gender'
,
label
:
'性别'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'idCardNumber'
,
label
:
'身份证号码'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'birthDate'
,
label
:
'出生日期'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'age'
,
label
:
'年龄'
,
rules
:
'required'
,
},
// {
// component: 'Input',
// fieldName: 'ageGroup',
// label: '年龄段',
// rules: 'required',
// },
{
component
:
'Input'
,
fieldName
:
'nativePlace'
,
label
:
'籍贯'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'ethnicity'
,
label
:
'民族'
,
rules
:
'required'
,
},
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_MARITAL_STATUS
),
},
fieldName
:
'maritalStatus'
,
label
:
'婚姻状况'
,
rules
:
'selectRequired'
,
},
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_POLITICAL_STATUS
),
},
fieldName
:
'politicalStatus'
,
label
:
'政治面貌'
,
rules
:
'selectRequired'
,
},
{
component
:
'Input'
,
fieldName
:
'phoneNumber'
,
label
:
'手机号码'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'emergencyContact'
,
label
:
'紧急联系人'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'emergencyContactPhone'
,
label
:
'紧急联系人电话'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'homeAddress'
,
label
:
'家庭地址'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'householdRegistrationAddress'
,
label
:
'户口所在地'
,
rules
:
'required'
,
},
{
component
:
'Divider'
,
componentProps
:
{
orientation
:
'center'
,
},
fieldName
:
'divider1'
,
formItemClass
:
'col-span-2'
,
hideLabel
:
true
,
renderComponentContent
:
()
=>
({
default
:
()
=>
'教育信息'
,
}),
},
{
component
:
'Input'
,
fieldName
:
'education'
,
label
:
'学历'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'degree'
,
label
:
'学位'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'graduationDate'
,
label
:
'毕业时间'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'major'
,
label
:
'专业'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'graduateSchool'
,
label
:
'毕业院校'
,
rules
:
'required'
,
},
{
component
:
'Divider'
,
componentProps
:
{
orientation
:
'center'
,
},
fieldName
:
'divider1'
,
formItemClass
:
'col-span-2'
,
hideLabel
:
true
,
renderComponentContent
:
()
=>
({
default
:
()
=>
'职业信息'
,
}),
},
{
component
:
'DatePicker'
,
fieldName
:
'workStartDate'
,
label
:
'参加工作时间'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'entryDate'
,
label
:
'入职时间'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'regularizationDate'
,
label
:
'转正时间'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'yearsOfService'
,
label
:
'工龄'
,
rules
:
'required'
,
},
// {
// component: 'Input',
// fieldName: 'yearsOfServiceSegment',
// label: '工龄段',
// rules: 'required',
// },
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_EMPLOYEE_TYPE
),
},
fieldName
:
'employeeType'
,
label
:
'员工类型'
,
rules
:
'selectRequired'
,
},
{
component
:
'Select'
,
componentProps
:
{
options
:
getDictOptions
(
HrDictEnum
.
HR_EMPLOYMENT_FORM
),
},
fieldName
:
'employmentForm'
,
label
:
'用工形式'
,
rules
:
'selectRequired'
,
},
{
component
:
'Input'
,
fieldName
:
'professionalTitle'
,
label
:
'职称情况'
,
// rules: 'required',
},
{
component
:
'Input'
,
fieldName
:
'resume'
,
label
:
'简历'
,
// rules: 'required',
},
{
component
:
'Divider'
,
componentProps
:
{
orientation
:
'center'
,
},
fieldName
:
'divider1'
,
formItemClass
:
'col-span-2'
,
hideLabel
:
true
,
renderComponentContent
:
()
=>
({
default
:
()
=>
'合同信息'
,
}),
},
{
component
:
'Input'
,
fieldName
:
'contractTerm'
,
label
:
'劳动合同期限'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'contractStartDate'
,
label
:
'劳动合同开始时间'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'contractEndDate'
,
label
:
'劳动合同截止时间'
,
rules
:
'required'
,
},
{
component
:
'DatePicker'
,
fieldName
:
'contractExpirationReminder'
,
label
:
'合同到期提醒'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
fieldName
:
'contractEntity'
,
label
:
'合同主体'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
// componentProps: {
// buttonStyle: 'solid',
// optionType: 'button',
// },
fieldName
:
'contractSigningStatus'
,
label
:
'劳动合同签订情况'
,
formItemClass
:
'col-span-2'
,
// rules: 'required',
},
{
component
:
'Divider'
,
componentProps
:
{
orientation
:
'center'
,
},
fieldName
:
'divider1'
,
formItemClass
:
'col-span-2'
,
hideLabel
:
true
,
renderComponentContent
:
()
=>
({
default
:
()
=>
'其他信息'
,
}),
},
{
component
:
'Input'
,
// componentProps: {
// buttonStyle: 'solid',
// optionType: 'button',
// },
fieldName
:
'transferStatus'
,
formItemClass
:
'col-span-2'
,
label
:
'异动情况'
,
rules
:
'required'
,
},
{
component
:
'Input'
,
// componentProps: {
// buttonStyle: 'solid',
// optionType: 'button',
// },
fieldName
:
'rewardPunishmentStatus'
,
formItemClass
:
'col-span-2'
,
label
:
'奖惩情况'
,
rules
:
'required'
,
},
{
component
:
'Textarea'
,
fieldName
:
'remarks'
,
formItemClass
:
'col-span-2'
,
label
:
'备注'
,
// rules: 'required',
},
// {
// component: 'DatePicker',
// fieldName: 'resignationDate',
// label: '离职时间',
// rules: 'required',
// },
// {
// component: 'Textarea',
// fieldName: 'resignationReason',
// label: '离职原因',
// rules: 'required',
// },
];
const
[
BasicForm
,
formApi
]
=
useVbenForm
({
commonConfig
:
{
componentProps
:
{
class
:
'w-full'
,
formItemClass
:
'col-span-1'
,
},
// formItemClass: 'col-span-2',
labelWidth
:
130
,
},
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
<
EmployeeInfoApi
.
Employee
>
();
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
<
EmployeeInfoApi
.
Employee
>
();
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-[900px]"
:title=
"getDrawerTitle"
>
<Skeleton
v-if=
"loading"
active
/>
<BasicForm
v-show=
"!loading"
class=
"mx-4"
/>
</Drawer>
</
template
>
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