diff --git a/app/common/controller/UsedCarController.php b/app/common/controller/UsedCarController.php index 13fd88d..cca9728 100644 --- a/app/common/controller/UsedCarController.php +++ b/app/common/controller/UsedCarController.php @@ -6,9 +6,11 @@ use app\common\model\UsedCar; use app\common\model\UsedCarPdfLog; use app\common\model\User; use app\common\service\OssService; +use app\common\service\SparkService; use app\common\traits\crud\CrudControllerTrait; use app\common\service\UsedCarService; use app\common\utils\pdf\service\MpdfDriver; +use app\queue\utils\XunfeiFanyi; use support\exception\BusinessException; use support\Request; @@ -22,6 +24,19 @@ class UsedCarController extends BaseController protected $noNeedHeaderData = ['downloadPdf']; + protected $lang = [ + 'en' => '英语', + 'ru' => '俄语', + 'es' => '西班牙语', + 'ar' => '阿拉伯语', + ]; + protected $currency = [ + 'USD' => '$', + 'RUB' => '₽', + 'AED' => 'د.إ', + 'EUR' => '€', + ]; + public function __construct() { $this->service = new UsedCarService(); @@ -114,9 +129,17 @@ class UsedCarController extends BaseController public function producePdf(Request $request){ try { $price = $request->get('price'); + $lang = $request->get('lang'); + $currency = $request->get('currency'); if(empty($price)){ throw new BusinessException("请输入生成pdf中的价格"); } + if(empty($lang) || empty($this->lang[$lang])){ + throw new BusinessException("语种错误"); + } + if(empty($currency) || empty($this->currency[$currency])){ + throw new BusinessException("币种错误"); + } $raw = $this->service->serviceShow($request); $data = $this->transformData($raw, method_exists($this, 'showFormat') ? [$this, 'showFormat'] @@ -146,7 +169,12 @@ class UsedCarController extends BaseController $user['social_code'] = $ossService->generatePrivateUrl($user['social_code']); $user['social_code'] = $this->service->downloadImage($user['social_code']); } - $pdf = (new MpdfDriver())->exportUsedCarPdf($data,$user,$contact); + + $field = $this->field($lang);//字段相关外文 + $field['currency'] = $this->currency[$currency]; + $data = $this->fanyi($data, $lang);//车辆字段翻译外文 + $contactField = $this->contact($lang); //名片相关外文 + $pdf = (new MpdfDriver())->exportUsedCarPdf($field,$data,$user,$contactField,$contact); UsedCar::where('id', $data['id'])->update(['pdf_src' => $pdf]); array_map('unlink', glob(runtime_path('pdf/images/*.jpg'))); @@ -160,7 +188,7 @@ class UsedCarController extends BaseController ]); return $this->success($pdf); } catch (\Throwable $e) { - return $this->error($e->getMessage()); + return $this->error($e->getMessage().$e->getLine().$e->getFile()); } } @@ -178,6 +206,160 @@ class UsedCarController extends BaseController ); } + public function fanyi($data, $to){ + foreach ($data as $k => $v) { + if (in_array($k, ['product_name', 'source_place', 'body_color', 'condition_desc']) && !empty(trim($v))) { +// $xunfei = new XunfeiFanyi(); +// $data[$k] = $xunfei->fanyi($v, $from = 'cn', $to); + + $toLang = $this->lang[$to]; + $spark = new SparkService(); + $str = $spark->chat("将“{$v}”翻译为{$toLang},不要有多余的描述"); + $str = preg_replace('/[\x{4e00}-\x{9fa5}]/u', '', $str); + $data[$k] =str_replace(['(',')','(',')','"'], '', $str);; + } + } + return $data; + } + + /** + * 字段名 + * @param $data + * @param $to + * @return mixed + */ + public function field($to){ + $field = [ + 'cn' => [ + 'price' => '车价', + 'source_place' => '车源地', + 'plate_time' => '上牌时间', + 'displacement' => '排量', + 'mileage' => '里程', + 'power' => '马力', + 'body_color' => '车身颜色', + 'created_at' => '创建时间', + 'condition_desc' => '车况介绍', + 'images' => '产品图', + ], + + 'en' => [ + 'price' => 'Price', + 'source_place' => 'Vehicle Location', + 'plate_time' => 'Registration Date', + 'displacement' => 'Engine Displacement', + 'mileage' => 'Mileage', + 'power' => 'Horsepower', + 'body_color' => 'Body Color', + 'created_at' => 'Created At', + 'condition_desc' => 'Vehicle Condition', + 'images' => 'Images', + ], + + 'ru' => [ + 'price' => 'Цена', + 'source_place' => 'Местонахождение автомобиля', + 'plate_time' => 'Дата регистрации', + 'displacement' => 'Объём двигателя', + 'mileage' => 'Пробег', + 'power' => 'Мощность', + 'body_color' => 'Цвет кузова', + 'created_at' => 'Дата создания', + 'condition_desc' => 'Состояние автомобиля', + 'images' => 'Фотографии', + ], + + 'es' => [ + 'price' => 'Precio', + 'source_place' => 'Ubicación del vehículo', + 'plate_time' => 'Fecha de matriculación', + 'displacement' => 'Cilindrada', + 'mileage' => 'Kilometraje', + 'power' => 'Potencia', + 'body_color' => 'Color de la carrocería', + 'created_at' => 'Fecha de creación', + 'condition_desc' => 'Estado del vehículo', + 'images' => 'Imágenes', + ], + + 'ar' => [ + 'price' => 'السعر', + 'source_place' => 'موقع السيارة', + 'plate_time' => 'تاريخ التسجيل', + 'displacement' => 'سعة المحرك', + 'mileage' => 'المسافة المقطوعة', + 'power' => 'قوة المحرك', + 'body_color' => 'لون الهيكل', + 'created_at' => 'تاريخ الإنشاء', + 'condition_desc' => 'حالة السيارة', + 'images' => 'صور المنتج', + ], + ]; + return $field[$to]; +// foreach ($field as $k => $v) { +//// $xunfei = new XunfeiFanyi(); +//// $field[$k] = $xunfei->fanyi($v, $from = 'cn', $to); +// $toLang = $this->lang[$to]; +// $spark = new SparkService(); +// $field[$k] = $spark->chat("“{$v}”翻译为{$toLang},不要有多余的描述"); +// } +// return $field; + } + + /** + * 名片外文 + */ + public function contact($to){ + $contactField = [ + 'cn' => [ + 'title' => '联系人名片', + 'name' => '姓名', + 'email' => '邮箱', + 'phone' => '电话', + 'WhatsApp' => 'WhatsApp', + 'code' => '二维码', + ], + + 'en' => [ + 'title' => 'Contact Name Card', + 'name' => 'Name', + 'email' => 'Email', + 'phone' => 'Phone', + 'WhatsApp' => 'WhatsApp', + 'code' => 'QR Code', + ], + + 'ru' => [ + 'title' => 'Контактная карточка', + 'name' => 'Имя', + 'email' => 'Электронная почта', + 'phone' => 'Телефон', + 'WhatsApp' => 'WhatsApp', + 'code' => 'QR-код', + ], + + 'es' => [ + 'title' => 'Tarjeta de visita de contacto', + 'name' => 'Nombre', + 'email' => 'Correo electrónico', + 'phone' => 'Teléfono', + 'WhatsApp' => 'WhatsApp', + 'code' => 'Código QR', + ], + + 'ar' => [ + 'title' => 'بطاقة الاتصال', + 'name' => 'الاسم', + 'email' => 'البريد الإلكتروني', + 'phone' => 'الهاتف', + 'WhatsApp' => 'واتساب', + 'code' => 'رمز QR', + ], + ]; + + return $contactField[$to]; + } + public function getPdf(Request $request) { try { diff --git a/app/common/service/SparkService.php b/app/common/service/SparkService.php new file mode 100644 index 0000000..171eae5 --- /dev/null +++ b/app/common/service/SparkService.php @@ -0,0 +1,82 @@ +apiPassword = $config['api_password']; + $this->model = $config['model']; + + // 使用 Guzzle 客户端,base_uri 指向 Spark API + $this->client = new Client([ + 'base_uri' => $config['base_uri'], + 'timeout' => 30, + 'verify' => false, + ]); + } + + /** + * 发送聊天请求 + * + * @param string $message 用户输入文本 + * @param string|null $userId 可选的用户唯一 ID + * @param array $options 其他可选参数(temperature 等) + * @return 返回 API 解析后的结果 + */ + public function chat(string $message, ?string $userId = null, array $options = [],string $file = 'spark') + { + $payload = array_merge([ + 'model' => $this->model, + 'messages' => [ + [ + 'role' => 'user', + 'content' => $message, + ] + ], + // 可根据需要设置 + 'temperature' => 1.0, + 'top_k' => 4, + ], $options); + + if ($userId !== null) { + $payload['user'] = $userId; + } + + try { + $response = $this->client->post('chat/completions', [ + 'headers' => [ + 'Content-Type' => 'application/json', + 'Authorization' => "Bearer {$this->apiPassword}", + ], + 'json' => $payload, + ]); + + $body = (string) $response->getBody(); + $result = json_decode($body, true); + if($result['code'] != 0){ + flg('spark chat:'.$body,false,$file); + } + return $result['choices'][0]['message']['content']; + } catch (RequestException $e) { + // 错误处理 + $message = $e->getMessage(); + if ($e->hasResponse()) { + $message .= ' ' . $e->getResponse()->getBody(); + } + // log 或抛出异常都可以 + error_log("[SparkService] Chat Error: {$message}"); + return null; + } + } +} \ No newline at end of file diff --git a/app/common/utils/XunfeiFanyi.php b/app/common/utils/XunfeiFanyi.php new file mode 100644 index 0000000..0b06ec2 --- /dev/null +++ b/app/common/utils/XunfeiFanyi.php @@ -0,0 +1,138 @@ + $header,'body' => $response); + return $data; + } + + + public function xfyun($text = "中华人民共和国于1949年成立", $from = "cn", $to = "en") + { + //在控制台-我的应用-机器翻译获取 + $app_id = "3d46198c"; + //在控制台-我的应用-机器翻译获取 + $api_sec = "ZWY2MmUyNjJjYmFkOTFlYTVmYWVhMGYy"; + //在控制台-我的应用-机器翻译获取 + $api_key = "b6d805f240176ecaea85130cb5f2bca1"; + // 机器翻译接口地址 + $url = "https://ntrans.xfyun.cn/v2/ots"; + //body组装 + // $text = "中华人民共和国于1949年成立";//待翻译文本 + $body = json_encode($this->getBody($app_id, $from, $to, $text)); + + // 组装http请求头 + $date =gmdate('D, d M Y H:i:s') . ' GMT'; + + $digestBase64 = "SHA-256=".base64_encode(hash("sha256", $body, true)); + $builder = sprintf("host: %s +date: %s +POST /v2/ots HTTP/1.1 +digest: %s", "ntrans.xfyun.cn", $date, $digestBase64); + // echo($builder); + $sha = base64_encode(hash_hmac("sha256", $builder, $api_sec, true)); + + $authorization = sprintf("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", $api_key,"hmac-sha256", + "host date request-line digest", $sha); + + $header = [ + "Authorization: ".$authorization, + 'Content-Type: application/json', + 'Accept: application/json,version=1.0', + 'Host: ntrans.xfyun.cn', + 'Date: ' .$date, + 'Digest: '.$digestBase64 + ]; + $response = $this->tocurl($url, $header, $body); + + // var_dump($response['body']); + return $response; + } + + + public function getBody($app_id, $from, $to, $text) + { + $common_param = [ + 'app_id' => $app_id + ]; + + $business = [ + 'from' => $from, + 'to' => $to, + ]; + + $data = [ + "text" => base64_encode($text) + ]; + + return $body = [ + 'common' => $common_param, + 'business' => $business, + 'data' => $data + ]; + } + + // 翻译 + public function fanyi($text = "", $from = "", $to = "") + { + try { + $res = $this->xfyun($text, $from, $to); + $data = json_decode($res["body"], true); + if ($data["code"] === 0) { + return $data["data"]["result"]; + } else { + $this->error = $data["message"]; + Log::error("XunfeiFanyi 失败: ".$data["message"],[$data]); + return false; + } + } catch (\Throwable $th) { + $this->error = $th->getMessage(); + Log::error("XunfeiFanyi 错误: ".$th->getMessage()); + return false; + } + } + + // 异常 + public function error() + { + return $this->error; + } + +} \ No newline at end of file diff --git a/app/common/utils/pdf/service/MpdfDriver.php b/app/common/utils/pdf/service/MpdfDriver.php index 436cb34..08981d7 100644 --- a/app/common/utils/pdf/service/MpdfDriver.php +++ b/app/common/utils/pdf/service/MpdfDriver.php @@ -116,7 +116,7 @@ class MpdfDriver return [$css, $html]; } - public function exportUsedCarPdf($car,$user,$contact) + public function exportUsedCarPdf($field,$car,$user,$contactField,$contact) { /*$car = [ 'title' => '奥迪Q3 2013款 35 TFSI 舒适型', @@ -157,7 +157,7 @@ class MpdfDriver $mpdf->SetProtection(//限制篡改或盗用 ['print'], // 允许的权限 copy:允许复制、print:允许打印 '', // 用户密码(可留空) - 'Admin@2026@!#' // 拥有者密码(一定要设置) + $car['code'] // 拥有者密码(一定要设置) ); //设置水印 diff --git a/app/common/utils/pdf/template/contactCard.stub b/app/common/utils/pdf/template/contactCard.stub index 5b8c4f4..493f73f 100644 --- a/app/common/utils/pdf/template/contactCard.stub +++ b/app/common/utils/pdf/template/contactCard.stub @@ -52,17 +52,17 @@
-| 车价 | -¥ = number_format($car['price'], 2) ?> | += $field['price'] ?> | += $field['currency'].' ' ?>= number_format($car['price'], 2) ?> |
| 车源地 | += $field['source_place'] ?> | = $car['source_place'] ?> | |
| 上牌时间 | += $field['plate_time'] ?> | = $car['plate_time'] ?> | |
| 排量 | += $field['displacement'] ?> | = $car['displacement'] ?> | |
| 里程 | += $field['mileage'] ?> | = $car['mileage'].'km' ?> | |
| 马力 | += $field['power'] ?> | = $car['power'] ?> | |
| 车身颜色 | += $field['body_color'] ?> | = $car['body_color'] ?: '-' ?> | |
| 创建时间 | += $field['created_at'] ?> | = $car['created_at'] ?> |
|
+
+ = $field['images'] ?>
+
+ |
+ |
|---|---|
|
|
-
- |