From e5afa43198da71f6b7b9cd43ab7e77c0942ccf4c Mon Sep 17 00:00:00 2001
From: "WIN-C27C5MSVTPO\\16961" <1696136552@qq.com>
Date: Tue, 27 Jan 2026 15:50:18 +0800
Subject: [PATCH] 1
---
.../controller/WordpressSiteController.php | 56 ++
app/common/model/WordpressSite.php | 49 +
app/common/model/WordpressUsedCar.php | 49 +
app/common/service/WordpressSiteService.php | 868 ++++++++++++++++++
app/common/validate/WordpressSiteValidate.php | 29 +
config/route.php | 16 +-
6 files changed, 1066 insertions(+), 1 deletion(-)
create mode 100644 app/admin/controller/WordpressSiteController.php
create mode 100644 app/common/model/WordpressSite.php
create mode 100644 app/common/model/WordpressUsedCar.php
create mode 100644 app/common/service/WordpressSiteService.php
create mode 100644 app/common/validate/WordpressSiteValidate.php
diff --git a/app/admin/controller/WordpressSiteController.php b/app/admin/controller/WordpressSiteController.php
new file mode 100644
index 0000000..199c05b
--- /dev/null
+++ b/app/admin/controller/WordpressSiteController.php
@@ -0,0 +1,56 @@
+service = new WordpressSiteService();
+ }
+
+ //推送,在wp站点上创建产品
+ public function createProduct(Request $request){
+ try {
+ $domain = $request->get('domain');
+ $id = $request->get('id');
+ $res = $this->service->createProduct($domain,$id);
+ return $this->success($res, '推送成功');
+ } catch (\Throwable $e) {
+ return $this->error($e->getMessage().'-'.$e->getLine().'-'.$e->getFile());
+ }
+ }
+
+ public function uploadImageToWp(Request $request){
+ try {
+ $domain = $request->get('domain');
+ $res = $this->service->uploadImageToWp($domain);
+ return $this->success($res, '推送成功');
+ } catch (\Throwable $e) {
+ return $this->error($e->getMessage());
+ }
+ }
+
+ /**
+ * 列表页数据格式化
+ *
+ * @param array $data
+ * @return array
+ */
+ // protected function indexFormat($data)
+ // {
+ // if (isset($data['created_at']))
+ // $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
+ // if (isset($data['updated_at']))
+ // $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
+ // return $data;
+ // }
+}
\ No newline at end of file
diff --git a/app/common/model/WordpressSite.php b/app/common/model/WordpressSite.php
new file mode 100644
index 0000000..d260df1
--- /dev/null
+++ b/app/common/model/WordpressSite.php
@@ -0,0 +1,49 @@
+validator;
+ }
+
+ /**
+ * @param Request $request
+ * @return mixed|Response
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function createPost(Request $request)
+ {
+ $client = new Client();
+ $url = "https://37car.dev.hnxinyouhe.com/wp-json/wp/v2/posts";
+
+ $data = [
+ "title" => "API 创建文章",
+ "content" => "内容来自 API",
+ "status" => "publish"
+ ];
+
+ try {
+ $response = $client->post($url, [
+ RequestOptions::AUTH => ['Borderless', '3Tdw 6O02 DM6f lb2S 7T3l WG8a'],
+ RequestOptions::JSON => $data,
+ RequestOptions::VERIFY => false, // 禁用 SSL 验证
+ ]);
+
+ $result = json_decode($response->getBody()->getContents(), true);
+
+ return $result;
+
+ } catch (\Exception $e) {
+ throw new \Exception($e->getMessage());
+ }
+ }
+
+ /**
+ * @param Request $request
+ * @return mixed|Response
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ public function createProduct(string $domain, $id)
+ {
+ $site = WordpressSite::where('site_url',$domain)->first();
+
+ //判断是否重复推送
+ $wpUsed = WordpressUsedCar::where('wp_site_id', $site['id'])->where('used_car_id', $id)->first();
+ if($wpUsed && ($wpUsed['retry_count']>2 || $wpUsed['status'] ==1)){
+ $site->last_uid = $id;
+ $site->save();
+ return '重复推送';
+ }
+
+ $client = new Client();
+// $url = $domain."/wp-json/wc/v3/products";
+ $url = $domain."/wp-json/wp/v2/product";
+
+ $row = UsedCar::where('id', $id)->first();
+ $ucImages = explode(",", $row->images);
+
+ //车辆相册
+ $images = [];
+ foreach ($ucImages as $ucImage) {
+ $image = $this->uploadImageToWp($domain, $site['api_user'], $site['api_secret'], $ucImage);
+ $images[] = ['id' => $image['id']];
+ }
+ $images = array_merge([$images[0]], $images);
+
+ //车辆详细信息
+ /*$detils= $this->drawDetils($row);
+ $detils_params_html = [];
+ foreach ($detils as $key => $detil) {
+ if(is_array($detil)){
+ $detil = implode(",", $detil);
+ }
+ $detils_params_html[] =$key.':'.(string)$detil;
+ }
+ $detils_params_html = implode(PHP_EOL, $detils_params_html);*/
+// $detils_params_html = $this->buildVehicleDetailsTable($detils);
+
+ //语言确定目标网站的语言
+ $locale = match ($row['locale']) {
+ 'en' => '英文',
+ 'ru' => '俄语',
+ 'ar' => '阿拉伯语',
+ 'fr ' => '法语',
+ default => '英文',
+ };
+
+ $spark = new SparkService();
+ $car_name = $row['product_name'];
+ $car_name_locale = $spark->chat('将车辆名称翻译为'.$locale.':'.$car_name,null,[],'wpSend');
+ $condition_desc_locale = $spark->chat("下面是车辆的车况介绍将卖家信息去掉,包括但不限于商家名称、集团简介、经销商信息、地址、电话、商家介绍等都去掉\"".$row['condition_desc']."\"",null,[],'wpSend');
+ $condition_desc_locale = $spark->chat("将下列车况描述翻译为".$locale.":".$condition_desc_locale);
+
+ $data = [
+ "name" => $car_name_locale,
+ "type" => "simple", //单品,不走规格变体
+ "regular_price" => number_format(($row['price']*$site['exchange_rate']), 2),
+ "sku" => "",
+ //"featured" => true,//是否精选
+ "description" => $condition_desc_locale,
+ "stock_status" => "instock",//instock现车
+// "categories" => [
+// ["id" => 16],//used二手车
+// ],
+ "images" => $images,
+ ];
+ $data['categories'][] = ["id" => $site['categories']];
+
+ //车辆档案相关参数
+ $meta = $this->drawMeta($row['used_detail']);
+
+ //车身颜色
+ $color = '';
+ foreach ($meta as $item){
+ if (!empty($item['key']) && $item['key'] == 'color') {
+ $color = $item['value'];
+ $color = $this->sparkTransl($spark,$color,$locale);
+ }
+ }
+ if ($site['tpl_type'] == 2) {
+ $meta = [];
+ }
+
+ //$configDetail = json_decode($row['config_detail'], true);
+
+ //车身级别
+ /*$body_style = '';
+ foreach ($configDetail[0]['items'] as $item){
+ if (!empty($item['key']) && $item['key'] == 'jb') {
+ $body_style = $item['value'];
+ $body_style = $this->sparkTransl($spark,$body_style,$locale);
+ }
+ }*/
+
+ //产品设置相关参数
+ $meta[] = [
+ 'key' => 'pro-intro-txt',//产品参数简介
+ 'value' => "
+ - Engine Size{$row['displacement']}
+ - Engine Power{$row['power']}
+ - Mileage(KM){$row['mileage']}
+ - Color{$color}
+
",
+ ];
+// Engine Size
+//Engine Power
+//Mileage
+//Color
+// Year{$row['year']}
+// Body Style{$body_style}
+
+ //属性:品牌、车体类型、颜色
+ $brand_locale = $spark->chat('将车辆品牌翻译为'.$locale.':'.$row['brand_name'],null,[],'wpSend');
+ $data['attributes'][] = [ //品牌
+ "id" => "1",
+ "visible" => true,
+ "variation" => false,
+ "options" => [$brand_locale]
+ ];
+ /*$data['attributes'][] = [ //车体类型
+ "id" => "2",
+ "visible" => true,
+ "variation" => false,
+ "options" => [$body_style]
+ ];*/
+ $data['attributes'][] = [ //颜色
+ "id" => "4",
+ "visible" => true,
+ "variation" => false,
+ "options" => [$color]
+ ];
+
+ // 构建车辆简介描述
+// $baseInfo = $this->parseCarConfigDetail($row['format_car_info']);
+// $vehicleDescription = $this->buildVehicleDescription($row, $baseInfo, $meta, $configDetail);
+
+ //翻译车辆简介描述
+ $desc = "车辆名称:{$car_name},车辆参数:".json_encode($meta)."车辆简介:{$row['condition_desc']}";
+ $vehicleDescription_locale = $spark->chat('根据给出的信息生成'.$locale.'车辆简介描述:'.$desc,null,[],'wpSend');
+
+ $meta[] = [
+ 'key' => 'pro-intro-des',//产品简介
+ 'value' => $vehicleDescription_locale,
+ ];
+
+// $meta[] = [ //列表标签
+// 'key' => 'hotpro_mark',//自定义热门产品标签
+// 'value' => 'In Stock', //In Stock、HOT SALE
+// ];
+
+
+ $data['meta_data'] = array_values($meta);
+
+ try {
+ $response = $client->post($url, [
+ //RequestOptions::AUTH => ['Borderless', '3Tdw 6O02 DM6f lb2S 7T3l WG8a'],
+ RequestOptions::AUTH => [$site['api_user'], $site['api_secret']],
+ RequestOptions::JSON => $data,
+ RequestOptions::VERIFY => false, // 禁用 SSL 验证
+ ]);
+
+ $result = json_decode($response->getBody()->getContents(), true);
+
+ $wordpressUsedCar = [
+ 'wp_site_id' => $site['id'],
+ 'used_car_id' => $id,
+ 'wp_post_id' => $result['id'],
+ 'request_payload' => json_encode($data, JSON_UNESCAPED_UNICODE),
+ 'response_body' => $response->getBody()->getContents(),
+ 'status' => 1,
+ 'retry_count' => 1,
+ ];
+ WordpressUsedCar::create($wordpressUsedCar);
+
+ $site->last_uid = $id;
+ $site->save();
+
+ return $result;
+
+ } catch (\Exception $e) {
+ $his = WordpressUsedCar::where('wp_site_id', $site['id'])->where('used_car_id', $id)->first();
+ var_dump($his);
+ if ($his){
+ $his->retry_count = $his->retry_count + 1;
+ $his->save();
+ if ($his->retry_count>=3){
+ $site->last_uid = $id;
+ $site->save();
+ }
+ }else{
+ $wordpressUsedCar = [
+ 'wp_site_id' => $site['id'],
+ 'used_car_id' => $id,
+ 'request_payload' => json_encode($data, JSON_UNESCAPED_UNICODE),
+// 'response_body' => !empty($response)?$response->getBody()->getContents():$response,
+ 'error_message' => $e->getMessage(),
+ 'status' => 0,
+ 'retry_count' => 1,
+ ];
+ WordpressUsedCar::create($wordpressUsedCar);
+ }
+ throw new \Exception($e->getMessage());
+ }
+ }
+
+ /**
+ * 使用spark lite对话翻译,检查如果没有中文直接返回,有中文则翻译
+ * @param $spark
+ * @param $str
+ * @param $locale
+ * @return mixed
+ */
+ public function sparkTransl($spark,$str,$locale)
+ {
+ if(!(preg_match('/[\x{4e00}-\x{9fff}]/u', $str) > 0)){
+ return $str;
+ };
+ $str = str_replace(["“", "”"], "", $str);
+ //翻译
+ $vehicleDescription_locale = $spark->chat('将“'.$str.'”翻译为'.$locale,null,[],'wpSend');
+ return $vehicleDescription_locale;
+
+ }
+
+ /**
+ * 获取meta_data字段,即ACF自定义的字段
+ * @param $used_detail
+ * @return array
+ * @throws \Exception
+ */
+ public function drawMeta($used_car){
+ $fieldMap = [ //中文字段 → ACF 字段名
+ 'plate_time', //上牌时间
+ 'displacement', //排量
+ 'mileage', //里程
+ 'power', //马力
+ 'body_color', //车身颜色
+ 'source_place', //车源地
+ 'price', //价格
+ ];
+
+ $metaData = [];
+
+ foreach ($fieldMap as $acfKey) {
+ if (!empty($used_car[$acfKey])) {
+ $metaData[] = [
+ 'key' => $acfKey,
+ 'value' => $used_car[$acfKey],
+ ];
+ }
+ }
+
+ return $metaData;
+ }
+
+ /**
+ * 安全取值
+ */
+ public function drawDetils($row)
+ {
+ $baseInfo = $this->parseCarConfigDetail($row['format_car_info']);
+
+ return [
+ 'Ref ID' => $row['used_car_id'],
+
+ 'Model Code' => $row['model_code'] ?? $row['car_name'],
+
+ 'Model Year' => $row['year'],
+
+ 'Exterior Color' => value($baseInfo, 'body_color'),
+
+ 'Engine' => value($baseInfo, 'engine_description'),
+
+ 'Drivetrain' => value($baseInfo, 'driver_form'),
+
+ 'Range' => '–',
+
+ 'Seats' => value($baseInfo, 'seat_count'),
+
+ 'Dim.(mm)' => value($baseInfo, 'length_width_height'),
+
+ 'Weight(kg)' => value($baseInfo, 'curb_weight'),
+
+ 'Steering' => 'Left',
+
+ 'Body Type' => value($baseInfo, 'car_body_struct'),
+
+ 'Mlg(km)' => $row['usage_mileage'],
+
+ 'Fuel' => $row['fuel_form'],
+
+ 'Transmission' => value($baseInfo, 'gearbox_description'),
+
+ 'Batt.Cap.(kWh)' => value($baseInfo, 'battery_capacity'),
+
+ 'Motor Power(kW)' => value($baseInfo, 'motor_power'),
+
+ 'M³' => value($baseInfo, 'cargo_volume'),
+
+ 'Doors' => value($baseInfo, 'door_nums'),
+ ];
+ }
+
+
+ /**
+ * 安全取值
+ */
+ function value(array $array, string $key, $default = '–')
+ {
+ if (!isset($array[$key]) || $array[$key] === '' || $array[$key] === null) {
+ return $default;
+ }
+ return $array[$key];
+ }
+
+ /**
+ * 将 format_car_info 拉平成 key => value
+ *
+ * @param string $json
+ * @return array
+ */
+ function parseCarConfigDetail(string $json): array
+ {
+ $data = json_decode($json, true);
+ if (!is_array($data)) {
+ return [];
+ }
+
+ $result = [];
+
+ foreach ($data as $group) {
+ if (!isset($group['items']) || !is_array($group['items'])) {
+ continue;
+ }
+
+ foreach ($group['items'] as $item) {
+ if (!isset($item['key'])) {
+ continue;
+ }
+ $result[$item['key']] = $item['value'] ?? '';
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * 从 config_detail 中提取配置信息,拉平成 key => value
+ *
+ * @param array $configDetail
+ * @return array
+ */
+ private function parseConfigDetail(array $configDetail): array
+ {
+ if (!is_array($configDetail)) {
+ return [];
+ }
+
+ $result = [];
+
+ foreach ($configDetail as $group) {
+ if (!isset($group['items']) || !is_array($group['items'])) {
+ continue;
+ }
+
+ foreach ($group['items'] as $item) {
+ if (!isset($item['key'])) {
+ continue;
+ }
+ $key = $item['key'];
+ $value = $item['value'] ?? '';
+
+ // 如果值不为空,存储它(如果已存在相同key,保留第一个非空值)
+ if ($value !== '' && $value !== null && (!isset($result[$key]) || $result[$key] === '')) {
+ $result[$key] = $value;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * 从 config_detail 中获取指定配置项的值
+ *
+ * @param array $configDetail
+ * @param string|array $keys 要查找的key,可以是字符串或数组(多个可能的key)
+ * @param string $default 默认值
+ * @return string
+ */
+ private function getConfigValue($configDetail, $keys, $default = ''): string
+ {
+ if (!is_array($configDetail)) {
+ return $default;
+ }
+
+ $keysToSearch = is_array($keys) ? $keys : [$keys];
+
+ foreach ($configDetail as $group) {
+ if (!isset($group['items']) || !is_array($group['items'])) {
+ continue;
+ }
+
+ foreach ($group['items'] as $item) {
+ if (!isset($item['key'])) {
+ continue;
+ }
+
+ $itemKey = $item['key'];
+ $itemValue = $item['value'] ?? '';
+
+ // 检查是否匹配任何要查找的key
+ foreach ($keysToSearch as $searchKey) {
+ if ($itemKey === $searchKey && $itemValue !== '' && $itemValue !== null) {
+ return (string)$itemValue;
+ }
+ }
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * 构建车辆简介描述
+ *
+ * @param array $row 车辆基本信息
+ * @param array $baseInfo 车辆配置信息
+ * @param array $meta meta_data数组
+ * @param array $configDetail 配置详情
+ * @return string
+ */
+ public function buildVehicleDescription($row, $baseInfo, $meta, $configDetail): string
+ {
+ $parts = [];
+
+ // 1. 品牌 + 系列 + 年份 + 车型名称
+ $brandName = trim($row['brand_name'] ?? '');
+ $seriesName = trim($row['series_name'] ?? '');
+ $year = trim($row['year'] ?? '');
+ $carName = trim($row['car_name'] ?? '');
+
+ $modelParts = [];
+ if ($brandName) $modelParts[] = $brandName;
+ if ($seriesName) $modelParts[] = $seriesName;
+ if ($year) $modelParts[] = $year;
+
+ // 尝试从car_name中提取版本信息(如 "Champion Edition", "Champion PRO")
+ $version = '';
+ $carNameWithoutVersion = $carName;
+ if ($carName) {
+ // 如果car_name包含版本信息,提取出来
+ if (preg_match('/\s+([A-Z][a-zA-Z\s]+(?:Edition|PRO|PLUS|MAX|PRO|Limited))$/i', $carName, $matches)) {
+ $version = trim($matches[1]);
+ $carNameWithoutVersion = trim(str_replace($version, '', $carName));
+ }
+ $modelParts[] = $carNameWithoutVersion;
+ if ($version) {
+ $modelParts[] = $version;
+ }
+ }
+
+ // 2. 引擎和变速箱信息(优先从 config_detail 中获取)
+ $engine = $this->getConfigValue($configDetail, ['fdj', 'engine', 'engine_description', '发动机'], '');
+ if (empty($engine)) {
+ $engine = $this->value($baseInfo, 'engine_description', '');
+ }
+
+ $transmission = $this->getConfigValue($configDetail, ['bsx', 'gearbox', 'gearbox_description', 'transmission', '变速箱'], '');
+ if (empty($transmission)) {
+ $transmission = $this->value($baseInfo, 'gearbox_description', '');
+ }
+
+ if ($engine || $transmission) {
+ $engineParts = [];
+ if ($engine && $engine !== '–') $engineParts[] = $engine;
+ if ($transmission && $transmission !== '–') $engineParts[] = $transmission;
+ if (!empty($engineParts)) {
+ $modelParts[] = implode(' ', $engineParts);
+ }
+ }
+
+ if (!empty($modelParts)) {
+ $parts[] = implode(' ', $modelParts);
+ }
+
+ // 3. 座位数(优先从 config_detail 中获取)
+ $seatCount = $this->getConfigValue($configDetail, ['zws', 'seat_count', 'seat', 'seats', '座位数'], '');
+ if (empty($seatCount) || $seatCount === '–') {
+ $seatCount = $this->value($baseInfo, 'seat_count', '');
+ }
+ if ($seatCount && $seatCount !== '–' && is_numeric($seatCount)) {
+ $parts[] = "{$seatCount}-seater";
+ }
+
+ // 4. 外观颜色(优先从 config_detail 中获取)
+ $exteriorColor = $this->getConfigValue($configDetail, ['cys', 'body_color', 'color', 'exterior_color', '车身颜色'], '');
+ // 如果 config_detail 中没有,尝试从 baseInfo 中获取
+ if (empty($exteriorColor) || $exteriorColor === '–') {
+ $exteriorColor = $this->value($baseInfo, 'body_color', '');
+ }
+ // 如果 baseInfo 中也没有,尝试从 meta 中获取
+ if (empty($exteriorColor) || $exteriorColor === '–') {
+ foreach ($meta as $item) {
+ if (!empty($item['key']) && $item['key'] == 'color') {
+ $exteriorColor = $item['value'] ?? '';
+ break;
+ }
+ }
+ }
+
+ if ($exteriorColor && $exteriorColor !== '–') {
+ // 翻译颜色为英文(如果必要)
+ $exteriorColorEn = $this->translateColorToEnglish($exteriorColor);
+ $parts[] = "{$exteriorColorEn} exterior";
+ }
+
+ // 5. 内饰颜色(尝试从config_detail中查找)
+ $interiorColor = $this->getInteriorColor($configDetail, $baseInfo);
+ if ($interiorColor && trim($interiorColor) !== '') {
+ $interiorColorEn = $this->translateColorToEnglish($interiorColor);
+ // 如果翻译后仍然是原始的中文值(说明未找到映射),使用light-colored作为默认值
+ if ($interiorColorEn === mb_strtolower($interiorColor, 'UTF-8') && !preg_match('/^[a-z\s-]+$/i', $interiorColor)) {
+ $interiorColorEn = 'light-colored';
+ }
+ if ($interiorColorEn) {
+ $parts[] = "{$interiorColorEn} interior";
+ }
+ }
+
+ // 6. 使用时间(从上牌时间计算)
+ $licenseDate = '';
+ foreach ($meta as $item) {
+ if (!empty($item['key']) && $item['key'] == 'license_date') {
+ $licenseDate = $item['value'] ?? '';
+ break;
+ }
+ }
+
+ if ($licenseDate) {
+ $usageTime = $this->calculateUsageTime($licenseDate);
+ if ($usageTime) {
+ $parts[] = "used for {$usageTime}";
+ }
+ }
+
+ // 7. 行驶里程
+ $mileage = $row['usage_mileage'] ?? '';
+ if ($mileage && is_numeric($mileage)) {
+ $formattedMileage = number_format((float)$mileage, 0, '.', ',');
+ $parts[] = "traveled {$formattedMileage} kilometers";
+ }
+
+ return implode(', ', $parts) . '.';
+ }
+
+ /**
+ * 计算使用时间
+ *
+ * @param string $licenseDate 上牌时间,格式可能是 YYYY-MM-DD 或其他
+ * @return string|null
+ */
+ private function calculateUsageTime($licenseDate): ?string
+ {
+ if (empty($licenseDate)) {
+ return null;
+ }
+
+ try {
+ // 尝试解析日期
+ $date = null;
+ if (preg_match('/^(\d{4})-(\d{1,2})-(\d{1,2})/', $licenseDate, $matches)) {
+ $date = new \DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3]);
+ } elseif (preg_match('/^(\d{4})-(\d{1,2})/', $licenseDate, $matches)) {
+ $date = new \DateTime($matches[1] . '-' . $matches[2] . '-01');
+ } elseif (is_numeric($licenseDate) && strlen($licenseDate) == 10) {
+ // Unix时间戳
+ $date = new \DateTime('@' . $licenseDate);
+ }
+
+ if (!$date) {
+ return null;
+ }
+
+ $now = new \DateTime();
+ $diff = $now->diff($date);
+
+ $years = $diff->y;
+ $months = $diff->m;
+
+ if ($years > 0) {
+ $months += $years * 12;
+ }
+
+ if ($months == 0) {
+ // 如果不到1个月,显示天数
+ $days = $diff->days;
+ if ($days > 0) {
+ return $days == 1 ? "1 day" : "{$days} days";
+ }
+ return null;
+ }
+
+ if ($months == 1) {
+ return "1 month";
+ } else {
+ return "{$months} months";
+ }
+ } catch (\Exception $e) {
+ Log::error('计算使用时间失败', ['license_date' => $licenseDate, 'error' => $e->getMessage()]);
+ return null;
+ }
+ }
+
+ /**
+ * 获取内饰颜色
+ *
+ * @param array $configDetail
+ * @param array $baseInfo
+ * @return string
+ */
+ private function getInteriorColor($configDetail, $baseInfo): string
+ {
+ $possibleKeys = ['nsys', 'interior_color', 'interiorColor', 'seat_color', 'seatColor', '内饰颜色'];
+
+ // 优先从 configDetail 中查找
+ $color = $this->getConfigValue($configDetail, $possibleKeys, '');
+ if (!empty($color) && $color !== '–') {
+ return $color;
+ }
+
+ // 如果 configDetail 中没有找到,尝试通过中文字段名查找
+ if (is_array($configDetail)) {
+ foreach ($configDetail as $group) {
+ if (isset($group['items']) && is_array($group['items'])) {
+ foreach ($group['items'] as $item) {
+ // 检查中文字段名
+ if (isset($item['name']) && (strpos($item['name'], '内饰') !== false || strpos($item['name'], '座椅') !== false)) {
+ if (!empty($item['value']) && $item['value'] !== '–') {
+ return $item['value'];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 最后尝试从 baseInfo 中查找
+ foreach ($possibleKeys as $key) {
+ if (!empty($baseInfo[$key]) && $baseInfo[$key] !== '–') {
+ return $baseInfo[$key];
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * 将颜色翻译为英文
+ *
+ * @param string $color 颜色(可能是中文)
+ * @return string
+ */
+ private function translateColorToEnglish($color): string
+ {
+ if (empty($color)) {
+ return '';
+ }
+
+ $colorMap = [
+ '白色' => 'white',
+ '黑色' => 'black',
+ '红色' => 'red',
+ '蓝色' => 'blue',
+ '绿色' => 'green',
+ '黄色' => 'yellow',
+ '银色' => 'silver',
+ '灰色' => 'gray',
+ '灰色' => 'grey',
+ '棕色' => 'brown',
+ '金色' => 'gold',
+ '橙色' => 'orange',
+ '紫色' => 'purple',
+ '粉色' => 'pink',
+ '米色' => 'beige',
+ '浅色' => 'light-colored',
+ '深色' => 'dark-colored',
+ ];
+
+ $colorLower = mb_strtolower(trim($color), 'UTF-8');
+
+ // 如果已经是英文,直接返回(转小写)
+ if (preg_match('/^[a-z\s-]+$/i', $color)) {
+ return strtolower($color);
+ }
+
+ // 查找中文映射
+ foreach ($colorMap as $cn => $en) {
+ if (strpos($colorLower, $cn) !== false) {
+ return $en;
+ }
+ }
+
+ // 如果没有找到映射,尝试提取可能的英文部分,否则返回原值
+ if (preg_match('/[a-z]+/i', $color, $matches)) {
+ return strtolower($matches[0]);
+ }
+
+ return strtolower($color);
+ }
+
+ /**
+ * 构建 Vehicle Details 4列表格(2组 Key/Value)
+ *
+ * @param array $items [['label'=>'Ref ID','value'=>'xxx'], ...]
+ * @return string
+ */
+ public function buildVehicleDetailsTable(array $items): string
+ {
+ $html = '';
+
+ // 每行 2 个字段(4 列)
+ $chunks = array_chunk($items, 2,true );
+
+ foreach ($chunks as $row) {
+ $html .= '';
+ foreach ($row as $label => $value) {
+ $label = htmlspecialchars($label);
+ $value = htmlspecialchars((string)($value ?: '–'));
+
+ $html .= "| {$label} | {$value} | ";
+ }
+
+ // 如果是奇数,补空列
+ if (count($row) === 1) {
+ $html .= ' | | ';
+ }
+
+ $html .= '
';
+ }
+
+ $html .= '
';
+
+ return $html;
+ }
+
+ /**
+ * 上传 OSS 图片到 WordPress 媒体库
+ *
+ * @param string $domain
+ * @param string $imageUrl 阿里云 OSS 图片地址
+ * @return array
+ * @throws \Exception
+ */
+ public function uploadImageToWp(string $domain,$api_user, $api_secret, string $imageUrl = "fdesk_test/usedcar_crawl/20251125/ff847a6a2b3114b4c2c230455b74cd2e.jpg"): array
+ {
+ $imageUrl = (new OssService)->generatePrivateUrl($imageUrl);
+
+
+ $client = new Client();
+
+ $filename = basename(parse_url($imageUrl, PHP_URL_PATH));
+ $mediaUrl = $domain . '/wp-json/wp/v2/media';
+
+ try {
+ // 1. 拉取 OSS 图片内容
+ $imageContent = file_get_contents($imageUrl);
+ if ($imageContent === false) {
+ throw new \Exception('图片下载失败:' . $imageUrl);
+ }
+
+ // 2. 上传到 WP 媒体库
+ $response = $client->post($mediaUrl, [
+ RequestOptions::AUTH => [$api_user, $api_secret],
+ RequestOptions::HEADERS => [
+ 'Content-Disposition' => 'attachment; filename="' . $filename . '"',
+ 'Content-Type' => 'image/jpeg', // 如有 png/webp 可自行判断
+ ],
+ RequestOptions::BODY => $imageContent,
+ RequestOptions::VERIFY => false,
+ ]);
+
+ return json_decode($response->getBody()->getContents(), true);
+
+ } catch (\Exception $e) {
+ throw new \Exception('上传图片失败:' .$domain . $imageUrl . "?????". $e->getMessage());
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/common/validate/WordpressSiteValidate.php b/app/common/validate/WordpressSiteValidate.php
new file mode 100644
index 0000000..f0fe8e9
--- /dev/null
+++ b/app/common/validate/WordpressSiteValidate.php
@@ -0,0 +1,29 @@
+ [
+
+ ],
+
+ 'update' => [
+
+ ]
+ ];
+}
\ No newline at end of file
diff --git a/config/route.php b/config/route.php
index b9337f4..51b96f0 100644
--- a/config/route.php
+++ b/config/route.php
@@ -75,4 +75,18 @@ Route::group('/common', function () {
Route::any('/info', [app\common\controller\UserController::class, 'show']);
Route::any('/edit', [app\common\controller\UserController::class, 'edit']);
});
-});
\ No newline at end of file
+
+});
+
+Route::group('/admin', function () {
+ //仪表盘路由规则
+ Route::group('/wp', function () {
+ Route::any('/list', [app\admin\controller\WordpressSiteController::class, 'index']);
+ Route::any('/show', [app\admin\controller\WordpressSiteController::class, 'show']);
+ Route::any('/store', [app\admin\controller\WordpressSiteController::class, 'store']);
+ Route::any('/update', [app\admin\controller\WordpressSiteController::class, 'update']);
+ Route::any('/destroy', [app\admin\controller\WordpressSiteController::class, 'destroy']);
+ Route::any('/send', [app\admin\controller\WordpressSiteController::class, 'createProduct']);
+ });
+
+});