model = FactoryInfoModel::class; $this->selectField = ['id', 'name', 'phone', 'classification', 'cover', 'address', 'status', 'created_at', 'updated_at']; $this->queryField = ['name' => 'like', 'phone' => 'like', 'classification' => '=', 'status' => '=']; $this->media = MediaUrlService::getInstance(); } /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ public function list(): array { $this->with = ['classificationInfo']; $result = $this->getPageList(); foreach ($result['items'] as &$item) { $item['classification_name'] = $item['classification_info']['name'] ?? ''; unset($item['classification_info']); $item['cover'] = $this->media->toPublic($item['cover'] ?? ''); } unset($item); return $result; } public function option(): mixed { return $this->getOption(); } /** * @throws Exception */ public function detail($id): mixed { $info = $this->getDetail($id); $info->cover = $this->media->toPublic($info->cover); return $info; } public function create($params): mixed { if (array_key_exists('cover', $params)) { $params['cover'] = $this->media->firstOf($params['cover']); } return $this->insert($params); } /** * @throws Exception */ public function update($id, $params): mixed { if (array_key_exists('cover', $params)) { $params['cover'] = $this->media->firstOf($params['cover']); } return $this->save($id, $params); } /** * 删除工厂时连带软删它的产品图,避免留下查不到工厂的图片 * @throws Exception */ public function delete($id): mixed { $ids = array_values(array_filter(array_map('intval', is_array($id) ? $id : [$id]))); if (empty($ids)) { $this->utils->errorThrow('参数错误'); } $now = time(); FactoryImageModel::whereIn('factory', $ids)->where('deleted_at', 0) ->update(['deleted_at' => $now, 'updated_at' => $now]); return $this->del($ids); } /** * @throws Exception */ public function status($id, $status): mixed { return $this->save($id, ['status' => (int) $status]); } /** * 导出工厂表:只回结构化数据,xlsx 由前端 ExcelJS 美化 */ public function exportExcel(): array { $rows = FactoryInfoModel::where('deleted_at', 0)->orderByDesc('id')->get([ 'id', 'name', 'phone', 'classification', 'address', 'status', ])->toArray(); foreach ($rows as &$row) { $row['status'] = (int) ($row['status'] ?? 0) === 0 ? '启用' : '禁用'; } unset($row); return [ 'filename' => 'factory.xlsx', 'title' => '工厂信息', 'sheet' => '工厂', 'columns' => [ ['key' => 'id', 'header' => 'ID', 'width' => 10, 'align' => 'center'], ['key' => 'name', 'header' => '工厂名称', 'width' => 22], ['key' => 'phone', 'header' => '电话', 'width' => 16], ['key' => 'classification', 'header' => '分类ID', 'width' => 12, 'align' => 'center'], ['key' => 'address', 'header' => '地址', 'width' => 32], ['key' => 'status', 'header' => '状态', 'width' => 10, 'align' => 'center'], ], 'rows' => $rows, ]; } /** * 导入工厂:前端 ExcelJS 拆好的行,按 name 更新 */ public function importRows(array $rows): array { $created = 0; $updated = 0; $now = time(); foreach ($rows as $row) { if (!is_array($row)) { continue; } $name = trim((string) ($row['name'] ?? $row['工厂名称'] ?? '')); if ($name === '') { continue; } $payload = [ 'name' => $name, 'phone' => (string) ($row['phone'] ?? $row['电话'] ?? ''), 'classification' => (int) ($row['classification'] ?? $row['分类ID'] ?? 0), 'address' => (string) ($row['address'] ?? $row['地址'] ?? ''), 'status' => $this->parseStatus($row['status'] ?? $row['状态'] ?? 0), 'updated_at' => $now, ]; $exists = FactoryInfoModel::where('name', $name)->where('deleted_at', 0)->first(); if (!empty($exists)) { FactoryInfoModel::where('id', $exists['id'])->update($payload); $updated++; } else { $payload['created_at'] = $now; FactoryInfoModel::insert($payload); $created++; } } return ['created' => $created, 'updated' => $updated]; } /** * Excel 状态列可能是「启用/禁用」或 0/1,统一成库里的数字 */ private function parseStatus(mixed $value): int { $raw = trim((string) $value); if (in_array($raw, ['上架', '启用', '正常', '0', ''], true)) { return 0; } if (in_array($raw, ['下架', '禁用', '1'], true)) { return 1; } return ((int) $raw) === 1 ? 1 : 0; } }