2 Commits

Author SHA1 Message Date
55a5f87f44 chore: 应用模板更新 2025-12-19 10:26:44 +08:00
75fdc82c8b fix: 修复无法导入excel的错误 2025-12-19 10:19:34 +08:00
2 changed files with 94 additions and 28 deletions

View File

@@ -360,28 +360,30 @@ class Project extends Base {
$file = request()->file('excel_file'); $file = request()->file('excel_file');
if (!$file) { if (!$file) {
$this->error('请选择要导入的文件'); $this->error('请选择要导入的文件');
return;
} }
// 验证文件类型 // 验证文件类型
$ext = strtolower(pathinfo($file->getInfo('name'), PATHINFO_EXTENSION)); $ext = strtolower(pathinfo($file->getInfo('name'), PATHINFO_EXTENSION));
if (!in_array($ext, ['xls', 'xlsx'])) { if (!in_array($ext, ['xls', 'xlsx'])) {
$this->error('只支持Excel格式文件(.xls, .xlsx)'); $this->error('只支持Excel格式文件(.xls, .xlsx)');
return;
} }
// 移动文件到临时目录 // 移动文件到临时目录
$info = $file->move(ROOT_PATH . 'data' . DS . 'runtime', ''); $info = $file->move(ROOT_PATH . 'data' . DS . 'runtime', '');
if (!$info) { if (!$info) {
$this->error('文件上传失败: ' . $file->getError()); $this->error('文件上传失败: ' . $file->getError());
return;
} }
$filename = ROOT_PATH . 'data' . DS . 'runtime' . DS . $info->getSaveName(); $filename = ROOT_PATH . 'data' . DS . 'runtime' . DS . $info->getSaveName();
// 解析Excel文件
$data = []; // 加载PHPExcel库
$objReader = null;
try { try {
// 引入PHPExcel库
vendor('phpoffice.phpexcel.Classes.PHPExcel'); vendor('phpoffice.phpexcel.Classes.PHPExcel');
// 判断文件类型 // 判断文件类型
if ($ext == 'xls') { if ($ext == 'xls') {
$objReader = \PHPExcel_IOFactory::createReader('Excel5'); $objReader = \PHPExcel_IOFactory::createReader('Excel5');
@@ -389,6 +391,17 @@ class Project extends Base {
$objReader = \PHPExcel_IOFactory::createReader('Excel2007'); $objReader = \PHPExcel_IOFactory::createReader('Excel2007');
} }
// 设置只读模式以提高性能
$objReader->setReadDataOnly(true);
} catch (\Exception $e) {
$this->error('加载PHPExcel库失败: ' . $e->getMessage());
return;
}
// 解析Excel文件
$data = [];
try {
$objPHPExcel = $objReader->load($filename); $objPHPExcel = $objReader->load($filename);
$sheet = $objPHPExcel->getSheet(0); $sheet = $objPHPExcel->getSheet(0);
$highestRow = $sheet->getHighestRow(); $highestRow = $sheet->getHighestRow();
@@ -400,43 +413,96 @@ class Project extends Base {
$rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE)[0]; $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE)[0];
// 确保行数据完整 // 确保行数据完整
if (count($rowData) >= 5) { if (count($rowData) >= 5) { // 修改为5列因为模板中已移除密码列
// 验证必要字段不为空 // 验证必要字段不为空
if (empty(trim($rowData[0]))) { if (empty(trim($rowData[0])) || empty(trim($rowData[4]))) { // 检查名称和有效期字段
continue; // 跳过必填字段为空的行 continue; // 跳过必填字段为空的行
} }
$data[] = [ $data[] = [
'name' => trim($rowData[0]), 'name' => trim($rowData[0]),
'enterprise' => trim($rowData[1]), 'enterprise' => trim($rowData[1]), // 个人/企业字段位置修正
'filing' => trim($rowData[2]), 'filing' => trim($rowData[2]), // 备案号字段位置修正
'sid' => trim($rowData[3]), 'sid' => trim($rowData[3]), // 证件号码字段位置修正
'limitationdate' => trim($rowData[4]), 'limitationdate' => trim($rowData[4]), // 有效期字段位置修正
'createtime' => getTime() 'createtime' => getTime()
]; ];
} }
} }
// 删除临时文件
unlink($filename);
// 批量插入数据
if (!empty($data)) {
$result = Db::name('project')->insertAll($data);
if ($result) {
$this->success('成功导入 ' . count($data) . ' 条记录');
} else {
$this->error('导入失败');
}
} else {
$this->error('文件中没有有效数据');
}
} catch (\Exception $e) { } catch (\Exception $e) {
$this->error('文件解析失败: ' . $e->getMessage());
return;
} finally {
// 删除临时文件 // 删除临时文件
if (file_exists($filename)) { if (file_exists($filename)) {
unlink($filename); unlink($filename);
} }
$this->error('文件解析失败: ' . $e->getMessage()); }
// 验证数据
if (empty($data)) {
$this->error('文件中没有有效数据');
return;
}
// 批量插入数据,避免重复数据
try {
// 先检查是否已存在相同的数据,避免重复插入
$insertData = [];
foreach ($data as $item) {
// 检查是否已存在相同的名称和证件号码
$exists = Db::name('project')
->where('name', $item['name'])
->find();
if (!$exists) {
$insertData[] = $item;
}
}
if (!empty($insertData)) {
// 记录插入前的信息
trace('准备插入 ' . count($insertData) . ' 条记录', 'info');
$result = Db::name('project')->insertAll($insertData);
// 记录插入后的信息
trace('成功插入 ' . count($insertData) . ' 条记录,结果: ' . var_export($result, true), 'info');
echo json_encode(['code' => 1, 'msg' => '成功导入 ' . count($insertData) . ' 条记录,已过滤 ' . (count($data) - count($insertData)) . ' 条重复数据']);
return; // 确保在success后立即返回
} else {
$this->error('没有新的数据需要导入,所有数据都已存在');
return; // 确保在error后立即返回
}
} catch (\Exception $e) {
// 记录详细的错误信息到日志
$errorMsg = '数据库插入失败: ' . $e->getMessage() .
' Code: ' . $e->getCode() .
' File: ' . $e->getFile() .
' Line: ' . $e->getLine();
// 同时记录第一条数据作为参考
if (!empty($data)) {
$errorMsg .= ' Sample Data: ' . json_encode($data[0], JSON_UNESCAPED_UNICODE);
}
// 记录到系统日志
trace($errorMsg, 'error');
$this->error($errorMsg);
return;
} catch (\Error $e) {
// 捕获Error类型的异常
$errorMsg = '数据库插入出现错误: ' . $e->getMessage() .
' Code: ' . $e->getCode() .
' File: ' . $e->getFile() .
' Line: ' . $e->getLine();
// 记录到系统日志
trace($errorMsg, 'error');
$this->error($errorMsg);
return;
} }
} }

View File

@@ -286,7 +286,7 @@
'<div class="layui-input-block">' + '<div class="layui-input-block">' +
'<button type="button" class="layui-btn custom-layui-btn" onclick="submitImport()">上传并导入</button>' + '<button type="button" class="layui-btn custom-layui-btn" onclick="submitImport()">上传并导入</button>' +
'<button type="button" class="layui-btn layui-btn-primary" onclick="layer.closeAll()">取消</button>' + '<button type="button" class="layui-btn layui-btn-primary" onclick="layer.closeAll()">取消</button>' +
'<a href="../../../data/project_template.xlsx" style="margin-left: 10px;" download="project_template.xlsx">下载模板</a>' + '<a href="/project_template.xlsx" style="margin-left: 10px;" download="project_template.xlsx">下载模板</a>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</form>' + '</form>' +