series = $series; $this->brands = $brands; $data = array_merge($brands, $series); $tree = $this->buildTree($data); $formattedTree = $this->formatTree($tree); $service = [ [ 'label' => '全部', 'value' => null ] ]; foreach ($formattedTree as $item) { $item['children'] = [ [ 'label' => $item['label'], 'value' => 'b_' . $item['value'] ], ...$item['children'] ]; $service [] = $item; } $data = Attributes::order('sort_order')->select(); $res = []; foreach ($data as $datum) { $datum->options = json_decode($datum->options); $re = $datum->toArray(); $out = [ 'id' => $re['id'], 'label' => $re['name'], 'type' => $re['input_type'], 'options' => $re['options'], 'name' => $re['field_key'], 'value' => $value_map[$re['id']] ?? null, ]; $res [] = $out; } $out = [ 'brands' => $service, 'extend' => $res ]; return $this->return_json($out); } public function car() { $data = request()->post(); $build = Cars::where('is_active', 1); $attr = $data['attr'] ?? null; $brand = $data['brand'] ?? null; $type = $data['type'] ?? 1; $price = $data['price'] ?? null; $sort = $data['sort'] ?? 1; if ($attr) { $ids = $this->getAttrIds($attr); $build->whereIn('id', $ids); } if ($brand) { if (str_starts_with($brand, 'b')) { $build->whereIn('brand_id', str_replace('b_', '', $brand)); } else { $build->whereIn('series_id', $brand); } } if (!empty($price)) { $prices = explode('-', $price); $build->whereBetween('price', $prices); } if (!empty($sort)) { $sort = explode('-', $sort); $build->order($sort[0], $sort[1]); } else { $build->order('id', 'desc'); } $build->where('car_type', $type); $list = $build->paginate(); $res = []; $car_ids = []; foreach ($list->items() as $item) { $out = $item->toArray(); $car_ids [] = $item['id']; if ($out['cover_image']) { $images = explode(',', $out['cover_image']); $images = array_map(function ($url) { return cdnurl($url, true) . '?imageMogr2/format/webp'; // true 表示生成绝对路径 }, $images); $out['cover_image'] = $images; } $res [] = $out; } $attr_value = AttributeValue::whereIn('car_id', $car_ids)->select(); $attr_array = []; foreach ($attr_value as $item) { $attr_array [] = $item->toArray(); } $attr_field = Attributes::order('sort_order')->select(); $attr_field_array = []; foreach ($attr_field as $datum) { $datum->options = json_decode($datum->options, true); $re = $datum->toArray(); $out = [ 'id' => $re['id'], 'label' => $re['name'], 'type' => $re['input_type'], 'options' => $re['options'], 'name' => $re['field_key'], 'sort_order' => $re['sort_order'], ]; $attr_field_array [] = $out; } $car_attr_map = $this->mapAllCarAttributesSorted($attr_array, $attr_field_array); foreach ($res as &$re) { if (isset($car_attr_map[$re['id']])) { $re['attr'] = array_splice($car_attr_map[$re['id']], 0, 3); } } return $this->return_json( [ 'total' => $list->total(), 'items' => $res ] ); } public function banners() { $banner = config('site.banner_images'); // 获取轮播图数组 $out = []; foreach ($banner as $item) { $out [] = cdnurl($item) . '?imageMogr2/format/webp'; } if (!empty(config('site.location'))){ $location = explode(',', config('site.location') ?? ''); }else{ $location = []; } $company = [ 'name' => config('site.name'), 'address' => config('site.address') ?? '', 'latitude' => $location[0] ?? 31.854870, // 地图坐标 'longitude' => $location [1] ?? 106.746141, 'phone' => config('site.tel') ??'' ]; $res = [ 'banner' => $out, 'company' => $company ]; return $this->return_json($res); } public function carInfo() { $id = request()->get('id'); $build = Cars::where('is_active', 1)->where('id', $id)->with([ 'brand', 'series', 'contact' => function ($q) { $q->field('id,username,mobile'); } ]); $car = $build->select()[0]; if (!$car) { return $this->return_json([], '未找到信息', code: 0); } $car = $car->toArray(); if ($car['cover_image']) { $images = explode(',', $car['cover_image']); $images = array_map(function ($url) { return cdnurl($url, true) . '?imageMogr2/format/webp'; // true 表示生成绝对路径 }, $images); $car['cover_image'] = $images; } $attr_value = AttributeValue::where('car_id', $car['id'])->select(); $attr_array = []; foreach ($attr_value as $item) { $attr_array [] = $item->toArray(); } $attr_field = Attributes::order('sort_order')->select(); $attr_field_array = []; foreach ($attr_field as $datum) { $datum->options = json_decode($datum->options, true); $re = $datum->toArray(); $out = [ 'id' => $re['id'], 'label' => $re['name'], 'type' => $re['input_type'], 'options' => $re['options'], 'name' => $re['field_key'], 'sort_order' => $re['sort_order'], ]; $attr_field_array [] = $out; } $car_attr_map = $this->mapAllCarAttributesSorted($attr_array, $attr_field_array); // dd($car_attr_map); $car['attr'] = $car_attr_map[$car['id']] ?? []; return $this->return_json($car); } private function mapAllCarAttributesSorted(array $carAttributes, array $attributeDefs): array { // 把属性定义按 id 映射为键,并附带 sort_order $defMap = []; foreach ($attributeDefs as $def) { $defMap[$def['id']] = $def; } // 先聚合 car_id 下的属性条目 $cars = []; foreach ($carAttributes as $attr) { $carId = $attr['car_id']; $attributeId = $attr['attribute_id']; $value = $attr['value']; if (empty($value)) continue; if (!isset($defMap[$attributeId])) continue; $def = $defMap[$attributeId]; $label = $def['label']; $type = $def['type']; $sortOrder = $def['sort_order']; $key = null; if ($type === 'checkbox') { foreach ($def['options'] as $opt) { if ((string)$opt['value'] === (string)$value) { $key = $opt['key']; break; } } } elseif ($type === 'range') { $key = $value . $def['options']['unit']; } if (!is_null($key)) { $cars[$carId][] = [ 'label' => $label, 'key' => $key, 'sort_order' => $sortOrder ]; } } // 对每个 car_id 下的属性按 sort_order 排序,并转成 label => key 格式 $result = []; foreach ($cars as $carId => $items) { usort($items, function ($a, $b) { return $a['sort_order'] <=> $b['sort_order']; }); foreach ($items as $item) { $result[$carId][$item['label']] = $item['key']; } } return $result; } private function getAttrIds($attrs) { $attrDB = Attributes::field('id,field_key,input_type')->select(); $attr_array = []; foreach ($attrDB as $item) { $attr_array[] = $item->toArray(); } $attr_map = array_column($attr_array, null, 'field_key'); $car_id = []; foreach ($attrs as $key => $item) { if (isset($attr_map[$key])) { $field = $attr_map[$key]; if ($field['input_type'] == 'checkbox') { $ids = AttributeValue::where('attribute_id', $field['id']) ->whereIn('value', $item)->column('DISTINCT car_id'); if ($car_id) { $car_id = array_intersect($car_id, $ids); } else { $car_id = $ids; } } elseif ($field['input_type'] == 'range') { $ids = AttributeValue::where('attribute_id', $field['id']) ->where('value', '>=', $item['start']) ->where('value', '<=', $item['end']) ->column('DISTINCT car_id'); if ($car_id) { $car_id = array_intersect($car_id, $ids); } else { $car_id = $ids; } } } } return array_values(array_unique($car_id)); } }