success('产品_基本资料'); } /** * 获取左侧菜单产品分类列表 * 按 product_type 分组 → 分类下显示对应产品 */ public function ProductTypeMenu() { if (Request::instance()->isGet() == false) { $this->error('非法请求'); } $params = Request::instance()->param(); // 获取所有产品 $productList = \db('产品_基本资料')->whereNull('mod_rq') ->column('id,product_code,product_name,product_type'); $data = []; if ($productList) { foreach ($productList as $item) { $type = $item['product_type'] ?: '未分类'; // 分类 $data[$type]['name'] = $type; // 分类下的产品 $data[$type]['list'][] = [ 'id' => $item['id'], 'product_code' => $item['product_code'], 'product_name' => $item['product_name'] ]; } } // 转成索引数组返回 $result = array_values($data); $this->success('获取成功', $result); } /** * 获取产品资料列表(产品→部件→工艺) */ public function ProductList() { if (!Request::instance()->isGet()) { $this->error('非法请求'); } $params = Request::instance()->param(); $where = []; if (!empty($params['search'])) { $where['product_code|product_name|product_type'] = ['like', '%' . $params['search'] . '%']; } $limit = empty($params['limit']) ? 30 : $params['limit']; $pages = empty($params['page']) ? 1 : $params['page']; // 1. 查询产品主表 $productList = db('产品_基本资料') ->whereNull('mod_rq') ->where($where) ->page($pages, $limit) ->order('id desc') ->select(); if (empty($productList)) { $this->success('获取成功', ['list' => [], 'count' => 0]); } // 提取产品编号 $productCodes = array_column($productList, 'product_code'); // 2. 查询部件(按 product_code 关联,并按 part_sort 排序) $parts = db('产品_部件资料') ->whereNull('mod_rq') ->whereIn('product_code', $productCodes) ->order('part_sort asc') // 按部件排序号升序 ->select(); // 提取 (product_code + part_sort) 作为关联键 $partKeys = []; foreach ($parts as $p) { $key = $p['product_code'] . '_' . $p['part_sort']; $partKeys[] = $key; } // 3. 查询工艺(按 product_code + part_sort 关联,并按 gy_sort 排序) $process = []; if (!empty($productCodes)) { $process = db('产品_工艺资料') ->whereNull('mod_rq') ->whereIn('product_code', $productCodes) ->order('part_sort asc, gy_sort asc') // 按部件排序+工序排序 ->select(); } // 部件按 product_code 分组 $partGroup = []; foreach ($parts as $val) { $partGroup[$val['product_code']][] = $val; } // 工艺按 (product_code + part_sort) 分组 $processGroup = []; foreach ($process as $val) { $key = $val['product_code'] . '_' . $val['part_sort']; $processGroup[$key][] = $val; } // 组装数据:产品 → 部件 → 工艺 foreach ($productList as &$product) { $currentParts = $partGroup[$product['product_code']] ?? []; foreach ($currentParts as &$item) { // 用 product_code + part_sort 关联工艺 $key = $product['product_code'] . '_' . $item['part_sort']; $item['processes'] = $processGroup[$key] ?? []; } $product['parts'] = $currentParts; } // 统计总数 $count = db('产品_基本资料') ->whereNull('mod_rq') ->where($where) ->count(); $this->success('获取成功', [ 'list' => $productList, 'count' => $count ]); } /** * 新增产品资料 */ public function ProductAdd() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $params = Request::instance()->param(); // 自动生成产品编号:CP000001 $lastCode = \db('产品_基本资料')->order('id desc')->value('product_code'); if ($lastCode) { $num = intval(str_replace('CP', '', $lastCode)) + 1; } else { $num = 1; } $params['product_code'] = 'CP' . str_pad($num, 6, '0', STR_PAD_LEFT); $data = []; $data['product_code'] = $params['product_code']; $data['product_name'] = $params['product_name']; $data['product_type'] = $params['product_type']; $data['unit'] = $params['unit']; $data['sys_id'] = $params['sys_id']; $data['status'] = 1; $data['sys_rq'] = date('Y-m-d H:i:s'); $result = \db('产品_基本资料')->insert($data); if ($result) { $this->success('新增成功'); } else { $this->error('新增失败'); } } /** * 修改产品资料 */ public function ProductEdit() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $params = Request::instance()->param(); if (empty($params['id'])) { $this->error('请选择数据'); } // 禁止修改编号 unset($params['product_code']); $data = []; $data['product_name'] = $params['product_name']; $data['product_type'] = $params['product_type']; $data['unit'] = $params['unit']; $data['sys_id'] = $params['sys_id']; $data['updatetime'] = date('Y-m-d H:i:s'); $result = \db('产品_基本资料') ->where('id', $params['id']) ->update($data); if ($result !== false) { $this->success('修改成功'); } else { $this->error('修改失败'); } } /** * 删除产品资料 */ public function ProductDelete() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $id = input('id'); if (empty($id)) { $this->error('请选择需要删除的数据'); } $ids = explode(',', $id); $result = \db('产品_基本资料') ->where('id', 'in', $ids) ->update(['mod_rq' => date('Y-m-d H:i:s')]); if ($result !== false) { $this->success('删除成功'); } else { $this->error('删除失败'); } } /** * 获取产品部件列表 */ public function ProductPartList() { if (Request::instance()->isGet() == false) { $this->error('非法请求'); } $params = Request::instance()->param(); $where = []; if (!empty($params['search'])) { $where['part_name'] = array('like', '%' . $params['search'] . '%'); } if (!empty($params['product_code'])) { $where['product_code'] = array('like', '%' . $params['product_code'] . '%'); } $limit = $params['limit']; if (empty($limit)) { $limit = 30; } $pages = $params['page']; if (empty($pages)) { $pages = 1; } $list = \db('产品_部件资料')->whereNull('mod_rq')->where($where)->page($pages)->limit($limit)->order('id desc')->select(); $count = \db('产品_部件资料')->whereNull('mod_rq')->where($where)->page($pages)->limit($limit)->count(); $this->success('获取成功', ['list' => $list, 'count' => $count]); } /** * 新增部件资料(支持批量) */ public function PartAdd() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $params = Request::instance()->param(); // 必传校验 if (empty($params['product_code']) || empty($params['part_list'])) { $this->error('产品编号/部件列表不能为空'); } $productCode = $params['product_code']; $sysId = $params['sys_id']; $partList = $params['part_list']; // 组装批量数据 $insertData = []; foreach ($partList as $item) { if (empty($item['part_name']) || empty($item['part_sort'])) { continue; // 跳过无效数据 } $insertData[] = [ 'product_code' => $productCode, 'part_sort' => $item['part_sort'], 'part_name' => $item['part_name'], 'sys_id' => $sysId, 'sys_rq' => date('Y-m-d H:i:s'), 'mod_rq' => null ]; } if (empty($insertData)) { $this->error('无有效部件数据'); } $res = db('产品_部件资料')->insertAll($insertData); return $res ? $this->success('新增成功') : $this->error('新增失败'); } /** * 修改部件资料 */ public function PartEdit() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $params = Request::instance()->param(); // 必传校验 if (empty($params['id']) || empty($params['part_name'])) { $this->error('ID/部件名称不能为空'); } $data = [ 'part_name' => $params['part_name'], 'sys_id' => $params['sys_id'], 'updatetime' => date('Y-m-d H:i:s') ]; $res = db('产品_部件资料') ->where('id', $params['id']) ->whereNull('mod_rq') ->update($data); return $res !== false ? $this->success('修改成功') : $this->error('修改失败'); } /** * 删除部件资料 */ public function PartDelete() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $id = input('id'); if (empty($id)) { $this->error('请选择需要删除的数据'); } $ids = explode(',', $id); $result = \db('产品_部件资料') ->where('id', 'in', $ids) ->update(['mod_rq' => date('Y-m-d H:i:s')]); if ($result !== false) { $this->success('删除成功'); } else { $this->error('删除失败'); } } /** * 获取产品工艺列表 */ public function ProductGyList() { if (!Request::instance()->isGet()) { $this->error('非法请求'); } $params = Request::instance()->param(); $where = []; if (!empty($params['search'])) { $where['a.gy_name'] = ['like', '%' . $params['search'] . '%']; } if (!empty($params['product_code'])) { $where['a.product_code'] = $params['product_code']; } $limit = empty($params['limit']) ? 30 : $params['limit']; $pages = empty($params['page']) ? 1 : $params['page']; //获取产品_工艺数据 $list = \db('产品_工艺资料')->alias('a') ->join('产品_部件资料 b', 'a.product_code = b.product_code AND a.part_sort = b.part_sort', 'LEFT') ->field(' a.id, a.product_code, a.part_sort, a.gy_sort, a.gy_name, a.big_process, a.standard_hour, a.standard_score, a.difficulty_coef, a.sys_id, a.sys_rq, a.updatetime, b.part_name ') ->whereNull('a.mod_rq') ->whereNull('b.mod_rq') ->where($where) ->page($pages, $limit) ->order('a.part_sort asc, a.id asc') ->select(); //统计总数量 $count = \db('产品_工艺资料')->alias('a') ->join('产品_部件资料 b', 'a.product_code = b.product_code AND a.part_sort = b.part_sort', 'LEFT') ->whereNull('a.mod_rq') ->whereNull('b.mod_rq') ->where($where) ->count(); $this->success('获取成功', [ 'list' => $list, 'count' => $count ]); } /** * 新增工艺资料(批量) */ public function ProcessAdd() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $params = Request::instance()->param(); $sys_id = $params['sys_id']; $process_list = $params['process_list'] ?? []; if (empty($process_list)) { $this->error('工艺数据不能为空'); } $insertData = []; foreach ($process_list as $item) { // 必传校验 if (empty($item['gy_name']) || empty($item['big_process'])) { continue; } $insertData[] = [ 'product_code' => $item['product_code'], 'part_sort' => $item['part_sort'], 'part_name' => $item['part_name'], 'gy_sort' => $item['gy_sort'], 'gy_name' => $item['gy_name'], 'big_process' => $item['big_process'], 'standard_hour' => $item['standard_hour'] ?? 0, 'standard_score' => $item['standard_score'] ?? 0, 'difficulty_coef' => $item['difficulty_coef'] ?? 1, 'sys_id' => $sys_id, 'sys_rq' => date('Y-m-d H:i:s') ]; } if (empty($insertData)) { $this->error('无有效工艺数据'); } $result = db('产品_工艺资料')->insertAll($insertData); return $result ? $this->success('新增成功') : $this->error('新增失败'); } /** * 修改工艺资料 */ public function ProcessEdit() { if (!Request::instance()->isPost()) { $this->error('非法请求'); } $params = Request::instance()->param(); //echo "
";
//print_r($params);
//echo "
";die;
        if (empty($params['id']) || empty($params['gy_name'])) {
            $this->error('ID/工序名称不能为空');
        }

        $data = [
            'gy_name' => $params['gy_name'],
            'big_process' => $params['big_process'],
//            'part_sort' => $params['part_sort'],
            'gy_sort' => $params['gy_sort'],
            'standard_hour' => $params['standard_hour'] ?? 0,
            'standard_score' => $params['standard_score'] ?? 0,
            'difficulty_coef' => $params['difficulty_coef'] ?? 1,
            'sys_id' => $params['sys_id'],
            'updatetime' => date('Y-m-d H:i:s')
        ];

        $res = db('产品_工艺资料')
            ->where('id', $params['id'])
            ->whereNull('mod_rq')
            ->update($data);

        return $res !== false ? $this->success('修改成功') : $this->error('修改失败');
    }

    /**
     * 删除工艺资料
     */
    public function ProcessDelete()
    {
        if (!Request::instance()->isPost()) {
            $this->error('非法请求');
        }

        $id = input('id');
        if (empty($id)) {
            $this->error('请选择需要删除的数据');
        }

        $ids = explode(',', $id);

        $result = \db('产品_工艺资料')
            ->where('id', 'in', $ids)
            ->update(['mod_rq' => date('Y-m-d H:i:s')]);

        if ($result !== false) {
            $this->success('删除成功');
        } else {
            $this->error('删除失败');
        }
    }

    /**
     * 调整部件与工艺序号牌组
     */
    public function UpdataSort(){
        if (!Request::instance()->isPost()) {
            $this->error('非法请求');
        }

        $params = Request::instance()->param();

        $product_code = $params['product_code'];
        $sys_id       = $params['sys_id'];

        if (empty($product_code)) {
            $this->error('产品编号不能为空');
        }

        // ======================
        // 更新 产品_部件资料
        // ======================
        if (!empty($params['part_list']) && is_array($params['part_list'])) {
            foreach ($params['part_list'] as $item) {
                $id = $item['id'] ?? 0;
                if ($id <= 0) continue;

                // 🔥 把要更新的内容放变量里
                $updateData = [
                    'part_sort' => $item['part_sort'],
                    'part_name' => $item['part_name'],
                    'sys_id'  => $sys_id
                ];

                Db::name('产品_部件资料')
                    ->where('id', $id)
                    ->update($updateData);
            }
        }

        // ======================
        // 更新 产品_工艺资料
        // ======================
        if (!empty($params['process_list']) && is_array($params['process_list'])) {
            foreach ($params['process_list'] as $item) {
                $id = $item['id'] ?? 0;
                if ($id <= 0) continue;

                // 🔥 把要更新的内容放变量里
                $updateData = [
                    'gy_sort'        => $item['gy_sort'],
                    'gy_name'        => $item['gy_name'] ,
                    'big_process'    => $item['big_process'],
                    'standard_hour'  => $item['standard_hour'],
                    'standard_score' => $item['standard_score'],
                    'part_sort'      => $item['part_sort'],
                    'part_name'      => $item['part_name'],
                    'sys_id'       => $sys_id
                ];

                Db::name('产品_工艺资料')
                    ->where('id', $id)
                    ->update($updateData);
            }
        }

        $this->success('排序更新成功');
    }

    /**
     * Excel 导入 部件 + 工艺
     */
    public function ProcessExcel(){
        if (!Request::instance()->isPost()) {
            $this->error('非法请求');
        }

        $params = Request::instance()->param();
        $file = request()->file('file');

        // 1. 先判断文件是否存在
        if (empty($file)) {
            $this->error('请上传Excel文件');
        }

        // 2. 必传参数校验
        $product_code = $params['product_code'];
        $sys_id = $params['sys_id'];

        if (empty($product_code)) {
            $this->error('请选择产品后,再进行提交');
        }

        // 3. 正确获取文件扩展名(解决 getExtension 为空的问题)
        $fileInfo = $file->getInfo();
        $fileName = $fileInfo['name'];
        $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));

        if (!in_array($ext, ['xlsx', 'xls'])) {
            $this->error('只支持 xls / xlsx 格式');
        }

        $file_path = $file->getRealPath();
        $data = [];

        if ($ext == 'xlsx') {
            $data = $this->readXlsx($file_path);
        } elseif ($ext == 'xls') {
            $data = $this->readXls($file_path);
        }

        // 4. 解析数据
        $rows = array_slice($data, 1);
        $insert_data = [];
        foreach ($rows as $row) {
            $part_name = trim($row[0] ?? '');
            $gy_name = trim($row[1] ?? '');
            if (empty($part_name) || empty($gy_name)) continue;

            $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),
            ];
        }

        if (empty($insert_data)) {
            $this->error('Excel 无有效数据');
        }

        // 5. 处理部件
        $part_map = [];
        $part_sort = 1;
        foreach ($insert_data as $item) {
            $name = $item['part_name'];
            if (!isset($part_map[$name])) {
                $part_map[$name] = $part_sort++;
            }
        }

        $part_all = [];
        foreach ($part_map as $name => $sort) {
            $part_all[] = [
                'product_code' => $product_code,
                'part_sort'    => $sort,
                'part_name'    => $name,
                'sys_id'       => $sys_id,
                'sys_rq'   => date('Y-m-d H:i:s'),
                'mod_rq'       => null
            ];
        }

        // 6. 处理工艺
        $gy_sort_map = [];
        $process_all = [];
        foreach ($insert_data as $item) {
            $part_sort = $part_map[$item['part_name']];
            $gy_sort_map[$part_sort] = isset($gy_sort_map[$part_sort]) ? $gy_sort_map[$part_sort] + 1 : 1;

            $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'],
                'difficulty_coef' => $item['difficulty_coef'],
                'sys_id'          => $sys_id,
                'sys_rq'      => date('Y-m-d H:i:s'),
                'mod_rq'       => null
            ];
        }

echo "
";
print_r($part_all);
echo "
";die;
        // 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);

        $this->success('导入成功', [
            '部件数量' => count($part_all),
            '工艺数量' => count($process_all)
        ]);
    }

    private function readXlsx($file)
    {
        if (!class_exists('ZipArchive')) {
            return [];
        }

        $zip = new \ZipArchive();
        if ($zip->open($file) !== true) {
            return [];
        }

        // 读取工作表内容和共享字符串
        $content = $zip->getFromName('xl/worksheets/sheet1.xml');
        $strings = $zip->getFromName('xl/sharedStrings.xml');
        $zip->close();

        // 解析共享字符串
        $str_map = [];
        if ($strings) {
            preg_match_all('/]*>([^<]+)<\/t><\/si>/s', $strings, $matches);
            $str_map = $matches[1] ?? [];
        }

        $rows = [];
        // 解析每一行
        preg_match_all('/]*>(.*?)<\/row>/s', $content, $row_matches);
        foreach ($row_matches[1] as $row_xml) {
            $cols = array_fill(0, 6, ''); // 固定6列,防止错位
            $cellIndex = 0;

            // 解析单元格
            preg_match_all('/]*>(.*?)<\/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>/', $cell_inner, $v_match)) {
                    $value = $v_match[1];
                } elseif (preg_match('/([^<]+)<\/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;
        }

        return $rows;
    }

    private function readXls($file)
    {
        $data = file_get_contents($file);
        $rows = [];
        $len = strlen($data);
        $p = 0;

        while ($p < $len) {
            $id = ord($data[$p]);
            $size = unpack('v', substr($data, $p + 1, 2))[1];
            if ($id == 0x20) {
                $row = [];
                $sp = $p + 4;
                while ($sp < $p + $size) {
                    $type = ord($data[$sp]);
                    if ($type == 0x02) {
                        $val = substr($data, $sp + 3, 1);
                        $row[] = trim($val);
                        $sp += 8;
                    } else {
                        $sp++;
                    }
                }
                if (!empty($row)) $rows[] = $row;
            }
            $p += $size;
        }
        return $rows;
    }
}