lin
This commit is contained in:
commit
91c436b4a3
|
@ -29,7 +29,7 @@ function getAreaName(codes: string[], level?: number): string {
|
||||||
// 修改表头提取工具函数
|
// 修改表头提取工具函数
|
||||||
function extractHeaders(columns: (ColDef | ColGroupDef)[]): string[] {
|
function extractHeaders(columns: (ColDef | ColGroupDef)[]): string[] {
|
||||||
const result: string[] = [];
|
const result: string[] = [];
|
||||||
|
|
||||||
const extractHeadersRecursive = (cols: (ColDef | ColGroupDef)[]) => {
|
const extractHeadersRecursive = (cols: (ColDef | ColGroupDef)[]) => {
|
||||||
cols.forEach(col => {
|
cols.forEach(col => {
|
||||||
if ('children' in col && col.children) {
|
if ('children' in col && col.children) {
|
||||||
|
@ -39,7 +39,7 @@ function extractHeaders(columns: (ColDef | ColGroupDef)[]): string[] {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
extractHeadersRecursive(columns);
|
extractHeadersRecursive(columns);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ export default function StaffTable() {
|
||||||
const [defaultFileName] = useState(`员工数据_${new Date().toISOString().slice(0, 10)}`);
|
const [defaultFileName] = useState(`员工数据_${new Date().toISOString().slice(0, 10)}`);
|
||||||
const [paginationEnabled, setPaginationEnabled] = useState(true);
|
const [paginationEnabled, setPaginationEnabled] = useState(true);
|
||||||
const [importVisible, setImportVisible] = useState(false);
|
const [importVisible, setImportVisible] = useState(false);
|
||||||
|
const [selectedRows, setSelectedRows] = useState<any[]>([]);
|
||||||
|
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
setFileNameVisible(true);
|
setFileNameVisible(true);
|
||||||
|
@ -165,11 +166,11 @@ export default function StaffTable() {
|
||||||
field: 'type',
|
field: 'type',
|
||||||
headerName: '人员类型',
|
headerName: '人员类型',
|
||||||
},
|
},
|
||||||
{ field: 'officerId', headerName: '警号'},
|
{ field: 'officerId', headerName: '警号' },
|
||||||
{ field: 'phoneNumber', headerName: '手机号' },
|
{ field: 'phoneNumber', headerName: '手机号' },
|
||||||
{ field: 'age', headerName: '年龄'},
|
{ field: 'age', headerName: '年龄' },
|
||||||
{
|
{
|
||||||
field: 'sex', headerName: '性别',
|
field: 'sex', headerName: '性别',
|
||||||
cellRenderer: (params: any) => {
|
cellRenderer: (params: any) => {
|
||||||
switch (params.value) {
|
switch (params.value) {
|
||||||
case true:
|
case true:
|
||||||
|
@ -182,32 +183,32 @@ export default function StaffTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
{ field: 'bloodType', headerName: '血型',},
|
{ field: 'bloodType', headerName: '血型', },
|
||||||
{
|
{
|
||||||
field: 'birthplace',
|
field: 'birthplace',
|
||||||
headerName: '籍贯',
|
headerName: '籍贯',
|
||||||
valueFormatter: (params) => params.value ? getAreaName(params.value.split('/')) : '',
|
valueFormatter: (params) => params.value ? getAreaName(params.value.split('/')) : '',
|
||||||
},
|
},
|
||||||
{ field: 'source', headerName: '来源'},
|
{ field: 'source', headerName: '来源' },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerName: '政治信息',
|
headerName: '政治信息',
|
||||||
children: [
|
children: [
|
||||||
{ field: 'politicalStatus', headerName: '政治面貌', },
|
{ field: 'politicalStatus', headerName: '政治面貌', },
|
||||||
{ field: 'partyPosition', headerName: '党内职务', }
|
{ field: 'partyPosition', headerName: '党内职务', }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerName: '职务信息',
|
headerName: '职务信息',
|
||||||
children: [
|
children: [
|
||||||
{ field: 'department.name', headerName: '所属部门', },
|
{ field: 'department.name', headerName: '所属部门', },
|
||||||
{ field: 'rank', headerName: '衔职级别', },
|
{ field: 'rank', headerName: '衔职级别', },
|
||||||
{
|
{
|
||||||
field: 'rankDate', headerName: '衔职时间',
|
field: 'rankDate', headerName: '衔职时间',
|
||||||
valueFormatter: (params: any) => params.value ? new Date(params.value).toLocaleDateString() : ''
|
valueFormatter: (params: any) => params.value ? new Date(params.value).toLocaleDateString() : ''
|
||||||
},
|
},
|
||||||
{ field: 'proxyPosition', headerName: '代理职务', },
|
{ field: 'proxyPosition', headerName: '代理职务', },
|
||||||
{ field: 'post', headerName: '岗位', }
|
{ field: 'post', headerName: '岗位', }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -222,17 +223,17 @@ export default function StaffTable() {
|
||||||
field: 'seniority', headerName: '工龄认定时间',
|
field: 'seniority', headerName: '工龄认定时间',
|
||||||
valueFormatter: (params: any) => params.value ? new Date(params.value).toLocaleDateString() : ''
|
valueFormatter: (params: any) => params.value ? new Date(params.value).toLocaleDateString() : ''
|
||||||
},
|
},
|
||||||
{ field: 'sourceType', headerName: '来源类型', },
|
{ field: 'sourceType', headerName: '来源类型', },
|
||||||
{
|
{
|
||||||
field: 'isReentry', headerName: '是否二次入职',
|
field: 'isReentry', headerName: '是否二次入职',
|
||||||
cellRenderer: (params: any) => params.value ? '是' : '否'
|
cellRenderer: (params: any) => params.value ? '是' : '否'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'isExtended', headerName: '是否延期服役',
|
field: 'isExtended', headerName: '是否延期服役',
|
||||||
cellRenderer: (params: any) => params.value ? '是' : '否'
|
cellRenderer: (params: any) => params.value ? '是' : '否'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'currentPositionDate', headerName: '现岗位开始时间',
|
field: 'currentPositionDate', headerName: '现岗位开始时间',
|
||||||
valueFormatter: (params: any) => params.value ? new Date(params.value).toLocaleDateString() : ''
|
valueFormatter: (params: any) => params.value ? new Date(params.value).toLocaleDateString() : ''
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -240,10 +241,10 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
headerName: '教育背景',
|
headerName: '教育背景',
|
||||||
children: [
|
children: [
|
||||||
{ field: 'education', headerName: '学历', },
|
{ field: 'education', headerName: '学历', },
|
||||||
{ field: 'educationType', headerName: '学历形式', },
|
{ field: 'educationType', headerName: '学历形式', },
|
||||||
{
|
{
|
||||||
field: 'isGraduated', headerName: '是否毕业',
|
field: 'isGraduated', headerName: '是否毕业',
|
||||||
cellRenderer: (params: any) => params.value ? '是' : '否'
|
cellRenderer: (params: any) => params.value ? '是' : '否'
|
||||||
},
|
},
|
||||||
{ field: 'major', headerName: '专业', },
|
{ field: 'major', headerName: '专业', },
|
||||||
|
@ -253,9 +254,9 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
headerName: '培训信息',
|
headerName: '培训信息',
|
||||||
children: [
|
children: [
|
||||||
{ field: 'trainType', headerName: '培训类型', },
|
{ field: 'trainType', headerName: '培训类型', },
|
||||||
{ field: 'trainInstitute', headerName: '培训机构', },
|
{ field: 'trainInstitute', headerName: '培训机构', },
|
||||||
{ field: 'trainMajor', headerName: '培训专业', },
|
{ field: 'trainMajor', headerName: '培训专业', },
|
||||||
{
|
{
|
||||||
field: 'hasTrain', headerName: '是否参加培训',
|
field: 'hasTrain', headerName: '是否参加培训',
|
||||||
cellRenderer: (params: any) => params.value ? '是' : '否'
|
cellRenderer: (params: any) => params.value ? '是' : '否'
|
||||||
|
@ -265,10 +266,10 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
headerName: '鉴定信息',
|
headerName: '鉴定信息',
|
||||||
children: [
|
children: [
|
||||||
{ field: 'certRank', headerName: '鉴定等级', },
|
{ field: 'certRank', headerName: '鉴定等级', },
|
||||||
{ field: 'certWork', headerName: '鉴定工种', },
|
{ field: 'certWork', headerName: '鉴定工种', },
|
||||||
{
|
{
|
||||||
field: 'hasCert', headerName: '是否参加鉴定',
|
field: 'hasCert', headerName: '是否参加鉴定',
|
||||||
cellRenderer: (params: any) => params.value ? '是' : '否'
|
cellRenderer: (params: any) => params.value ? '是' : '否'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -279,7 +280,7 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
field: 'equipment',
|
field: 'equipment',
|
||||||
headerName: '操作维护装备',
|
headerName: '操作维护装备',
|
||||||
|
|
||||||
cellRenderer: (params: any) => (
|
cellRenderer: (params: any) => (
|
||||||
<div
|
<div
|
||||||
style={{ lineHeight: '24px' }}
|
style={{ lineHeight: '24px' }}
|
||||||
|
@ -291,7 +292,7 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
field: 'projects',
|
field: 'projects',
|
||||||
headerName: '演训任务经历',
|
headerName: '演训任务经历',
|
||||||
|
|
||||||
cellRenderer: (params: any) => (
|
cellRenderer: (params: any) => (
|
||||||
<div
|
<div
|
||||||
style={{ lineHeight: '24px' }}
|
style={{ lineHeight: '24px' }}
|
||||||
|
@ -304,7 +305,7 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
field: 'awards',
|
field: 'awards',
|
||||||
headerName: '奖励信息',
|
headerName: '奖励信息',
|
||||||
|
|
||||||
cellRenderer: (params: any) => (
|
cellRenderer: (params: any) => (
|
||||||
<div
|
<div
|
||||||
style={{ lineHeight: '24px' }}
|
style={{ lineHeight: '24px' }}
|
||||||
|
@ -316,7 +317,7 @@ export default function StaffTable() {
|
||||||
{
|
{
|
||||||
field: 'punishments',
|
field: 'punishments',
|
||||||
headerName: '处分信息',
|
headerName: '处分信息',
|
||||||
|
|
||||||
cellRenderer: (params: any) => (
|
cellRenderer: (params: any) => (
|
||||||
<div
|
<div
|
||||||
style={{ lineHeight: '24px' }}
|
style={{ lineHeight: '24px' }}
|
||||||
|
@ -345,7 +346,313 @@ export default function StaffTable() {
|
||||||
wrapText: true,
|
wrapText: true,
|
||||||
autoHeight: true
|
autoHeight: true
|
||||||
};
|
};
|
||||||
|
// 修改导出模板处理函数
|
||||||
|
const handleExportTemplate = () => {
|
||||||
|
const headerNames = extractHeaders(columnDefs);
|
||||||
|
|
||||||
|
// 创建示例数据行
|
||||||
|
let exampleRow: Record<string, string> = {};
|
||||||
|
|
||||||
|
// 检查是否有选中行
|
||||||
|
if (selectedRows.length > 0) {
|
||||||
|
// 使用第一条选中的记录作为模板数据
|
||||||
|
const templateData = selectedRows[0];
|
||||||
|
|
||||||
|
// 使用选中的员工数据填充示例行
|
||||||
|
exampleRow = headerNames.reduce((obj, header) => {
|
||||||
|
// 查找表头对应的字段名
|
||||||
|
let fieldName = '';
|
||||||
|
let found = false;
|
||||||
|
|
||||||
|
// 遍历列定义,查找匹配的字段
|
||||||
|
columnDefs.forEach(colDef => {
|
||||||
|
if ('children' in colDef && colDef.children) {
|
||||||
|
colDef.children.forEach(childCol => {
|
||||||
|
if ('field' in childCol && childCol.headerName === header) {
|
||||||
|
fieldName = childCol.field;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if ('field' in colDef && colDef.headerName === header) {
|
||||||
|
fieldName = colDef.field;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 如果找到了字段名,从模板数据中获取值
|
||||||
|
if (found && fieldName && templateData[fieldName] !== undefined) {
|
||||||
|
// 根据字段类型处理值
|
||||||
|
switch (fieldName) {
|
||||||
|
// 日期类型字段 - 格式化为字符串
|
||||||
|
case 'hireDate':
|
||||||
|
case 'seniority':
|
||||||
|
case 'rankDate':
|
||||||
|
case 'currentPositionDate':
|
||||||
|
obj[header] = templateData[fieldName] ?
|
||||||
|
new Date(templateData[fieldName]).toISOString().split('T')[0] :
|
||||||
|
'';
|
||||||
|
break;
|
||||||
|
// 布尔类型字段 - 转为"是"或"否"
|
||||||
|
case 'sex':
|
||||||
|
obj[header] = templateData[fieldName] === true ? '男' :
|
||||||
|
templateData[fieldName] === false ? '女' : '';
|
||||||
|
break;
|
||||||
|
case 'enabled':
|
||||||
|
case 'isReentry':
|
||||||
|
case 'isExtended':
|
||||||
|
case 'isGraduated':
|
||||||
|
case 'hasTrain':
|
||||||
|
case 'hasCert':
|
||||||
|
obj[header] = templateData[fieldName] ? '是' : '否';
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 其他字段 - 直接使用值
|
||||||
|
default:
|
||||||
|
obj[header] = templateData[fieldName] !== null &&
|
||||||
|
templateData[fieldName] !== undefined ?
|
||||||
|
String(templateData[fieldName]) : '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有找到对应的值,设为空字符串
|
||||||
|
obj[header] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}, {} as Record<string, string>);
|
||||||
|
} else {
|
||||||
|
// 如果没有选中行,使用默认示例数据
|
||||||
|
exampleRow = headerNames.reduce((obj, header) => {
|
||||||
|
// 根据不同的表头设置不同的示例值
|
||||||
|
switch (header) {
|
||||||
|
case '姓名': obj[header] = '张三'; break;
|
||||||
|
case '身份证号': obj[header] = '110101199001011234'; break;
|
||||||
|
case '人员类型': obj[header] = '在职'; break;
|
||||||
|
case '警号': obj[header] = '012345'; break;
|
||||||
|
case '手机号': obj[header] = '13800138000'; break;
|
||||||
|
case '年龄': obj[header] = '30'; break;
|
||||||
|
case '性别': obj[header] = '男'; break;
|
||||||
|
// ... 其他默认示例值保持不变
|
||||||
|
default: obj[header] = ''; break;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}, {} as Record<string, string>);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建空白行供用户填写
|
||||||
|
const emptyRow = headerNames.reduce((obj, header) => {
|
||||||
|
obj[header] = '';
|
||||||
|
return obj;
|
||||||
|
}, {} as Record<string, string>);
|
||||||
|
|
||||||
|
// 创建工作簿和工作表
|
||||||
|
const wb = utils.book_new();
|
||||||
|
const ws = utils.json_to_sheet([exampleRow], { header: headerNames });
|
||||||
|
|
||||||
|
// 设置列宽
|
||||||
|
const colWidth = headerNames.map(() => ({ wch: 20 }));
|
||||||
|
ws['!cols'] = colWidth;
|
||||||
|
|
||||||
|
// 在第二行添加提示文字
|
||||||
|
const rowIdx = 2; // 第二行索引
|
||||||
|
const cellRef = utils.encode_cell({ r: rowIdx, c: 0 }); // A3单元格
|
||||||
|
|
||||||
|
const tipText = selectedRows.length > 0
|
||||||
|
? '以上为选中人员数据,请在下方行填写实际数据'
|
||||||
|
: '以上为示例数据,请在下方行填写实际数据';
|
||||||
|
|
||||||
|
ws[cellRef] = { t: 's', v: tipText };
|
||||||
|
|
||||||
|
// 手动添加空白行
|
||||||
|
utils.sheet_add_json(ws, [emptyRow], { skipHeader: true, origin: rowIdx + 1 });
|
||||||
|
|
||||||
|
// 合并提示文字单元格
|
||||||
|
if (!ws['!merges']) ws['!merges'] = [];
|
||||||
|
ws['!merges'].push({
|
||||||
|
s: { r: rowIdx, c: 0 }, // 起始单元格 A3
|
||||||
|
e: { r: rowIdx, c: Math.min(5, headerNames.length - 1) } // 结束单元格,跨越多列
|
||||||
|
});
|
||||||
|
|
||||||
|
utils.book_append_sheet(wb, ws, "员工模板");
|
||||||
|
writeFile(wb, `员工数据模板_${new Date().toISOString().slice(0, 10)}.xlsx`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加导入API钩子
|
||||||
|
const createManyMutation = api.staff.create.useMutation({
|
||||||
|
onSuccess: () => {
|
||||||
|
message.success('员工数据导入成功');
|
||||||
|
refetch(); // 刷新表格数据
|
||||||
|
setImportVisible(false);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
message.error(`导入失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理Excel导入数据
|
||||||
|
const handleImportData = (excelData: any[]) => {
|
||||||
|
// 转换Excel数据为后端接受的格式
|
||||||
|
const staffData = excelData.map(row => {
|
||||||
|
// 创建一个标准的员工对象
|
||||||
|
const staff: any = {};
|
||||||
|
|
||||||
|
// 遍历列定义,匹配Excel中的数据
|
||||||
|
columnDefs.forEach(colDef => {
|
||||||
|
if ('children' in colDef && colDef.children) {
|
||||||
|
colDef.children.forEach(childCol => {
|
||||||
|
if ('field' in childCol && childCol.headerName) {
|
||||||
|
// 使用表头名称查找Excel数据
|
||||||
|
const value = row[childCol.headerName];
|
||||||
|
if (value !== undefined) {
|
||||||
|
// 处理嵌套属性 (如 department.name)
|
||||||
|
if (childCol.field.includes('.')) {
|
||||||
|
const [parent, child] = childCol.field.split('.');
|
||||||
|
// 对于department.name特殊处理
|
||||||
|
if (parent === 'department' && child === 'name') {
|
||||||
|
// 仅存储部门名称,后续可处理
|
||||||
|
staff.departmentName = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 根据字段类型进行处理
|
||||||
|
processFieldValue(staff, childCol.field, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if ('field' in colDef && colDef.headerName) {
|
||||||
|
const value = row[colDef.headerName];
|
||||||
|
if (value !== undefined) {
|
||||||
|
processFieldValue(staff, colDef.field, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return staff;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 调用后端API保存数据
|
||||||
|
if (staffData.length > 0) {
|
||||||
|
// 逐个创建员工记录
|
||||||
|
staffData.forEach(staff => {
|
||||||
|
createManyMutation.mutate({
|
||||||
|
data: staff
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
message.success(`已提交${staffData.length}条员工数据导入请求`);
|
||||||
|
} else {
|
||||||
|
message.warning('没有可导入的有效数据');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 字段值处理函数
|
||||||
|
const processFieldValue = (staff: any, field: string, value: any) => {
|
||||||
|
// 跳过空值
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据字段类型分别处理
|
||||||
|
switch (field) {
|
||||||
|
// 字符串字段 - 确保转为字符串
|
||||||
|
case 'idNumber':
|
||||||
|
case 'officerId':
|
||||||
|
case 'phoneNumber':
|
||||||
|
case 'username':
|
||||||
|
case 'password':
|
||||||
|
case 'showname':
|
||||||
|
case 'avatar':
|
||||||
|
case 'type':
|
||||||
|
case 'bloodType':
|
||||||
|
case 'birthplace':
|
||||||
|
case 'source':
|
||||||
|
case 'politicalStatus':
|
||||||
|
case 'partyPosition':
|
||||||
|
case 'rank':
|
||||||
|
case 'proxyPosition':
|
||||||
|
case 'post':
|
||||||
|
case 'sourceType':
|
||||||
|
case 'education':
|
||||||
|
case 'educationType':
|
||||||
|
case 'major':
|
||||||
|
case 'foreignLang':
|
||||||
|
case 'trainType':
|
||||||
|
case 'trainInstitute':
|
||||||
|
case 'trainMajor':
|
||||||
|
case 'certRank':
|
||||||
|
case 'certWork':
|
||||||
|
case 'equipment':
|
||||||
|
case 'projects':
|
||||||
|
case 'awards':
|
||||||
|
case 'punishments':
|
||||||
|
case 'domainId':
|
||||||
|
case 'deptId':
|
||||||
|
staff[field] = String(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 布尔字段 - 转为布尔值
|
||||||
|
case 'sex':
|
||||||
|
staff[field] = value === '男' ? true : value === '女' ? false : null;
|
||||||
|
break;
|
||||||
|
case 'enabled':
|
||||||
|
case 'isReentry':
|
||||||
|
case 'isExtended':
|
||||||
|
case 'isGraduated':
|
||||||
|
case 'hasTrain':
|
||||||
|
case 'hasCert':
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
staff[field] = value === '是' || value === '√' || value === 'true' || value === '1';
|
||||||
|
} else {
|
||||||
|
staff[field] = Boolean(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 数值字段 - 转为数字
|
||||||
|
case 'age':
|
||||||
|
staff[field] = parseInt(value, 10);
|
||||||
|
break;
|
||||||
|
case 'order':
|
||||||
|
staff[field] = parseFloat(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 日期字段 - 转为日期格式
|
||||||
|
case 'rankDate':
|
||||||
|
case 'hireDate':
|
||||||
|
case 'seniority':
|
||||||
|
case 'currentPositionDate':
|
||||||
|
// 尝试将日期字符串转换为日期对象
|
||||||
|
try {
|
||||||
|
// Excel日期可能以不同格式导出
|
||||||
|
let dateValue = value;
|
||||||
|
|
||||||
|
// 如果是Excel序列号格式的日期
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
// Excel日期是从1900年1月1日开始的天数
|
||||||
|
// 需要转换为JavaScript日期
|
||||||
|
const excelEpoch = new Date(1899, 11, 30);
|
||||||
|
dateValue = new Date(excelEpoch.getTime() + value * 86400000);
|
||||||
|
}
|
||||||
|
// 如果是字符串格式的日期
|
||||||
|
else if (typeof value === 'string') {
|
||||||
|
// 尝试解析常见日期格式
|
||||||
|
dateValue = new Date(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查日期是否有效
|
||||||
|
if (dateValue instanceof Date && !isNaN(dateValue.getTime())) {
|
||||||
|
staff[field] = dateValue.toISOString();
|
||||||
|
} else {
|
||||||
|
console.warn(`无效的日期格式: ${field} = ${value}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`日期转换错误 (${field}): ${e}`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 默认情况下保持原值
|
||||||
|
default:
|
||||||
|
staff[field] = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ag-theme-alpine w-full h-[calc(100vh-100px)]"
|
<div className="ag-theme-alpine w-full h-[calc(100vh-100px)]"
|
||||||
style={{
|
style={{
|
||||||
|
@ -392,7 +699,43 @@ export default function StaffTable() {
|
||||||
onChange={(e) => setFileName(e.target.value)}
|
onChange={(e) => setFileName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal
|
||||||
|
title="导入员工数据"
|
||||||
|
open={importVisible}
|
||||||
|
onCancel={() => setImportVisible(false)}
|
||||||
|
footer={null}
|
||||||
|
>
|
||||||
|
<Upload
|
||||||
|
accept=".xlsx,.xls"
|
||||||
|
beforeUpload={file => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
try {
|
||||||
|
const wb = read(e.target?.result);
|
||||||
|
const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
message.warning('Excel文件中没有数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.info(`读取到${data.length}条数据,正在处理...`);
|
||||||
|
handleImportData(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析Excel文件失败:', error);
|
||||||
|
message.error('Excel文件格式错误,请确保使用正确的模板');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button icon={<UploadOutlined />}>选择Excel文件</Button>
|
||||||
|
</Upload>
|
||||||
|
<div className="mt-4 text-gray-500 text-sm">
|
||||||
|
提示:请使用导出模板功能获取标准模板,按格式填写数据后导入
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="h-full flex items-center justify-center">
|
<div className="h-full flex items-center justify-center">
|
||||||
<div className="text-gray-600 text-xl">加载中...</div>
|
<div className="text-gray-600 text-xl">加载中...</div>
|
||||||
|
@ -400,7 +743,7 @@ export default function StaffTable() {
|
||||||
) : (
|
) : (
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
modules={[SetFilterModule, ClientSideRowModelModule]}
|
modules={[SetFilterModule, ClientSideRowModelModule]}
|
||||||
onGridReady={(params) => setGridApi(params.api)} // 添加gridApi回调
|
onGridReady={(params) => setGridApi(params.api)}
|
||||||
rowData={staffs}
|
rowData={staffs}
|
||||||
columnDefs={columnDefs}
|
columnDefs={columnDefs}
|
||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
|
@ -413,6 +756,10 @@ export default function StaffTable() {
|
||||||
pagination={paginationEnabled}
|
pagination={paginationEnabled}
|
||||||
paginationAutoPageSize={true}
|
paginationAutoPageSize={true}
|
||||||
cacheQuickFilter={true}
|
cacheQuickFilter={true}
|
||||||
|
rowSelection="single"
|
||||||
|
onSelectionChanged={(event) => {
|
||||||
|
setSelectedRows(event.api.getSelectedRows());
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue