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: '姓名',
......
data:image/png;base64,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
......@@ -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>
......
This diff is collapsed.
<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