Commit fc891eb2 authored by 刘斌's avatar 刘斌

feat: 增加离职管理

parent 19435678
......@@ -35,7 +35,7 @@ export function uploadApi(
) {
const { onUploadProgress, signal, otherData = {} } = options ?? {};
return requestClient.upload<UploadResult>(
'/resource/oss/upload',
'/system/oss/upload',
{ file, ...otherData },
{ onUploadProgress, signal, timeout: 60_000 },
);
......
......@@ -25,5 +25,6 @@ export function commonExport(url: string, data: Record<string, any>) {
// transformResponse: false,
responseReturn: 'body',
responseType: 'blob',
timeout: 600_000,
});
}
import type { BaseModel, PageQuery } from '#/api/baseModel';
import type { EmployeeInfoApi } from './employeeModel';
import type { 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;
genderName?: string;
/**
* 身份证号码
*/
idCardNumber?: number;
/**
* 出生日期
*/
birthDate?: string;
/**
* 年龄
*/
age?: number;
/**
* 年龄段
*/
ageGroup?: string;
/**
* 籍贯
*/
nativePlace?: string;
/**
* 民族
*/
ethnicity?: string;
/**
* 婚姻状况
*/
maritalStatus?: string;
maritalStatusName?: string;
/**
* 政治面貌
*/
politicalStatus?: string;
politicalStatusName?: string;
/**
* 手机号码
*/
phoneNumber?: string;
/**
* 紧急联系人
*/
emergencyContact?: string;
/**
* 紧急联系人电话
*/
emergencyContactPhone?: string;
/**
* 家庭地址
*/
homeAddress?: string;
/**
* 户口所在地
*/
householdRegistrationAddress?: string;
/**
* 参加工作时间
*/
workStartDate?: string;
/**
* 入职时间
*/
entryDate?: string;
/**
* 工龄
*/
yearsOfService?: number;
/**
* 工龄段
*/
yearsOfServiceSegment?: string;
yearsOfServiceSegmentName?: string;
/**
* 学历
*/
education?: string;
/**
* 学位
*/
degree?: string;
/**
* 毕业时间
*/
graduationDate?: string;
/**
* 专业
*/
major?: string;
/**
* 毕业院校
*/
graduateSchool?: string;
/**
* 员工类型
*/
employeeType?: string;
employeeTypeName?: string;
/**
* 职称情况
*/
professionalTitle?: string;
/**
* 简历
*/
resume?: string;
/**
* 用工形式
*/
employmentForm?: string;
employmentFormName?: 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;
}
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;
}
}
/**
* 查询员工信息列表
* @param params
......@@ -286,6 +48,13 @@ export function apiUpdate(data: EmployeeInfoApi.Employee) {
export function apiDelete(id: Array<number> | number) {
return requestClient.delete(`/employee/info/${id}`);
}
/**
* 导出员工信息列表
* @param params
*/
export function exportEmployeeList(params: PageQuery) {
return commonExport('/employee/info/export', params);
}
/**
* 导出员工信息
* @param params
......
import type { BaseModel } from '#/api/baseModel';
export namespace EmployeeInfoApi {
export interface Employee extends BaseModel {
/**
* 板块
*/
plate?: string;
/**
* 一级部门
*/
firstLevelDepartment?: string;
/**
* 二级部门
*/
secondLevelDepartment?: string;
/**
* 三级部门
*/
thirdLevelDepartment?: string;
/**
* 部门ID
*/
deptId?: number;
/**
* 工号
*/
employeeId?: number;
/**
* 职级
*/
jobLevel?: number;
/**
* 岗位类型
*/
positionType?: string;
positionTypeName?: string;
/**
* 序列
*/
sequence?: string;
sequenceName?: string;
/**
* 主岗位
*/
position?: string;
/**
* 姓名
*/
name?: string;
/**
* 性别
*/
gender?: string;
genderName?: string;
/**
* 身份证号码
*/
idCardNumber?: number;
/**
* 照片
*/
photo?: string;
/**
* 图片ID
*/
ossId?: number;
/**
* 出生日期
*/
birthDate?: string;
/**
* 年龄
*/
age?: number;
/**
* 年龄段
*/
ageGroup?: string;
ageGroupName?: string;
/**
* 兼职板块
*/
partTimePlate?: string;
/**
* 兼职一级部门
*/
partTimeFirstDept?: string;
/**
* 兼职二级部门
*/
partTimeSecondDept?: string;
/**
* 兼职三级部门
*/
partTimeThirdDept?: string;
/**
* 兼职岗位
*/
partTimePosition?: string;
/**
* 籍贯
*/
nativePlace?: string;
/**
* 民族
*/
ethnicity?: string;
/**
* 婚姻状况
*/
maritalStatus?: string;
maritalStatusName?: string;
/**
* 政治面貌
*/
politicalStatus?: string;
politicalStatusName?: string;
/**
* 手机号码
*/
phoneNumber?: string;
/**
* 紧急联系人
*/
emergencyContact?: string;
/**
* 紧急联系人电话
*/
emergencyContactPhone?: string;
/**
* 家庭地址
*/
homeAddress?: string;
/**
* 户口所在地
*/
householdRegistrationAddress?: string;
/**
* 参加工作时间
*/
workStartDate?: string;
/**
* 入职时间
*/
entryDate?: string;
/**
* 工龄
*/
yearsOfService?: string;
/**
* 工龄段
*/
yearsOfServiceSegment?: string;
yearsOfServiceSegmentName?: string;
/**
* 全日制学历
*/
fulltimeEducation?: string;
/**
* 全日制毕业院校
*/
fulltimeSchool?: string;
/**
* 全日制专业
*/
fulltimeMajor?: string;
/**
* 全日制毕业日期
*/
fulltimeGraduationDate?: string;
/**
* 全日制学位
*/
fulltimeDegree?: string;
/**
* 非全日制学历
*/
nonFulltimeEducation?: string;
/**
* 非全日制毕业院校
*/
nonFulltimeSchool?: string;
/**
* 非全日制专业
*/
nonFulltimeMajor?: string;
/**
* 非全日制毕业日期
*/
nonFulltimeGraduationDate?: string;
/**
* 非全日制学位
*/
nonFulltimeDegree?: string;
/**
* 学历分类
*/
educationCategory?: string;
educationCategoryName?: string;
/**
* 员工类型
*/
employeeType?: string;
employeeTypeName?: string;
/**
* 职称情况
*/
professionalTitle?: string;
/**
* 证书情况
*/
certificateStatus?: string;
/**
* 外部个人履历
*/
externalResume?: string;
/**
* 内部个人履历
*/
internalResume?: string;
/**
* 用工形式
*/
employmentForm?: string;
employmentFormName?: string;
/**
* 合同形式
*/
contractForm?: string;
contractFormName?: string;
/**
* 劳动合同期限
*/
contractTerm?: string;
/**
* 劳动合同开始时间
*/
contractStartDate?: string;
/**
* 劳动合同截止时间
*/
contractEndDate?: string;
/**
* 合同到期提醒
*/
contractExpirationReminder?: string;
/**
* 劳动合同签订情况
*/
contractSigningStatus?: string;
/**
* 合同主体
*/
contractEntity?: string;
/**
* 社保主体
*/
socialSecurityEntity?: string;
/**
* 是否缴纳社保
*/
hasSocialSecurityPaid?: number;
hasSocialSecurityPaidName?: number;
/**
* 公积金主体
*/
providentFundEntity?: number;
/**
* 是否缴纳公积金
*/
hasProvidentFundPaid?: number;
hasProvidentFundPaidName?: number;
/**
* 试用期(月数)
*/
probationPeriod?: number;
/**
* 转正时间
*/
regularizationDate?: string;
/**
* 奖励情况
*/
rewardStatus?: string;
/**
* 处罚情况
*/
punishmentStatus?: string;
/**
* 备注
*/
remarks?: string;
/**
* 办公电话
*/
officePhone?: string;
/**
* 短线
*/
shortLine?: string;
/**
* 银行卡号
*/
bankCardNumber?: string;
/**
* 开户行
*/
bankName?: string;
/**
* 公司内是否有亲属关系
*/
hasRelativeInCompany?: string;
hasRelativeInCompanyName?: string;
/**
* 亲属姓名
*/
relativeName?: string;
/**
* 介绍人
*/
introducer?: string;
/**
* 工资发放地
*/
salaryLocation?: string;
/**
* 绩效比例
*/
performanceRatio?: string;
/**
* 离职类型
*/
resignationType?: string;
resignationTypeName?: string;
/**
* 离职时间
*/
resignationDate?: string;
/**
* 离职原因
*/
resignationReason?: string;
/**
* 最后结薪日
*/
finalPayDate?: string;
/**
* 离职申请状态
*/
resignationApplyStatus?: number;
resignationApplyStatusName?: number;
/**
* 入职审批状态
*/
entryApplyStatus?: number;
entryApplyStatusName?: number;
/**
* 调配申请状态
*/
transferApplyStatus?: number;
transferApplyStatusName?: number;
}
export interface EmployeeApplyBo {
/**
* 序号
*/
id?: number;
/**
* 入职时间
*/
entryDate?: Date;
/**
* 备注
*/
remark?: string;
}
export interface EmployeeTransferApplyBo extends EmployeeApplyBo {
/**
* 板块
*/
plate: string;
/**
* 一级部门
*/
firstLevelDepartment?: string;
/**
* 二级部门
*/
secondLevelDepartment?: string;
/**
* 三级部门
*/
thirdLevelDepartment?: string;
/**
* 部门ID
*/
deptId?: number;
}
export interface EmployeeResignApplyBo extends EmployeeApplyBo {
/**
* 离职类型
*/
resignationType: string;
/**
* 离职时间
*/
resignDate?: Date;
/**
* 离职原因
*/
resignReason?: string;
/**
* 最后结薪日
*/
finalPayDate?: Date;
}
}
// export interface EmployeeResign extends EmployeeInfoApi.Employee {
// }
import type { PageQuery } from '#/api/baseModel';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询员工信息列表
* @param params
* @returns {*} page
*/
export function apiPage(params: PageQuery) {
return requestClient.get('/employee/info/resign/page', { params });
}
// /**
// * 查询员工信息详细
// * @param id
// */
// export function apiDetail(id: number) {
// return requestClient.get(`/employee/resign/info/${id}`);
// }
/**
* 展示员工信息详细
* @param id
*/
export function apiInfoDetail(id: number) {
return requestClient.get(`/employee/info/resign/detail/${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 exportEmployeeList(params: PageQuery) {
return commonExport('/employee/info/resign/export', params);
}
// /**
// * 导出员工信息
// * @param params
// */
// 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 applyTransfer(data: EmployeeInfoApi.EmployeeTransferApplyBo) {
// return requestClient.post('/employee/info/applyTransfer', data);
// }
/**
* 下载用户导入模板
* @returns blob
*/
export function downloadImportTemplate() {
return commonExport('/employee/info/resign/importTemplate', {});
}
/**
* 从excel导入用户
* @param file
* @returns void
*/
export function employeeResignImportData(file: Blob) {
return requestClient.post<{ errMessage: string; success: boolean }>(
'/employee/info/resign/excel/import',
{ file },
{
headers: {
'Content-Type': 'multipart/form-data;charset=UTF-8',
},
isTransformResponse: false,
responseReturn: 'body',
timeout: 300_000,
},
);
}
......@@ -301,7 +301,7 @@ export function useUpload(
});
info.onSuccess!(res);
if (props.showSuccessMsg) {
message.success($t('component.upload.uploadSuccess'));
message.success('上传成功');
}
emit('success', info.file as RcFile, res);
} catch (error: any) {
......
......@@ -24,6 +24,18 @@ const routes: RouteRecordRaw[] = [
componentPath: '#/views/hr/employeeInfo/list.vue',
},
},
{
path: '/hr/resignEmployee/list',
name: 'ResignEmployeeList',
component: () => import('#/views/hr/employeeInfo/list.vue'),
meta: {
title: '离职员工列表',
icon: 'clarity:employee-line',
keepAlive: true,
permission: ['dashboard'],
componentPath: '#/views/hr/resignEmployee/list.vue',
},
},
{
name: 'EmployeeFlowList',
path: '/hr/employee/flow',
......
import { z } from '#/adapter/form';
// 校验码计算和验证函数
function verifyIDCardChecksum(idNumber: string): boolean {
if (idNumber.length !== 18) return false;
// 1. 权重因子 [citation:5][citation:6][citation:8]
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 2. 校验码对应表 [citation:5][citation:6][citation:8]
const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idNumber[i], 10) * weights[i];
}
const mod = sum % 11;
const expectedCheckCode = checkCodes[mod];
// 3. 检查最后一位校验码是否匹配(包括大小写X的处理)
return idNumber[17].toUpperCase() === expectedCheckCode;
}
// 定义并导出Zod模式
export const idCardSchema = z.string()
.min(1, { message: "身份证号不能为空" })
// 基础正则校验:基本格式和日期粗略校验
.regex(/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/, {
message: "身份证号码格式不正确"
})
// 自定义 refine 校验:校验码精确校验
.refine((id) => verifyIDCardChecksum(id), {
message: "身份证号码校验码错误"
});
......@@ -7,6 +7,12 @@ export const HrDictEnum = {
HR_EDUCATION: 'hr_education', // 通知状态
HR_EMPLOYEE_TYPE: 'hr_employee_type', // 通知类型
HR_EMPLOYMENT_FORM: 'hr_employment_form', // 操作类型
HR_JOB_LEVEL: "hr_job_level", // 员工职级
HR_POSITION_TYPE: "hr_position_type", // 员工岗位类型
HR_SEQUENCE: "hr_sequence", // 员工序列
HR_EDUCATION_CATEGORY: "hr_education_category", // 员工学历类别
HR_CONTRACT_FORM: "hr_contract_form", // 员工合同形式
HR_RESIGNATION_TYPE: "hr_resignation_type", // 员工离职类型
// SYS_JOB_TYPE: 'sys_job_type', // 定时任务类型
// SYS_JOB_STATUS: 'sys_job_status', // 定时任务状态
// SYS_OSS_ACCESS_POLICY: 'oss_access_policy', // oss权限桶类型
......
<script lang="ts" setup>
import type { VbenFormSchema } from '#/adapter/form';
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { ref } from 'vue';
......
<script lang="ts" setup>
import type { VbenFormSchema } from '#/adapter/form';
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { ref } from 'vue';
......
<script lang="ts" setup>
import type { VbenFormSchema } from '#/adapter/form';
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { ref } from 'vue';
......
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { getDictOptions } from '#/utils/dict';
......@@ -12,11 +12,6 @@ export const querySchema: VbenFormSchema[] = [
fieldName: 'plate',
label: '板块',
},
{
component: 'Input',
fieldName: 'project',
label: '项目',
},
{
component: 'Input',
fieldName: 'firstLevelDepartment',
......@@ -27,6 +22,11 @@ export const querySchema: VbenFormSchema[] = [
fieldName: 'secondLevelDepartment',
label: '二级部门',
},
{
component: 'Input',
fieldName: 'thirdLevelDepartment',
label: '三级部门',
},
{
component: 'Input',
fieldName: 'employeeId',
......@@ -43,9 +43,12 @@ export const querySchema: VbenFormSchema[] = [
label: '岗位',
},
{
component: 'Input',
fieldName: 'post',
label: '职务',
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_SEQUENCE),
},
fieldName: 'sequence',
label: '序列',
},
{
component: 'Input',
......@@ -144,6 +147,30 @@ export const querySchema: VbenFormSchema[] = [
fieldName: 'yearsOfServiceSegment',
label: '工龄段',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_MARITAL_STATUS),
},
fieldName: 'maritalStatus',
label: '婚姻状况',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_POLITICAL_STATUS),
},
fieldName: 'politicalStatus',
label: '政治面貌',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_EDUCATION_CATEGORY),
},
fieldName: 'educationCategory',
label: '学历分类',
},
// {
// component: 'Input',
// fieldName: 'education',
......@@ -241,10 +268,6 @@ export function useColumns(): VxeTableGridOptions<EmployeeInfoApi.Employee>['col
title: '板块',
field: 'plate',
},
{
title: '项目',
field: 'project',
},
{
title: '一级部门',
field: 'firstLevelDepartment',
......@@ -253,6 +276,10 @@ export function useColumns(): VxeTableGridOptions<EmployeeInfoApi.Employee>['col
title: '二级部门',
field: 'secondLevelDepartment',
},
{
title: '三级部门',
field: 'thirdLevelDepartment',
},
{
title: '工号',
field: 'employeeId',
......@@ -262,12 +289,12 @@ export function useColumns(): VxeTableGridOptions<EmployeeInfoApi.Employee>['col
// field: 'jobLevel',
// },
{
title: '岗位',
title: '岗位',
field: 'position',
},
{
title: '职务',
field: 'post',
title: '序列',
field: 'sequenceName',
},
{
title: '姓名',
......
<script setup lang="ts">
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { ref, shallowRef } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { Descriptions, DescriptionsItem, Skeleton } from 'ant-design-vue';
import {
Descriptions,
DescriptionsItem,
Image,
Skeleton,
Spin,
} from 'ant-design-vue';
import { apiInfoDetail } from '#/api/hr/employeeInfo';
......@@ -18,14 +24,20 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({
const currentEmployee = shallowRef<EmployeeInfoApi.Employee | null>(null);
const loading = ref(false);
const isResign = ref(false);
async function handleOpenChange(open: boolean) {
if (!open) {
return null;
}
const { id } = drawerApi.getData() as { id?: number };
const { id, resignFlag } = drawerApi.getData() as {
id?: number;
resignFlag?: boolean;
};
if (!id) {
return null;
}
isResign.value = !!resignFlag;
const data = await apiInfoDetail(id);
currentEmployee.value = data;
}
......@@ -62,26 +74,44 @@ async function handleOpenChange(open: boolean) {
<DescriptionsItem label="板块">
{{ currentEmployee.plate }}
</DescriptionsItem>
<DescriptionsItem label="项目">
{{ currentEmployee.project }}
</DescriptionsItem>
<DescriptionsItem label="一级部门">
{{ currentEmployee.firstLevelDepartment }}
</DescriptionsItem>
<DescriptionsItem label="二级部门">
{{ currentEmployee.secondLevelDepartment }}
</DescriptionsItem>
<DescriptionsItem label="三级部门">
{{ currentEmployee.thirdLevelDepartment }}
</DescriptionsItem>
<DescriptionsItem label="工号">
{{ currentEmployee.employeeId }}
{{ currentEmployee.employeeNo }}
</DescriptionsItem>
<DescriptionsItem label="职级">
{{ currentEmployee.jobLevel }}
</DescriptionsItem>
<DescriptionsItem label="岗位">
<DescriptionsItem label="岗位">
{{ currentEmployee.position }}
</DescriptionsItem>
<DescriptionsItem label="职务">
{{ currentEmployee.post }}
<DescriptionsItem label="岗位类型">
{{ currentEmployee.positionTypeName }}
</DescriptionsItem>
<DescriptionsItem label="序列">
{{ currentEmployee.sequenceName }}
</DescriptionsItem>
<DescriptionsItem label="兼职板块">
{{ currentEmployee.partTimePlate }}
</DescriptionsItem>
<DescriptionsItem label="兼职一级部门">
{{ currentEmployee.partTimeFirstDept }}
</DescriptionsItem>
<DescriptionsItem label="兼职二级部门">
{{ currentEmployee.partTimeSecondDept }}
</DescriptionsItem>
<DescriptionsItem label="兼职三级部门">
{{ currentEmployee.partTimeThirdDept }}
</DescriptionsItem>
<DescriptionsItem label="兼职岗位">
{{ currentEmployee.partTimePosition }}
</DescriptionsItem>
</Descriptions>
<Descriptions
......@@ -103,6 +133,19 @@ async function handleOpenChange(open: boolean) {
<DescriptionsItem label="姓名">
{{ currentEmployee.name }}
</DescriptionsItem>
<DescriptionsItem label="照片">
<Image
v-if="!!currentEmployee.photo"
:src="currentEmployee.photo"
height="50px"
>
<template #placeholder>
<div class="flex size-full items-center justify-center">
<Spin />
</div>
</template>
</Image>
</DescriptionsItem>
<DescriptionsItem label="性别">
{{ currentEmployee.genderName }}
</DescriptionsItem>
......@@ -159,20 +202,38 @@ async function handleOpenChange(open: boolean) {
<template #title>
<div class="text-center">教育信息</div>
</template>
<DescriptionsItem label="学历">
{{ currentEmployee.education }}
<DescriptionsItem label="全日制学历">
{{ currentEmployee.fulltimeEducation }}
</DescriptionsItem>
<DescriptionsItem label="全日制毕业院校">
{{ currentEmployee.fulltimeSchool }}
</DescriptionsItem>
<DescriptionsItem label="全日制专业">
{{ currentEmployee.fulltimeMajor }}
</DescriptionsItem>
<DescriptionsItem label="全日制毕业日期">
{{ currentEmployee.fulltimeGraduationDate }}
</DescriptionsItem>
<DescriptionsItem label="学位">
{{ currentEmployee.degree }}
<DescriptionsItem label="全日制学位">
{{ currentEmployee.fulltimeDegree }}
</DescriptionsItem>
<DescriptionsItem label="毕业时间">
{{ currentEmployee.graduationDate }}
<DescriptionsItem label="非全日制学历">
{{ currentEmployee.nonFulltimeEducation }}
</DescriptionsItem>
<DescriptionsItem label="专业">
{{ currentEmployee.major }}
<DescriptionsItem label="非全日制毕业院校">
{{ currentEmployee.nonFulltimeSchool }}
</DescriptionsItem>
<DescriptionsItem label="毕业院校">
{{ currentEmployee.graduateSchool }}
<DescriptionsItem label="非全日制专业">
{{ currentEmployee.nonFulltimeMajor }}
</DescriptionsItem>
<DescriptionsItem label="非全日制毕业日期">
{{ currentEmployee.nonFulltimeGraduationDate }}
</DescriptionsItem>
<DescriptionsItem label="非全日制学位">
{{ currentEmployee.nonFulltimeDegree }}
</DescriptionsItem>
<DescriptionsItem label="学历分类">
{{ currentEmployee.educationCategoryName }}
</DescriptionsItem>
</Descriptions>
<Descriptions
......@@ -215,6 +276,15 @@ async function handleOpenChange(open: boolean) {
<DescriptionsItem label="职称情况">
{{ currentEmployee.professionalTitle }}
</DescriptionsItem>
<DescriptionsItem label="证书情况">
{{ currentEmployee.certificateStatus }}
</DescriptionsItem>
<DescriptionsItem label="外部个人履历">
{{ currentEmployee.externalResume }}
</DescriptionsItem>
<DescriptionsItem label="内部个人履历">
{{ currentEmployee.internalResume }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show="!loading"
......@@ -232,6 +302,9 @@ async function handleOpenChange(open: boolean) {
<template #title>
<div class="text-center">合同信息</div>
</template>
<DescriptionsItem label="合同形式">
{{ currentEmployee.contractFormName }}
</DescriptionsItem>
<DescriptionsItem label="劳动合同期限">
{{ currentEmployee.contractTerm }}
</DescriptionsItem>
......@@ -250,13 +323,28 @@ async function handleOpenChange(open: boolean) {
<DescriptionsItem label="劳动合同签订情况">
{{ currentEmployee.contractSigningStatus }}
</DescriptionsItem>
<DescriptionsItem label="社保主体">
{{ currentEmployee.socialSecurityEntity }}
</DescriptionsItem>
<DescriptionsItem label="是否缴纳社保">
{{ currentEmployee.hasSocialSecurityPaidName }}
</DescriptionsItem>
<DescriptionsItem label="公积金主体">
{{ currentEmployee.providentFundEntity }}
</DescriptionsItem>
<DescriptionsItem label="是否缴纳公积金">
{{ currentEmployee.hasProvidentFundPaidName }}
</DescriptionsItem>
<DescriptionsItem label="试用期">
{{ currentEmployee.probationPeriod }}
</DescriptionsItem>
</Descriptions>
<Descriptions
v-show="!loading"
v-if="currentEmployee"
size="small"
bordered
:column="1"
:column="2"
class="mb-1"
:label-style="{
width: '140px',
......@@ -267,31 +355,71 @@ async function handleOpenChange(open: boolean) {
<template #title>
<div class="text-center">其他信息</div>
</template>
<DescriptionsItem label="异动情况">
{{ currentEmployee.transferStatus }}
<DescriptionsItem label="办公电话">
{{ currentEmployee.officePhone }}
</DescriptionsItem>
<DescriptionsItem label="奖惩情况">
{{ currentEmployee.rewardPunishmentStatus }}
<DescriptionsItem label="短线">
{{ currentEmployee.shortLine }}
</DescriptionsItem>
<DescriptionsItem label="备注">
<DescriptionsItem label="银行卡号">
{{ currentEmployee.bankCardNumber }}
</DescriptionsItem>
<DescriptionsItem label="开户行">
{{ currentEmployee.bankName }}
</DescriptionsItem>
<DescriptionsItem label="是否有亲属关系">
{{ currentEmployee.hasRelativeInCompanyName }}
</DescriptionsItem>
<DescriptionsItem label="亲属姓名">
{{ currentEmployee.relativeName }}
</DescriptionsItem>
<DescriptionsItem label="介绍人">
{{ currentEmployee.introducer }}
</DescriptionsItem>
<DescriptionsItem label="工资发放地">
{{ currentEmployee.salaryLocation }}
</DescriptionsItem>
<DescriptionsItem label="绩效比例" :span="2">
{{ currentEmployee.performanceRatio }}
</DescriptionsItem>
<DescriptionsItem label="奖励情况" :span="2">
{{ currentEmployee.rewardStatus }}
</DescriptionsItem>
<DescriptionsItem label="处罚情况" :span="2">
{{ currentEmployee.punishmentStatus }}
</DescriptionsItem>
<DescriptionsItem label="备注" :span="2">
{{ currentEmployee.remarks }}
</DescriptionsItem>
<!-- <DescriptionsItem label="请求参数">
<div class="max-h-[300px] overflow-y-auto">
<component :is="renderJsonPreview(currentLog.params)" />
</div>
</Descriptions>
<Descriptions
v-show="!loading"
v-if="isResign && 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.resignationTypeName }}
</DescriptionsItem>
<DescriptionsItem label="离职时间">
{{ currentEmployee.resignationDate }}
</DescriptionsItem>
<DescriptionsItem v-if="currentLog.result" label="响应参数">
<div class="max-h-[300px] overflow-y-auto">
<component :is="renderJsonPreview(currentLog.result)" />
</div>
<DescriptionsItem label="最后结薪日" :span="2">
{{ currentEmployee.finalPayDate }}
</DescriptionsItem>
<DescriptionsItem label="请求耗时">
{{ `${currentLog.costTime} ms` }}
<DescriptionsItem label="离职原因" :span="2">
{{ currentEmployee.resignationReason }}
</DescriptionsItem>
<DescriptionsItem label="操作时间">
{{ `${currentLog.createTime}` }}
</DescriptionsItem> -->
</Descriptions>
</BasicDrawer>
</template>
data:image/png;base64,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
<script lang="ts" setup>
import type { VbenFormSchema } from '#/adapter/form';
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { DictEnum } from '@vben/constants';
import { addFullName, getVxePopupContainer } from '@vben/utils';
import { Skeleton } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import {
selectDeptNamesByLevel,
selectDeptNamesByParent,
} from '#/api/hr/employeeDept';
import { apiAdd, apiDetail, apiUpdate } from '#/api/hr/employeeInfo';
import { useVbenForm, z } from '#/adapter/form';
import { treeList } from '#/api/auth/dept';
import { apiDetail } from '#/api/hr/employeeInfo';
import { getDictOptions } from '#/utils/dict';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
import { idCardSchema } from '../../../utils/validator';
import { HrDictEnum } from '../dict-enum';
const emit = defineEmits<{
......@@ -27,6 +26,25 @@ const formData = ref<EmployeeInfoApi.Employee>();
const loading = ref(false);
const isUpdate = ref(false);
// function genDeptTree(deptList: SysDeptApi.Dept[]): SysDeptApi.Dept[] {
// const top: SysDeptApi.Dept = {
// children: [],
// id: 0,
// name: '顶级部门',
// label: '顶级部门',
// parentId: -1,
// nodePath: '/',
// orderNum: 0,
// status: 1,
// };
// deptList.forEach((item) => {
// if (item.parentId === 0) {
// top.children?.push(item);
// }
// });
// return [top];
// }
const formSchema: VbenFormSchema[] = [
{
component: 'Divider',
......@@ -41,72 +59,62 @@ const formSchema: VbenFormSchema[] = [
}),
},
{
component: 'Input',
fieldName: 'plate',
label: '板块',
rules: 'required',
component: 'TreeSelect',
// 在onOpenChange里更新 这里不需要默认的componentProps
defaultValue: undefined,
fieldName: 'deptId',
label: '所属部门',
rules: 'selectRequired',
},
{
component: 'Input',
fieldName: 'project',
label: '项目',
rules: 'required',
fieldName: 'employeeNo',
label: '工号',
// rules: 'required',
},
{
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: 'InputNumber',
fieldName: 'jobLevel',
label: '职级',
rules: z.number().gt(0).lt(10).optional(),
},
{
component: 'Input',
fieldName: 'position',
label: '主岗位',
// rules: 'required',
},
{
component: 'Select',
componentProps: {
getVxePopupContainer,
placeholder: '请先选择一级部门',
options: getDictOptions(HrDictEnum.HR_SEQUENCE),
},
fieldName: 'secondLevelDepartment',
label: '二级部门',
rules: 'required',
},
{
component: 'Input',
fieldName: 'employeeId',
label: '工号',
rules: 'required',
fieldName: 'sequence',
label: '序列',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'jobLevel',
label: '职级',
rules: 'required',
component: 'Select',
componentProps: {
getVxePopupContainer,
options: getDictOptions(HrDictEnum.HR_POSITION_TYPE),
},
fieldName: 'positionType',
label: '岗位类型',
// rules: 'selectRequired',
},
{
component: 'Input',
fieldName: 'position',
label: '岗位',
rules: 'required',
component: 'TreeSelect',
// 在onOpenChange里更新 这里不需要默认的componentProps
defaultValue: undefined,
fieldName: 'partDeptId',
label: '兼职部门',
},
{
component: 'Input',
fieldName: 'post',
label: '职务',
rules: 'required',
fieldName: 'partTimePosition',
label: '兼职岗位',
// rules: 'required',
},
{
component: 'Divider',
......@@ -138,11 +146,20 @@ const formSchema: VbenFormSchema[] = [
label: '性别',
rules: 'required',
},
{
component: 'ImageUpload',
componentProps: {
maxCount: 1,
},
fieldName: 'photo',
label: '照片',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'idCardNumber',
label: '身份证号码',
rules: 'required',
rules: idCardSchema,
},
{
component: 'DatePicker',
......@@ -156,10 +173,10 @@ const formSchema: VbenFormSchema[] = [
rules: 'required',
},
{
component: 'Input',
component: 'InputNumber',
fieldName: 'age',
label: '年龄',
rules: 'required',
rules: z.number().gt(0, '年龄不能小于0').lt(100, '年龄不能大于100'),
},
// {
// component: 'Input',
......@@ -169,51 +186,61 @@ const formSchema: VbenFormSchema[] = [
// },
{
component: 'Input',
fieldName: 'nativePlace',
label: '籍贯',
rules: 'required',
fieldName: 'ethnicity',
label: '民族',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'ethnicity',
label: '民族',
rules: 'required',
fieldName: 'nativePlace',
label: '籍贯',
// rules: 'required',
},
{
component: 'Select',
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(HrDictEnum.HR_MARITAL_STATUS),
},
fieldName: 'maritalStatus',
label: '婚姻状况',
rules: 'selectRequired',
// rules: 'selectRequired',
},
{
component: 'Select',
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(HrDictEnum.HR_POLITICAL_STATUS),
},
fieldName: 'politicalStatus',
label: '政治面貌',
rules: 'selectRequired',
// rules: 'selectRequired',
},
{
component: 'Input',
fieldName: 'phoneNumber',
label: '手机号码',
rules: 'required',
rules: z
.string()
.regex(/^1[3-9]\d{9}$/, { message: '请输入正确的联系电话' }),
},
{
component: 'Input',
fieldName: 'emergencyContact',
label: '紧急联系人',
rules: 'required',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'emergencyContactPhone',
label: '紧急联系人电话',
rules: 'required',
rules: z
.string()
.regex(/^1[3-9]\d{9}$/, '请输入正确的手机号码')
.optional()
.or(z.literal('')),
},
{
component: 'Input',
......@@ -225,7 +252,7 @@ const formSchema: VbenFormSchema[] = [
component: 'Input',
fieldName: 'householdRegistrationAddress',
label: '户口所在地',
rules: 'required',
// rules: 'required',
},
{
component: 'Divider',
......@@ -241,15 +268,21 @@ const formSchema: VbenFormSchema[] = [
},
{
component: 'Input',
fieldName: 'education',
label: '学历',
rules: 'required',
fieldName: 'fulltimeEducation',
label: '全日制学历',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'degree',
label: '学位',
rules: 'required',
fieldName: 'fulltimeSchool',
label: '全日制毕业院校',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'fulltimeMajor',
label: '全日制专业',
// rules: 'required',
},
{
component: 'DatePicker',
......@@ -258,21 +291,62 @@ const formSchema: VbenFormSchema[] = [
valueFormat: 'YYYY-MM-DD',
getVxePopupContainer,
},
fieldName: 'graduationDate',
label: '毕业时间',
rules: 'required',
fieldName: 'fulltimeGraduationDate',
label: '全日制毕业日期',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'major',
label: '专业',
rules: 'required',
fieldName: 'fulltimeDegree',
label: '全日制学位',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'graduateSchool',
label: '毕业院校',
rules: 'required',
fieldName: 'nonFulltimeEducation',
label: '非全日制学历',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'nonFulltimeSchool',
label: '非全日制毕业院校',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'nonFulltimeMajor',
label: '非全日制专业',
// rules: 'required',
},
{
component: 'DatePicker',
componentProps: {
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
getVxePopupContainer,
},
fieldName: 'nonFulltimeGraduationDate',
label: '非全日制毕业日期',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'nonFulltimeDegree',
label: '非全日制学位',
// rules: 'required',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(HrDictEnum.HR_EDUCATION_CATEGORY),
},
fieldName: 'educationCategory',
label: '学历分类',
formItemClass: 'col-span-2',
// rules: 'required',
},
{
component: 'Divider',
......@@ -295,7 +369,7 @@ const formSchema: VbenFormSchema[] = [
},
fieldName: 'workStartDate',
label: '参加工作时间',
rules: 'required',
// rules: 'required',
},
{
component: 'DatePicker',
......@@ -306,7 +380,7 @@ const formSchema: VbenFormSchema[] = [
},
fieldName: 'entryDate',
label: '入职时间',
rules: 'required',
// rules: 'required',
},
{
component: 'DatePicker',
......@@ -317,13 +391,13 @@ const formSchema: VbenFormSchema[] = [
},
fieldName: 'regularizationDate',
label: '转正时间',
rules: 'required',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'yearsOfService',
label: '工龄',
rules: 'required',
// rules: 'required',
},
// {
// component: 'Input',
......@@ -338,16 +412,7 @@ const formSchema: VbenFormSchema[] = [
},
fieldName: 'employeeType',
label: '员工类型',
rules: 'selectRequired',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_EMPLOYMENT_FORM),
},
fieldName: 'employmentForm',
label: '用工形式',
rules: 'selectRequired',
// rules: 'selectRequired',
},
{
component: 'Input',
......@@ -357,8 +422,23 @@ const formSchema: VbenFormSchema[] = [
},
{
component: 'Input',
fieldName: 'resume',
label: '简历',
fieldName: 'certificateStatus',
label: '证书情况',
formItemClass: 'col-span-2',
// rules: 'required',
},
{
component: 'Textarea',
fieldName: 'externalResume',
label: '外部个人履历',
formItemClass: 'col-span-2',
// rules: 'required',
},
{
component: 'Textarea',
fieldName: 'internalResume',
label: '内部个人履历',
formItemClass: 'col-span-2',
// rules: 'required',
},
{
......@@ -373,11 +453,33 @@ const formSchema: VbenFormSchema[] = [
default: () => '合同信息',
}),
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(HrDictEnum.HR_EMPLOYMENT_FORM),
},
fieldName: 'employmentForm',
label: '用工形式',
// rules: 'selectRequired',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(HrDictEnum.HR_CONTRACT_FORM),
},
fieldName: 'contractForm',
label: '合同形式',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'contractTerm',
label: '劳动合同期限',
rules: 'required',
// rules: 'required',
},
{
component: 'DatePicker',
......@@ -388,7 +490,7 @@ const formSchema: VbenFormSchema[] = [
},
fieldName: 'contractStartDate',
label: '劳动合同开始时间',
rules: 'required',
// rules: 'required',
},
{
component: 'DatePicker',
......@@ -399,7 +501,7 @@ const formSchema: VbenFormSchema[] = [
},
fieldName: 'contractEndDate',
label: '劳动合同截止时间',
rules: 'required',
// rules: 'required',
},
{
component: 'DatePicker',
......@@ -416,7 +518,7 @@ const formSchema: VbenFormSchema[] = [
component: 'Input',
fieldName: 'contractEntity',
label: '合同主体',
rules: 'required',
// rules: 'required',
},
{
component: 'Input',
......@@ -426,9 +528,48 @@ const formSchema: VbenFormSchema[] = [
// },
fieldName: 'contractSigningStatus',
label: '劳动合同签订情况',
formItemClass: 'col-span-2',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'socialSecurityEntity',
label: '社保主体',
// rules: 'required',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(DictEnum.SYS_YES_NO),
},
fieldName: 'hasSocialSecurityPaid',
label: '是否缴纳社保',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'providentFundEntity',
label: '公积金主体',
// rules: 'required',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(DictEnum.SYS_YES_NO),
},
fieldName: 'hasProvidentFundPaid',
label: '是否缴纳公积金',
// rules: 'required',
},
{
component: 'InputNumber',
fieldName: 'probationPeriod',
label: '试用期(月数)',
rules: z.number().optional(),
},
{
component: 'Divider',
componentProps: {
......@@ -442,26 +583,26 @@ const formSchema: VbenFormSchema[] = [
}),
},
{
component: 'Input',
component: 'Textarea',
// componentProps: {
// buttonStyle: 'solid',
// optionType: 'button',
// },
fieldName: 'transferStatus',
fieldName: 'rewardStatus',
formItemClass: 'col-span-2',
label: '异动情况',
rules: 'required',
label: '奖励情况',
// rules: 'required',
},
{
component: 'Input',
component: 'Textarea',
// componentProps: {
// buttonStyle: 'solid',
// optionType: 'button',
// },
fieldName: 'rewardPunishmentStatus',
fieldName: 'punishmentStatus',
formItemClass: 'col-span-2',
label: '奖惩情况',
rules: 'required',
label: '处罚情况',
// rules: 'required',
},
{
component: 'Textarea',
......@@ -470,6 +611,65 @@ const formSchema: VbenFormSchema[] = [
label: '备注',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'officePhone',
label: '办公电话',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'shortLine',
label: '短线',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'bankCardNumber',
label: '银行卡号',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'bankName',
label: '开户行',
// rules: 'required',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
optionType: 'button',
options: getDictOptions(DictEnum.SYS_YES_NO),
},
fieldName: 'hasRelativeInCompany',
label: '是否有亲属关系',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'relativeName',
label: '亲属姓名',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'introducer',
label: '介绍人',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'salaryLocation',
label: '工资发放地',
// rules: 'required',
},
{
component: 'Input',
fieldName: 'performanceRatio',
label: '绩效比例',
// rules: 'required',
},
// {
// component: 'DatePicker',
// fieldName: 'resignationDate',
......@@ -498,6 +698,78 @@ const [BasicForm, formApi] = useVbenForm({
wrapperClass: 'grid-cols-2',
});
async function setupDeptSelect() {
const deptArray = await treeList();
// const deptTree = genDeptTree(deptArray);
addFullName(deptArray, 'label', ' / ');
formApi.updateSchema([
{
componentProps: (formModel) => ({
treeData: deptArray,
async onSelect(deptId: number | string, node: Record<string, any>) {
/** 根据部门Node获取部门等级数组 */
const result = node.fullName
.split('/')
.map((item: string) => item.trim())
.filter(Boolean);
/** 变化后需要重新设置部门信息 */
formModel.plate = result[0];
formModel.firstLevelDepartment = result[1];
formModel.secondLevelDepartment = result[2];
formModel.thirdLevelDepartment = result[3];
},
class: 'w-full',
treeLine: { showLeafIcon: false },
treeIcon: false,
// 筛选的字段
treeNodeFilterProp: 'label',
// 选中后显示在输入框的值
treeNodeLabelProp: 'fullName',
getVxePopupContainer,
fieldNames: { label: 'label', value: 'id' },
labelField: 'label',
showSearch: true,
treeDefaultExpandAll: true,
valueField: 'id',
childrenField: 'children',
}),
fieldName: 'deptId',
},
{
componentProps: (formModel) => ({
treeData: deptArray,
async onSelect(deptId: number | string, node: Record<string, any>) {
/** 根据部门Node获取部门等级数组 */
const result = node.fullName
.split('/')
.map((item: string) => item.trim())
.filter(Boolean);
/** 变化后需要重新设置部门信息 */
formModel.partTimePlate = result[0];
formModel.partTimeFirstDept = result[1];
formModel.partTimeSecondDept = result[2];
formModel.partTimeThirdDept = result[3];
},
class: 'w-full',
treeLine: { showLeafIcon: false },
treeIcon: false,
// 筛选的字段
treeNodeFilterProp: 'label',
// 选中后显示在输入框的值
treeNodeLabelProp: 'fullName',
getVxePopupContainer,
fieldNames: { label: 'label', value: 'id' },
labelField: 'label',
showSearch: true,
treeDefaultExpandAll: true,
valueField: 'id',
childrenField: 'children',
}),
fieldName: 'partDeptId',
},
]);
}
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
{
initializedGetter: defaultFormValueGetter(formApi),
......@@ -517,12 +789,14 @@ const [Drawer, drawerApi] = useVbenDrawer({
loading.value = true;
const { id } = drawerApi.getData() as { id?: number };
isUpdate.value = !!id;
console.log('[id]', id);
// 初始化
await setupDeptSelect();
// console.log('[id]', id);
if (id) {
const data = await apiDetail(id);
formData.value = data;
await formApi.setValues(formData.value!);
await setupDeptLevel2Options(data.firstLevelDepartment);
// await setupDeptLevel2Options(data.firstLevelDepartment);
} else {
formApi.resetForm();
}
......@@ -532,26 +806,27 @@ const [Drawer, drawerApi] = useVbenDrawer({
},
});
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 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 onSubmit() {
const { valid } = await formApi.validate();
if (valid) {
drawerApi.lock();
const data = await formApi.getValues<EmployeeInfoApi.Employee>();
console.log('[data]', data);
try {
await (formData.value?.id
? apiUpdate({ id: formData.value.id, ...data })
......
......@@ -2,15 +2,19 @@
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { EmployeeInfoApi } from '#/api/hr/employeeInfo';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import {
ExportOutlined,
PlusOutlined,
UploadOutlined,
} from '@ant-design/icons-vue';
import { Button, Space } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { apiExport, apiPage } from '#/api/hr/employeeInfo';
import { apiExport, apiPage, exportEmployeeList } from '#/api/hr/employeeInfo';
import { GhostButton } from '#/components/global/button';
import { commonDownloadExcel } from '#/utils/file/download';
......@@ -120,6 +124,13 @@ function onTransfer(row: EmployeeInfoApi.Employee) {
function handleDownloadExcel(row: EmployeeInfoApi.Employee) {
commonDownloadExcel(apiExport, '员工信息', row.id);
}
function handleDownloadEmployeeList() {
commonDownloadExcel(
exportEmployeeList,
'员工信息',
gridApi.formApi.form.values,
);
}
</script>
<template>
<Page auto-content-height>
......@@ -128,10 +139,24 @@ function handleDownloadExcel(row: EmployeeInfoApi.Employee) {
<Grid table-title="员工信息列表">
<template #toolbar-tools>
<Space>
<Button
type="primary"
ghost
v-access:code="['employee:info:export']"
@click.stop="handleDownloadEmployeeList"
>
<template #icon>
<ExportOutlined />
</template>
导出
</Button>
<Button
v-access:code="['employee:info:import']"
@click="handleImport"
>
<template #icon>
<UploadOutlined />
</template>
导入
</Button>
<Button
......@@ -139,7 +164,7 @@ function handleDownloadExcel(row: EmployeeInfoApi.Employee) {
type="primary"
@click="onCreate"
>
<Plus class="size-5" />
<PlusOutlined />
入职
</Button>
</Space>
......
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { getDictOptions } from '#/utils/dict';
import { HrDictEnum } from '../dict-enum';
export const querySchema: VbenFormSchema[] = [
{
component: 'Input',
fieldName: 'plate',
label: '板块',
},
{
component: 'Input',
fieldName: 'firstLevelDepartment',
label: '一级部门',
},
{
component: 'Input',
fieldName: 'secondLevelDepartment',
label: '二级部门',
},
{
component: 'Input',
fieldName: 'thirdLevelDepartment',
label: '三级部门',
},
{
component: 'Input',
fieldName: 'employeeId',
label: '工号',
},
{
component: 'Input',
fieldName: 'jobLevel',
label: '职级',
},
{
component: 'Input',
fieldName: 'position',
label: '岗位',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_SEQUENCE),
},
fieldName: 'sequence',
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: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_MARITAL_STATUS),
},
fieldName: 'maritalStatus',
label: '婚姻状况',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_POLITICAL_STATUS),
},
fieldName: 'politicalStatus',
label: '政治面貌',
},
{
component: 'Select',
componentProps: {
options: getDictOptions(HrDictEnum.HR_EDUCATION_CATEGORY),
},
fieldName: 'educationCategory',
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: 'firstLevelDepartment',
},
{
title: '二级部门',
field: 'secondLevelDepartment',
},
{
title: '三级部门',
field: 'thirdLevelDepartment',
},
{
title: '工号',
field: 'employeeId',
},
// {
// title: '职级',
// field: 'jobLevel',
// },
{
title: '主岗位',
field: 'position',
},
{
title: '序列',
field: 'sequenceName',
},
{
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',
},
];
}
<script lang="ts" setup>
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { EmployeeInfoApi } from '#/api/hr/employeeModel';
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { ExportOutlined, UploadOutlined } from '@ant-design/icons-vue';
import { Button, Space } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { apiPage, exportEmployeeList } from '#/api/hr/resignEmployee';
import { GhostButton } from '#/components/global/button';
import { commonDownloadExcel } from '#/utils/file/download';
import employeeDetailDrawer from '../employeeInfo/employee-detail-drawer.vue';
import { querySchema, useColumns } from './data';
import resignEmployeeImportModal from './resign-employee-import-modal.vue';
/**
* 导入
*/
const [ResignEmployeeImportModal, resignEmployeeImportModalApi] = useVbenModal({
connectedComponent: resignEmployeeImportModal,
});
function handleImport() {
resignEmployeeImportModalApi.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 [EmployeeDetailDrawer, employeeDetailDrawerApi] = useVbenDrawer({
connectedComponent: employeeDetailDrawer,
});
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 onRefresh() {
gridApi.query();
}
function onEdit(row: EmployeeInfoApi.Employee) {
// formDrawerApi.setData({ id: row.id }).open();
employeeDetailDrawerApi.setData({ id: row.id, resignFlag: true }).open();
}
function handleDownloadEmployeeList() {
commonDownloadExcel(
exportEmployeeList,
'员工信息',
gridApi.formApi.form.values,
);
}
</script>
<template>
<Page auto-content-height>
<EmployeeDetailDrawer />
<Grid table-title="离职员工列表">
<template #toolbar-tools>
<Space>
<Button
v-access:code="['employee:infoResign:export']"
@click.stop="handleDownloadEmployeeList"
>
<template #icon>
<ExportOutlined />
</template>
导出
</Button>
<Button
v-access:code="['employee:infoResign:import']"
@click="handleImport"
type="primary"
>
<template #icon>
<UploadOutlined />
</template>
导入
</Button>
</Space>
</template>
<template #action="{ row }">
<!-- 租户管理员不可修改admin角色 防止误操作 -->
<!-- 超级管理员可通过租户切换来操作租户管理员角色 -->
<!-- -->
<!-- <template
v-if="!row.superAdmin && (row.roleKey !== 'admin' || isSuperAdmin)"
> -->
<Space>
<GhostButton
v-access:code="['employee:infoResign:query']"
@click.stop="onEdit(row)"
>
查看
</GhostButton>
</Space>
<!-- </template> -->
</template>
</Grid>
<ResignEmployeeImportModal @reload="onRefresh" />
</Page>
</template>
<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,
employeeResignImportData,
} from '#/api/hr/resignEmployee';
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 employeeResignImportData(
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>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment