|
@@ -562,42 +562,48 @@ class Product extends Api
|
|
|
/**
|
|
/**
|
|
|
* Excel 导入 部件 + 工艺
|
|
* Excel 导入 部件 + 工艺
|
|
|
*/
|
|
*/
|
|
|
- public function ProcessExcel()
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public function ProcessExcel(){
|
|
|
if (!Request::instance()->isPost()) {
|
|
if (!Request::instance()->isPost()) {
|
|
|
$this->error('非法请求');
|
|
$this->error('非法请求');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 获取上传文件
|
|
|
|
|
|
|
+ $params = Request::instance()->param();
|
|
|
$file = request()->file('file');
|
|
$file = request()->file('file');
|
|
|
- echo "<pre>";
|
|
|
|
|
- print_r($file);
|
|
|
|
|
- echo "<pre>";die;
|
|
|
|
|
|
|
+echo "<pre>";
|
|
|
|
|
+print_r($params);
|
|
|
|
|
+echo "<pre>";die;
|
|
|
|
|
+ // 1. 先判断文件是否存在
|
|
|
if (empty($file)) {
|
|
if (empty($file)) {
|
|
|
$this->error('请上传Excel文件');
|
|
$this->error('请上传Excel文件');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 接收产品编号
|
|
|
|
|
- $product_code = input('product_code');
|
|
|
|
|
|
|
+ // 2. 必传参数校验
|
|
|
|
|
+ $product_code = $params['product_code'];
|
|
|
|
|
+ $sys_id = $params['sys_id'];
|
|
|
|
|
+
|
|
|
if (empty($product_code)) {
|
|
if (empty($product_code)) {
|
|
|
- $this->error('请传入产品编号 product_code');
|
|
|
|
|
|
|
+ $this->error('请选择产品后,再进行提交');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 获取文件路径
|
|
|
|
|
- $file_path = $file->getRealPath();
|
|
|
|
|
- $ext = strtolower($file->getExtension());
|
|
|
|
|
|
|
+ // 3. 正确获取文件扩展名(解决 getExtension 为空的问题)
|
|
|
|
|
+ $fileInfo = $file->getInfo();
|
|
|
|
|
+ $fileName = $fileInfo['name'];
|
|
|
|
|
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
|
|
|
|
|
|
|
- // 读取数据(兼容 xls + xlsx)
|
|
|
|
|
|
|
+ if (!in_array($ext, ['xlsx', 'xls'])) {
|
|
|
|
|
+ $this->error('只支持 xls / xlsx 格式');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $file_path = $file->getRealPath();
|
|
|
$data = [];
|
|
$data = [];
|
|
|
|
|
+
|
|
|
if ($ext == 'xlsx') {
|
|
if ($ext == 'xlsx') {
|
|
|
$data = $this->readXlsx($file_path);
|
|
$data = $this->readXlsx($file_path);
|
|
|
} elseif ($ext == 'xls') {
|
|
} elseif ($ext == 'xls') {
|
|
|
$data = $this->readXls($file_path);
|
|
$data = $this->readXls($file_path);
|
|
|
- } else {
|
|
|
|
|
- $this->error('只支持 xls / xlsx 格式');
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 去掉表头,过滤空行
|
|
|
|
|
|
|
+ // 4. 解析数据
|
|
|
$rows = array_slice($data, 1);
|
|
$rows = array_slice($data, 1);
|
|
|
$insert_data = [];
|
|
$insert_data = [];
|
|
|
foreach ($rows as $row) {
|
|
foreach ($rows as $row) {
|
|
@@ -606,12 +612,12 @@ class Product extends Api
|
|
|
if (empty($part_name) || empty($gy_name)) continue;
|
|
if (empty($part_name) || empty($gy_name)) continue;
|
|
|
|
|
|
|
|
$insert_data[] = [
|
|
$insert_data[] = [
|
|
|
- 'part_name' => $part_name,
|
|
|
|
|
- 'gy_name' => $gy_name,
|
|
|
|
|
- 'big_process' => trim($row[2] ?? ''),
|
|
|
|
|
- 'standard_hour' => floatval($row[3] ?? 0),
|
|
|
|
|
- 'standard_score' => floatval($row[4] ?? 0),
|
|
|
|
|
- 'difficulty_coef' => floatval($row[5] ?? 1),
|
|
|
|
|
|
|
+ 'part_name' => $part_name,
|
|
|
|
|
+ 'gy_name' => $gy_name,
|
|
|
|
|
+ 'big_process' => trim($row[2] ?? ''),
|
|
|
|
|
+ 'standard_hour' => floatval($row[3] ?? 0),
|
|
|
|
|
+ 'standard_score' => floatval($row[4] ?? 0),
|
|
|
|
|
+ 'difficulty_coef' => floatval($row[5] ?? 1),
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -619,7 +625,7 @@ class Product extends Api
|
|
|
$this->error('Excel 无有效数据');
|
|
$this->error('Excel 无有效数据');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ===================== 1. 处理部件(去重 + 排序) =====================
|
|
|
|
|
|
|
+ // 5. 处理部件
|
|
|
$part_map = [];
|
|
$part_map = [];
|
|
|
$part_sort = 1;
|
|
$part_sort = 1;
|
|
|
foreach ($insert_data as $item) {
|
|
foreach ($insert_data as $item) {
|
|
@@ -629,24 +635,19 @@ class Product extends Api
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 插入部件
|
|
|
|
|
$part_all = [];
|
|
$part_all = [];
|
|
|
foreach ($part_map as $name => $sort) {
|
|
foreach ($part_map as $name => $sort) {
|
|
|
$part_all[] = [
|
|
$part_all[] = [
|
|
|
'product_code' => $product_code,
|
|
'product_code' => $product_code,
|
|
|
- 'part_sort' => $sort,
|
|
|
|
|
- 'part_name' => $name,
|
|
|
|
|
- 'sys_id' => '超级管理员',
|
|
|
|
|
- 'createtime' => date('Y-m-d H:i:s'),
|
|
|
|
|
- 'mod_rq' => null,
|
|
|
|
|
|
|
+ 'part_sort' => $sort,
|
|
|
|
|
+ 'part_name' => $name,
|
|
|
|
|
+ 'sys_id' => $sys_id,
|
|
|
|
|
+ 'sys_rq' => date('Y-m-d H:i:s'),
|
|
|
|
|
+ 'mod_rq' => null
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 清空旧数据(可选)
|
|
|
|
|
- db('产品_部件资料')->where('product_code', $product_code)->delete();
|
|
|
|
|
- db('产品_部件资料')->insertAll($part_all);
|
|
|
|
|
-
|
|
|
|
|
- // ===================== 2. 处理工艺 =====================
|
|
|
|
|
|
|
+ // 6. 处理工艺
|
|
|
$gy_sort_map = [];
|
|
$gy_sort_map = [];
|
|
|
$process_all = [];
|
|
$process_all = [];
|
|
|
foreach ($insert_data as $item) {
|
|
foreach ($insert_data as $item) {
|
|
@@ -654,22 +655,27 @@ class Product extends Api
|
|
|
$gy_sort_map[$part_sort] = isset($gy_sort_map[$part_sort]) ? $gy_sort_map[$part_sort] + 1 : 1;
|
|
$gy_sort_map[$part_sort] = isset($gy_sort_map[$part_sort]) ? $gy_sort_map[$part_sort] + 1 : 1;
|
|
|
|
|
|
|
|
$process_all[] = [
|
|
$process_all[] = [
|
|
|
- 'product_code' => $product_code,
|
|
|
|
|
- 'part_sort' => $part_sort,
|
|
|
|
|
- 'part_name' => $item['part_name'],
|
|
|
|
|
- 'gy_sort' => $gy_sort_map[$part_sort],
|
|
|
|
|
- 'gy_name' => $item['gy_name'],
|
|
|
|
|
- 'big_process' => $item['big_process'],
|
|
|
|
|
- 'standard_hour' => $item['standard_hour'],
|
|
|
|
|
- 'standard_score' => $item['standard_score'],
|
|
|
|
|
|
|
+ 'product_code' => $product_code,
|
|
|
|
|
+ 'part_sort' => $part_sort,
|
|
|
|
|
+ 'part_name' => $item['part_name'],
|
|
|
|
|
+ 'gy_sort' => $gy_sort_map[$part_sort],
|
|
|
|
|
+ 'gy_name' => $item['gy_name'],
|
|
|
|
|
+ 'big_process' => $item['big_process'],
|
|
|
|
|
+ 'standard_hour' => $item['standard_hour'],
|
|
|
|
|
+ 'standard_score' => $item['standard_score'],
|
|
|
'difficulty_coef' => $item['difficulty_coef'],
|
|
'difficulty_coef' => $item['difficulty_coef'],
|
|
|
- 'sys_id' => '超级管理员',
|
|
|
|
|
- 'createtime' => date('Y-m-d H:i:s'),
|
|
|
|
|
- 'mod_rq' => null,
|
|
|
|
|
|
|
+ 'sys_id' => $sys_id,
|
|
|
|
|
+ 'sys_rq' => date('Y-m-d H:i:s'),
|
|
|
|
|
+ 'mod_rq' => null
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- db('产品_工艺资料')->where('product_code', $product_code)->delete();
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 写入数据库(你可以按需注释)
|
|
|
|
|
+ db('产品_部件资料')->where('product_code', $product_code)->update(['mod_rq' => date('Y-m-d H:i:s')]);
|
|
|
|
|
+ db('产品_部件资料')->insertAll($part_all);
|
|
|
|
|
+
|
|
|
|
|
+ db('产品_工艺资料')->where('product_code', $product_code)->update(['mod_rq' => date('Y-m-d H:i:s')]);
|
|
|
db('产品_工艺资料')->insertAll($process_all);
|
|
db('产品_工艺资料')->insertAll($process_all);
|
|
|
|
|
|
|
|
$this->success('导入成功', [
|
|
$this->success('导入成功', [
|
|
@@ -678,42 +684,67 @@ class Product extends Api
|
|
|
]);
|
|
]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// ------------------------------ 以下是内置读取函数,不用装任何插件 ------------------------------
|
|
|
|
|
- /**
|
|
|
|
|
- * 读取 xlsx
|
|
|
|
|
- */
|
|
|
|
|
private function readXlsx($file)
|
|
private function readXlsx($file)
|
|
|
{
|
|
{
|
|
|
- $zip = new ZipArchive();
|
|
|
|
|
- if ($zip->open($file) !== true) return [];
|
|
|
|
|
|
|
+ if (!class_exists('ZipArchive')) {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ $zip = new \ZipArchive();
|
|
|
|
|
+ if ($zip->open($file) !== true) {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 读取工作表内容和共享字符串
|
|
|
$content = $zip->getFromName('xl/worksheets/sheet1.xml');
|
|
$content = $zip->getFromName('xl/worksheets/sheet1.xml');
|
|
|
$strings = $zip->getFromName('xl/sharedStrings.xml');
|
|
$strings = $zip->getFromName('xl/sharedStrings.xml');
|
|
|
$zip->close();
|
|
$zip->close();
|
|
|
|
|
|
|
|
- $rows = [];
|
|
|
|
|
|
|
+ // 解析共享字符串
|
|
|
$str_map = [];
|
|
$str_map = [];
|
|
|
-
|
|
|
|
|
if ($strings) {
|
|
if ($strings) {
|
|
|
- preg_match_all('/<si><t>([^<]+)<\/t><\/si>/', $strings, $m);
|
|
|
|
|
- $str_map = $m[1] ?? [];
|
|
|
|
|
|
|
+ preg_match_all('/<si><t[^>]*>([^<]+)<\/t><\/si>/s', $strings, $matches);
|
|
|
|
|
+ $str_map = $matches[1] ?? [];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ $rows = [];
|
|
|
|
|
+ // 解析每一行
|
|
|
preg_match_all('/<row[^>]*>(.*?)<\/row>/s', $content, $row_matches);
|
|
preg_match_all('/<row[^>]*>(.*?)<\/row>/s', $content, $row_matches);
|
|
|
- foreach ($row_matches[1] as $row) {
|
|
|
|
|
- $cols = [];
|
|
|
|
|
- preg_match_all('/<c[^>]*><v>([^<]+)<\/v><\/c>/', $row, $m);
|
|
|
|
|
- foreach ($m[1] ?? [] as $v) {
|
|
|
|
|
- $cols[] = is_numeric($v) && isset($str_map[$v]) ? $str_map[$v] : $v;
|
|
|
|
|
|
|
+ foreach ($row_matches[1] as $row_xml) {
|
|
|
|
|
+ $cols = array_fill(0, 6, ''); // 固定6列,防止错位
|
|
|
|
|
+ $cellIndex = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // 解析单元格
|
|
|
|
|
+ preg_match_all('/<c r="[^"]+"(?: t="([^"]+)")?[^>]*>(.*?)<\/c>/s', $row_xml, $cell_matches);
|
|
|
|
|
+ foreach ($cell_matches[0] as $i => $cell_xml) {
|
|
|
|
|
+ if ($cellIndex >= 6) break; // 只取前6列
|
|
|
|
|
+
|
|
|
|
|
+ $cell_type = $cell_matches[1][$i] ?? '';
|
|
|
|
|
+ $cell_inner = $cell_matches[2][$i] ?? '';
|
|
|
|
|
+ $value = '';
|
|
|
|
|
+
|
|
|
|
|
+ // 读取单元格值
|
|
|
|
|
+ if (preg_match('/<v>([^<]+)<\/v>/', $cell_inner, $v_match)) {
|
|
|
|
|
+ $value = $v_match[1];
|
|
|
|
|
+ } elseif (preg_match('/<t>([^<]+)<\/t>/', $cell_inner, $t_match)) {
|
|
|
|
|
+ $value = $t_match[1];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理共享字符串
|
|
|
|
|
+ if ($cell_type === 's' && isset($str_map[$value])) {
|
|
|
|
|
+ $value = $str_map[$value];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $cols[$cellIndex] = $value;
|
|
|
|
|
+ $cellIndex++;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
$rows[] = $cols;
|
|
$rows[] = $cols;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return $rows;
|
|
return $rows;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 读取 xls
|
|
|
|
|
- */
|
|
|
|
|
private function readXls($file)
|
|
private function readXls($file)
|
|
|
{
|
|
{
|
|
|
$data = file_get_contents($file);
|
|
$data = file_get_contents($file);
|