Browse Source

Merge pull request #2291 from visuddhinanda/development

Development
visuddhinanda 11 months ago
parent
commit
1ab0103041

+ 56 - 0
api-v8/app/Console/Commands/CreateMyHanCrop.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+
+class CreateMyHanCrop extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'command:name';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $csvFile = config("mint.path.dict_text") . '/zh/my-han/index.csv';
+        if (($fp = fopen($csvFile, "r")) !== false) {
+            $row = 0;
+            $page = 0;
+            while (($data = fgetcsv($fp, 0, ',')) !== false) {
+                if ($row === 0) {
+                    continue;
+                }
+                $page = $data[1];
+                $word = $data[2];
+                $row++;
+            }
+            fclose($fp);
+        }
+        return 0;
+    }
+}

+ 51 - 31
api-v8/app/Console/Commands/MqAiTranslate.php

@@ -6,13 +6,8 @@ use Illuminate\Console\Command;
 use App\Http\Api\Mq;
 use App\Http\Api\Mq;
 use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Http;
-use Illuminate\Support\Str;
 use Illuminate\Http\Client\RequestException;
 use Illuminate\Http\Client\RequestException;
 
 
-use App\Http\Controllers\AuthController;
-use App\Models\Sentence;
-use App\Models\ModelLog;
-
 class MqAiTranslate extends Command
 class MqAiTranslate extends Command
 {
 {
     /**
     /**
@@ -63,7 +58,7 @@ class MqAiTranslate extends Command
             //获取model token
             //获取model token
             $first = $messages[0];
             $first = $messages[0];
             Log::debug($queue . ' ai assistant token', ['user' => $first->model->uid]);
             Log::debug($queue . ' ai assistant token', ['user' => $first->model->uid]);
-            $modelToken = AuthController::getUserToken($first->model->uid);
+            $modelToken = $first->model->token;
             Log::debug($queue . ' ai assistant token', ['token' => $modelToken]);
             Log::debug($queue . ' ai assistant token', ['token' => $modelToken]);
 
 
             $this->setTaskStatus($first->task->info->id, 'running', $modelToken);
             $this->setTaskStatus($first->task->info->id, 'running', $modelToken);
@@ -90,9 +85,7 @@ class MqAiTranslate extends Command
 
 
             foreach ($messages as $key => $message) {
             foreach ($messages as $key => $message) {
                 $taskDiscussionContent = [];
                 $taskDiscussionContent = [];
-                //写入 model log
-                $modelLog = new ModelLog();
-                $modelLog->uid = Str::uuid();
+
 
 
                 $param = [
                 $param = [
                     "model" => $message->model->model,
                     "model" => $message->model->model,
@@ -109,9 +102,14 @@ class MqAiTranslate extends Command
                     'url' => $message->model->url,
                     'url' => $message->model->url,
                     'data' => $param
                     'data' => $param
                 ]);
                 ]);
-                $modelLog->model_id = $message->model->uid;
-                $modelLog->request_at = now();
-                $modelLog->request_data = json_encode($param, JSON_UNESCAPED_UNICODE);
+
+                //写入 model log
+                $modelLogData = [
+                    'model_id' => $message->model->uid,
+                    'request_at' => now(),
+                    'request_data' => json_encode($param, JSON_UNESCAPED_UNICODE),
+                ];
+
                 try {
                 try {
                     $response = Http::withToken($message->model->key)
                     $response = Http::withToken($message->model->key)
                         ->timeout(300)
                         ->timeout(300)
@@ -120,10 +118,12 @@ class MqAiTranslate extends Command
                     $response->throw(); // 触发异常(如果请求失败)
                     $response->throw(); // 触发异常(如果请求失败)
                     $taskDiscussionContent[] = '- LLM request successful';
                     $taskDiscussionContent[] = '- LLM request successful';
                     Log::info($queue . ' LLM request successful');
                     Log::info($queue . ' LLM request successful');
-                    $modelLog->request_headers = json_encode($response->handlerStats(), JSON_UNESCAPED_UNICODE);
-                    $modelLog->response_headers = json_encode($response->headers(), JSON_UNESCAPED_UNICODE);
-                    $modelLog->status = $response->status();
-                    $modelLog->response_data = json_encode($response->json(), JSON_UNESCAPED_UNICODE);
+
+                    $modelLogData['request_headers'] = json_encode($response->handlerStats(), JSON_UNESCAPED_UNICODE);
+                    $modelLogData['response_headers'] = json_encode($response->headers(), JSON_UNESCAPED_UNICODE);
+                    $modelLogData['status'] = $response->status();
+                    $modelLogData['response_data'] = json_encode($response->json(), JSON_UNESCAPED_UNICODE);
+                    self::saveModelLog($modelToken, $modelLogData);
                     /*
                     /*
                 if ($response->failed()) {
                 if ($response->failed()) {
                     $modelLog->success = false;
                     $modelLog->success = false;
@@ -134,18 +134,17 @@ class MqAiTranslate extends Command
                 } catch (RequestException $e) {
                 } catch (RequestException $e) {
                     Log::error($queue . ' LLM request exception: ' . $e->getMessage());
                     Log::error($queue . ' LLM request exception: ' . $e->getMessage());
                     $failResponse = $e->response;
                     $failResponse = $e->response;
-                    $modelLog->request_headers = json_encode($failResponse->handlerStats(), JSON_UNESCAPED_UNICODE);
-                    $modelLog->response_headers = json_encode($failResponse->headers(), JSON_UNESCAPED_UNICODE);
-                    $modelLog->status = $failResponse->status();
-                    $modelLog->response_data = $response->body();
-                    $modelLog->success = false;
-                    $modelLog->save();
+
+                    $modelLogData['request_headers'] = json_encode($failResponse->handlerStats(), JSON_UNESCAPED_UNICODE);
+                    $modelLogData['response_headers'] = json_encode($failResponse->headers(), JSON_UNESCAPED_UNICODE);
+                    $modelLogData['status'] = $failResponse->status();
+                    $modelLogData['response_data'] = $response->body();
+                    $modelLogData['success'] = false;
+                    self::saveModelLog($modelToken, $modelLogData);
                     continue;
                     continue;
                 }
                 }
-
-
-                $modelLog->save();
                 Log::info($queue . ' model log saved');
                 Log::info($queue . ' model log saved');
+
                 $aiData = $response->json();
                 $aiData = $response->json();
                 Log::debug($queue . ' LLM http response', ['data' => $response->json()]);
                 Log::debug($queue . ' LLM http response', ['data' => $response->json()]);
                 $responseContent = $aiData['choices'][0]['message']['content'];
                 $responseContent = $aiData['choices'][0]['message']['content'];
@@ -217,12 +216,21 @@ class MqAiTranslate extends Command
 
 
                 //写入discussion
                 //写入discussion
                 #获取句子id
                 #获取句子id
-                $sUid = Sentence::where('book_id', $message->sentence->book_id)
-                    ->where('paragraph', $message->sentence->paragraph)
-                    ->where('word_start', $message->sentence->word_start)
-                    ->where('word_end', $message->sentence->word_end)
-                    ->where('channel_uid', $message->sentence->channel_uid)
-                    ->value('uid');
+                $url = config('app.url') . '/api/v2/sentence-info/aa';
+                Log::info('ai translate', ['url' => $url]);
+                $response = Http::timeout(10)->withToken($modelToken)->get($url, [
+                    'book' => $message->sentence->book_id,
+                    'par' => $message->sentence->paragraph,
+                    'start' => $message->sentence->word_start,
+                    'end' => $message->sentence->word_end,
+                    'channel' => $message->sentence->channel_uid
+                ]);
+                if ($response->json()['ok']) {
+                    $sUid = $response->json()['data']['id'];
+                } else {
+                    Log::error($queue . ' sentence id error', ['data' => $response->json()]);
+                    return 1;
+                }
                 $url = config('app.url') . '/api/v2/discussion';
                 $url = config('app.url') . '/api/v2/discussion';
                 $data = [
                 $data = [
                     'res_id' => $sUid,
                     'res_id' => $sUid,
@@ -326,4 +334,16 @@ class MqAiTranslate extends Command
             Log::info('ai_translate task status done');
             Log::info('ai_translate task status done');
         }
         }
     }
     }
+
+    private function saveModelLog($token, $data)
+    {
+        $url = config('app.url') . '/api/v2/model-log';
+
+        $response = Http::timeout(10)->withToken($token)->post($url, $data);
+        if ($response->failed()) {
+            Log::error('ai-translate model log create failed', ['data' => $response->json()]);
+            return false;
+        }
+        return true;
+    }
 }
 }

+ 158 - 158
api-v8/app/Console/Commands/UpgradeDict.php

@@ -26,8 +26,8 @@ class UpgradeDict extends Command
      */
      */
     protected $description = '导入csv字典';
     protected $description = '导入csv字典';
 
 
-	protected $dictInfo;
-	protected $cols;
+    protected $dictInfo;
+    protected $cols;
 
 
     /**
     /**
      * Create a new command instance.
      * Create a new command instance.
@@ -39,175 +39,175 @@ class UpgradeDict extends Command
         parent::__construct();
         parent::__construct();
     }
     }
 
 
-	private function scandict($dir){
-		if(is_dir($dir)){
-			$this->info("scan:".$dir);
-			if($files = scandir($dir)){
-				//进入目录搜索字典或子目录
-				foreach ($files as $file) {
-					//进入语言目录循环搜索
-					$fullPath = $dir."/".$file;
-					if(is_dir($fullPath) && $file !== '.' && $file !== '..'){
-						//是目录继续搜索
-						$this->scandict($fullPath);
-					}else{
-						//是文件,查看是否是字典信息文件
-						$infoFile = $fullPath;
-						if(pathinfo($infoFile,PATHINFO_EXTENSION) === 'ini'){
-							$this->dictInfo = parse_ini_file($infoFile,true);
-							if(isset($this->dictInfo['meta']['dictname'])){
-								//是字典信息文件
-								$this->info($this->dictInfo['meta']['dictname']);
-								if(Str::isUuid($this->argument('uuid'))){
-									if($this->argument('uuid') !== $this->dictInfo['meta']['uuid']){
-										continue;
-									}
-								}
-								if(!Str::isUuid($this->dictInfo['meta']['uuid'])){
-									$this->error("not uuid");
-									continue;
-								}
+    private function scandict($dir)
+    {
+        if (is_dir($dir)) {
+            $this->info("scan:" . $dir);
+            if ($files = scandir($dir)) {
+                //进入目录搜索字典或子目录
+                foreach ($files as $file) {
+                    //进入语言目录循环搜索
+                    $fullPath = $dir . "/" . $file;
+                    if (is_dir($fullPath) && $file !== '.' && $file !== '..') {
+                        //是目录继续搜索
+                        $this->scandict($fullPath);
+                    } else {
+                        //是文件,查看是否是字典信息文件
+                        $infoFile = $fullPath;
+                        if (pathinfo($infoFile, PATHINFO_EXTENSION) === 'ini') {
+                            $this->dictInfo = parse_ini_file($infoFile, true);
+                            if (isset($this->dictInfo['meta']['dictname'])) {
+                                //是字典信息文件
+                                $this->info($this->dictInfo['meta']['dictname']);
+                                if (Str::isUuid($this->argument('uuid'))) {
+                                    if ($this->argument('uuid') !== $this->dictInfo['meta']['uuid']) {
+                                        continue;
+                                    }
+                                }
+                                if (!Str::isUuid($this->dictInfo['meta']['uuid'])) {
+                                    $this->error("not uuid");
+                                    continue;
+                                }
                                 //读取 description
                                 //读取 description
-                                $desFile = $dir."/description.md";
-                                if(file_exists($desFile)){
+                                $desFile = $dir . "/description.md";
+                                if (file_exists($desFile)) {
                                     $description = file_get_contents($desFile);
                                     $description = file_get_contents($desFile);
-                                }else{
+                                } else {
                                     $description = $this->dictInfo['meta']['description'];
                                     $description = $this->dictInfo['meta']['description'];
                                 }
                                 }
-								$tableDict = DictInfo::firstOrNew([
-									"id" => $this->dictInfo['meta']['uuid']
-								]);
-								$tableDict->id = $this->dictInfo['meta']['uuid'];
-								$tableDict->name = $this->dictInfo['meta']['dictname'];
-								$tableDict->shortname = $this->dictInfo['meta']['shortname'];
-								$tableDict->description = $description;
-								$tableDict->src_lang = $this->dictInfo['meta']['src_lang'];
-								$tableDict->dest_lang = $this->dictInfo['meta']['dest_lang'];
-								$tableDict->rows = $this->dictInfo['meta']['rows'];
-								$tableDict->owner_id = config("mint.admin.root_uuid");
-								$tableDict->meta = json_encode($this->dictInfo['meta']);
-								$tableDict->save();
+                                $tableDict = DictInfo::firstOrNew([
+                                    "id" => $this->dictInfo['meta']['uuid']
+                                ]);
+                                $tableDict->id = $this->dictInfo['meta']['uuid'];
+                                $tableDict->name = $this->dictInfo['meta']['dictname'];
+                                $tableDict->shortname = $this->dictInfo['meta']['shortname'];
+                                $tableDict->description = $description;
+                                $tableDict->src_lang = $this->dictInfo['meta']['src_lang'];
+                                $tableDict->dest_lang = $this->dictInfo['meta']['dest_lang'];
+                                $tableDict->rows = $this->dictInfo['meta']['rows'];
+                                $tableDict->owner_id = config("mint.admin.root_uuid");
+                                $tableDict->meta = json_encode($this->dictInfo['meta']);
+                                $tableDict->save();
 
 
-								if($this->option('part')){
-									$this->info(" dict id = ".$this->dictInfo['meta']['uuid']);
-								}else{
-									$del = UserDict::where("dict_id",$this->dictInfo['meta']['uuid'])->delete();
-									$this->info("delete {$del} rows dict id = ".$this->dictInfo['meta']['uuid']);
-								}
+                                if ($this->option('part')) {
+                                    $this->info(" dict id = " . $this->dictInfo['meta']['uuid']);
+                                } else {
+                                    $del = UserDict::where("dict_id", $this->dictInfo['meta']['uuid'])->delete();
+                                    $this->info("delete {$del} rows dict id = " . $this->dictInfo['meta']['uuid']);
+                                }
                                 /**
                                 /**
                                  * 允许一个字典拆成若干个小文件
                                  * 允许一个字典拆成若干个小文件
                                  * 文件名 为 ***.csv , ***-1.csv , ***-2.csv
                                  * 文件名 为 ***.csv , ***-1.csv , ***-2.csv
                                  *
                                  *
                                  */
                                  */
-								$filename = $dir.'/'.pathinfo($infoFile,PATHINFO_FILENAME);
-								$csvFile = $filename . ".csv";
-								$count = 0;
-								$bar = $this->output->createProgressBar($this->dictInfo['meta']['rows']);
-								while (file_exists($csvFile)) {
-									# code...
-									$this->info("runing:{$csvFile}");
-									$inputRow = 0;
-									if (($fp = fopen($csvFile, "r")) !== false) {
-										$this->cols = array();
-										while (($data = fgetcsv($fp, 0, ',')) !== false) {
-											if ($inputRow == 0) {
-												foreach ($data as $key => $colname) {
-													# 列名列表
-													$this->cols[$colname] = $key;
-												}
-											}else{
-												if($this->option('part')){
-													//仅仅提取拆分零件
-													$word = $this->get($data,'word');
-													$factor1 = $this->get($data,'factors');
-													$factor1 = \str_replace([' ','(',')','=','-','$'],"+",$factor1);
-													foreach (\explode('+',$factor1)  as $part) {
-														# code...
-														if(empty($part)){
-															continue;
-														}
-														if(isset($newPart[$part])){
-															$newPart[$part][0]++;
-														}else{
-															$partExists = Cache::remember('dict/part/'.$part,config('cache.expire',1000),function() use($part){
-																return UserDict::where('word',$part)->exists();
-															});
-															if(!$partExists){
-															$count++;
-															$newPart[$part] = [1,$word];
-															$this->info("{$count}:{$part}-{$word}");
-															}
-														}
-
-													}
-												}else{
-													$newDict = new UserDict();
-													$newDict->id = app('snowflake')->id();
-													$newDict->word = $data[$this->cols['word']];
-													$newDict->type = $this->get($data,'type');
-													$newDict->grammar = $this->get($data,'grammar');
-													$newDict->parent = $this->get($data,'parent');
-													$newDict->mean = $this->get($data,'mean');
-													$newDict->note = $this->get($data,'note');
-													$newDict->factors = $this->get($data,'factors');
-													$newDict->factormean = $this->get($data,'factormean');
-													$newDict->status = $this->get($data,'status');
-													$newDict->language = $this->get($data,'language');
-													$newDict->confidence = $this->get($data,'confidence');
-													$newDict->source = $this->get($data,'source');
-													$newDict->create_time =(int)(microtime(true)*1000);
-													$newDict->creator_id = 1;
-													$newDict->dict_id = $this->dictInfo['meta']['uuid'];
-													$newDict->save();
-												}
+                                $filename = $dir . '/' . pathinfo($infoFile, PATHINFO_FILENAME);
+                                $csvFile = $filename . ".csv";
+                                $count = 0;
+                                $bar = $this->output->createProgressBar($this->dictInfo['meta']['rows']);
+                                while (file_exists($csvFile)) {
+                                    # code...
+                                    $this->info("runing:{$csvFile}");
+                                    $inputRow = 0;
+                                    if (($fp = fopen($csvFile, "r")) !== false) {
+                                        $this->cols = array();
+                                        while (($data = fgetcsv($fp, 0, ',')) !== false) {
+                                            if ($inputRow == 0) {
+                                                foreach ($data as $key => $colname) {
+                                                    # 列名列表
+                                                    $this->cols[$colname] = $key;
+                                                }
+                                            } else {
+                                                if ($this->option('part')) {
+                                                    //仅仅提取拆分零件
+                                                    $word = $this->get($data, 'word');
+                                                    $factor1 = $this->get($data, 'factors');
+                                                    $factor1 = \str_replace([' ', '(', ')', '=', '-', '$'], "+", $factor1);
+                                                    foreach (\explode('+', $factor1)  as $part) {
+                                                        # code...
+                                                        if (empty($part)) {
+                                                            continue;
+                                                        }
+                                                        if (isset($newPart[$part])) {
+                                                            $newPart[$part][0]++;
+                                                        } else {
+                                                            $partExists = Cache::remember('dict/part/' . $part, config('cache.expire', 1000), function () use ($part) {
+                                                                return UserDict::where('word', $part)->exists();
+                                                            });
+                                                            if (!$partExists) {
+                                                                $count++;
+                                                                $newPart[$part] = [1, $word];
+                                                                $this->info("{$count}:{$part}-{$word}");
+                                                            }
+                                                        }
+                                                    }
+                                                } else {
+                                                    $newDict = new UserDict();
+                                                    $newDict->id = app('snowflake')->id();
+                                                    $newDict->word = $data[$this->cols['word']];
+                                                    $newDict->type = $this->get($data, 'type');
+                                                    $newDict->grammar = $this->get($data, 'grammar');
+                                                    $newDict->parent = $this->get($data, 'parent');
+                                                    $newDict->mean = $this->get($data, 'mean');
+                                                    $newDict->note = $this->get($data, 'note');
+                                                    $newDict->factors = $this->get($data, 'factors');
+                                                    $newDict->factormean = $this->get($data, 'factormean');
+                                                    $newDict->status = $this->get($data, 'status');
+                                                    $newDict->language = $this->get($data, 'language');
+                                                    $newDict->confidence = $this->get($data, 'confidence');
+                                                    $newDict->source = $this->get($data, 'source');
+                                                    $newDict->create_time = (int)(microtime(true) * 1000);
+                                                    $newDict->creator_id = 0;
+                                                    $newDict->dict_id = $this->dictInfo['meta']['uuid'];
+                                                    $newDict->save();
+                                                }
 
 
-												$bar->advance();
-											}
-											$inputRow++;
-										}
-									}
-									$count++;
-									$csvFile = $filename . "-{$count}.csv";
-								}
-								$bar->finish();
-								Storage::disk('local')->put("tmp/pm-part.csv", "part,count,word");
-                                if(isset($newPart)){
+                                                $bar->advance();
+                                            }
+                                            $inputRow++;
+                                        }
+                                    }
+                                    $count++;
+                                    $csvFile = $filename . "-{$count}.csv";
+                                }
+                                $bar->finish();
+                                Storage::disk('local')->put("tmp/pm-part.csv", "part,count,word");
+                                if (isset($newPart)) {
                                     foreach ($newPart as $part => $info) {
                                     foreach ($newPart as $part => $info) {
                                         # 写入磁盘文件
                                         # 写入磁盘文件
                                         Storage::disk('local')->append("tmp/pm-part.csv", "{$part},{$info[0]},{$info[1]}");
                                         Storage::disk('local')->append("tmp/pm-part.csv", "{$part},{$info[0]},{$info[1]}");
                                     }
                                     }
                                 }
                                 }
-								$this->info("done");
-							}
-
-						}
-					}
-				}
-				//子目录搜素完毕
-				return;
-			}else{
-				//获取子目录失败
-				$this->error("scandir fail");
-				return;
-			}
-		}else{
-			$this->error("this is not dir input={$dir}");
-			return;
-		}
-	}
+                                $this->info("done");
+                            }
+                        }
+                    }
+                }
+                //子目录搜素完毕
+                return;
+            } else {
+                //获取子目录失败
+                $this->error("scandir fail");
+                return;
+            }
+        } else {
+            $this->error("this is not dir input={$dir}");
+            return;
+        }
+    }
 
 
-	/**
-	 * 获取列的值
-	 */
-	protected function get($data,$colname,$defualt=""){
-		if(isset($this->cols[$colname])){
-			return $data[$this->cols[$colname]];
-		}else if(isset($this->dictInfo['cols'][$colname])){
-			return $this->dictInfo['cols'][$colname];
-		}else{
-			return $defualt;
-		}
-	}
+    /**
+     * 获取列的值
+     */
+    protected function get($data, $colname, $defualt = "")
+    {
+        if (isset($this->cols[$colname])) {
+            return $data[$this->cols[$colname]];
+        } else if (isset($this->dictInfo['cols'][$colname])) {
+            return $this->dictInfo['cols'][$colname];
+        } else {
+            return $defualt;
+        }
+    }
     /**
     /**
      * Execute the console command.
      * Execute the console command.
      *
      *
@@ -215,12 +215,12 @@ class UpgradeDict extends Command
      */
      */
     public function handle()
     public function handle()
     {
     {
-        if(\App\Tools\Tools::isStop()){
+        if (\App\Tools\Tools::isStop()) {
             return 0;
             return 0;
         }
         }
-		$this->info("upgrade dict start");
-		$this->scandict(config("mint.path.dict_text"));
-		$this->info("upgrade dict done");
+        $this->info("upgrade dict start");
+        $this->scandict(config("mint.path.dict_text"));
+        $this->info("upgrade dict done");
 
 
         return 0;
         return 0;
     }
     }

+ 13 - 1
api-v8/app/Http/Api/AiAssistantApi.php

@@ -43,7 +43,19 @@ class AiAssistantApi
                 $data['avatar'] = Storage::temporaryUrl($img, now()->addDays(6));
                 $data['avatar'] = Storage::temporaryUrl($img, now()->addDays(6));
             }
             }
         } else {
         } else {
-            $data['avatar'] = config('app.url') . '/assets/images/avatar/ai-assistant.png';
+            $logo = null;
+            foreach (config('mint.ai.logo') as $key => $value) {
+                if (strpos($user->model, $key) !== false) {
+                    $logo = $value;
+                    break;
+                }
+            }
+            $base = config('app.url') . '/assets/images/avatar/';
+            if ($logo === null) {
+                $data['avatar'] = $base . 'ai-assistant.png';
+            } else {
+                $data['avatar'] = $base . $logo;
+            }
         }
         }
         return $data;
         return $data;
     }
     }

+ 3 - 0
api-v8/app/Http/Api/AiTaskPrepare.php

@@ -12,6 +12,7 @@ use App\Http\Api\Mq;
 use App\Http\Api\ChannelApi;
 use App\Http\Api\ChannelApi;
 
 
 use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Log;
+use App\Http\Controllers\AuthController;
 
 
 class AiTaskPrepare
 class AiTaskPrepare
 {
 {
@@ -113,6 +114,8 @@ class AiTaskPrepare
 
 
         # ai model
         # ai model
         $aiModel = AiModel::findOrFail($task->executor_id);
         $aiModel = AiModel::findOrFail($task->executor_id);
+        $modelToken = AuthController::getUserToken($aiModel->uid);
+        $aiModel['token'] = $modelToken;
         $sumLen = 0;
         $sumLen = 0;
         $mqData = [];
         $mqData = [];
         foreach ($sentences as $key => $sentence) {
         foreach ($sentences as $key => $sentence) {

+ 13 - 0
api-v8/app/Http/Controllers/ModelLogController.php

@@ -6,6 +6,7 @@ use App\Models\ModelLog;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use App\Http\Api\AuthApi;
 use App\Http\Api\AuthApi;
 use App\Http\Resources\ModelLogResource;
 use App\Http\Resources\ModelLogResource;
+use Illuminate\Support\Str;
 
 
 class ModelLogController extends Controller
 class ModelLogController extends Controller
 {
 {
@@ -56,6 +57,18 @@ class ModelLogController extends Controller
     public function store(Request $request)
     public function store(Request $request)
     {
     {
         //
         //
+        $modelLog = new ModelLog();
+        $modelLog->uid = Str::uuid();
+        $modelLog->model_id = $request->get('model_id');
+        $modelLog->request_at = $request->get('request_at');
+        $modelLog->request_headers = $request->get('request_headers');
+        $modelLog->request_data = $request->get('request_data');
+        $modelLog->response_headers = $request->get('response_headers');
+        $modelLog->response_data = $request->get('response_data');
+        $modelLog->status = $request->get('status');
+        $modelLog->success = $request->get('success', true);
+        $modelLog->save();
+        return $this->ok(new ModelLogResource($modelLog));
     }
     }
 
 
     /**
     /**

+ 129 - 145
api-v8/app/Http/Controllers/SentenceInfoController.php

@@ -7,9 +7,8 @@ use App\Models\PaliSentence;
 use App\Models\PaliText;
 use App\Models\PaliText;
 
 
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Cache;
+use App\Http\Resources\SentResource;
 use App\Tools\RedisClusters;
 use App\Tools\RedisClusters;
-use Illuminate\Support\Facades\DB;
 
 
 class SentenceInfoController extends Controller
 class SentenceInfoController extends Controller
 {
 {
@@ -20,20 +19,7 @@ class SentenceInfoController extends Controller
      *
      *
      * @return \Illuminate\Http\Response
      * @return \Illuminate\Http\Response
      */
      */
-    public function index()
-    {
-        //
-    }
-
-    /**
-     * Show the form for creating a new resource.
-     *
-     * @return \Illuminate\Http\Response
-     */
-    public function create()
-    {
-        //
-    }
+    public function index(Request $request) {}
 
 
     /**
     /**
      * Store a newly created resource in storage.
      * Store a newly created resource in storage.
@@ -46,12 +32,13 @@ class SentenceInfoController extends Controller
         //
         //
     }
     }
 
 
-    private function getSentProgress(Request $request,$date=''){
+    private function getSentProgress(Request $request, $date = '')
+    {
         $channel = $request->get('channel');
         $channel = $request->get('channel');
         $from = $request->get('from');
         $from = $request->get('from');
-        if ($request->has('to')){
+        if ($request->has('to')) {
             $to = $request->get('to');
             $to = $request->get('to');
-        }else{
+        } else {
             $to = $this->_endParagraph;
             $to = $this->_endParagraph;
         }
         }
 
 
@@ -62,82 +49,83 @@ class SentenceInfoController extends Controller
         # page
         # page
         # percent
         # percent
         $view = 'strlen';
         $view = 'strlen';
-        if($request->has('view')){
-            $view =$request->get('view');
-        }else if($request->has('type')){
-            $view =$request->get('type');
+        if ($request->has('view')) {
+            $view = $request->get('view');
+        } else if ($request->has('type')) {
+            $view = $request->get('type');
         }
         }
 
 
 
 
         #一页书中的字符数
         #一页书中的字符数
         $pageStrLen = 2000;
         $pageStrLen = 2000;
-        if($request->has('strlen')){
-            $pageStrLen =$request->get('strlen');
+        if ($request->has('strlen')) {
+            $pageStrLen = $request->get('strlen');
         }
         }
-        if($request->has('pagelen')){
+        if ($request->has('pagelen')) {
             $pageStrLen = $request->get('pagelen');
             $pageStrLen = $request->get('pagelen');
         }
         }
 
 
         # 页数
         # 页数
         $pageNumber = 300;
         $pageNumber = 300;
-        if($request->has('pages')){
-            $pageNumber =$request->get('pages');
+        if ($request->has('pages')) {
+            $pageNumber = $request->get('pages');
         }
         }
 
 
-        $db = Sentence::where('sentences.channel_uid',$request->get('channel'))
-                    ->where('sentences.book_id','>=',$request->get('book'))
-                    ->where('sentences.paragraph','>=',$request->get('from'))
-                    ->where('sentences.paragraph','<=',$to);
-        if($view==="palistrlen"){
-            $db = $db->leftJoin('pali_texts', function($join)
-                    {
-                        $join->on('sentences.book_id', '=', 'pali_texts.book');
-                        $join->on('sentences.paragraph','=','pali_texts.paragraph');
-                    });
+        $db = Sentence::where('sentences.channel_uid', $request->get('channel'))
+            ->where('sentences.book_id', '>=', $request->get('book'))
+            ->where('sentences.paragraph', '>=', $request->get('from'))
+            ->where('sentences.paragraph', '<=', $to);
+        if ($view === "palistrlen") {
+            $db = $db->leftJoin('pali_texts', function ($join) {
+                $join->on('sentences.book_id', '=', 'pali_texts.book');
+                $join->on('sentences.paragraph', '=', 'pali_texts.paragraph');
+            });
         }
         }
-        if(!empty($date)){
-            $db = $db->whereDate('sentences.created_at','=',$date);
+        if (!empty($date)) {
+            $db = $db->whereDate('sentences.created_at', '=', $date);
         }
         }
-        if($view==="palistrlen"){
+        if ($view === "palistrlen") {
             return $db->sum('pali_texts.lenght');
             return $db->sum('pali_texts.lenght');
         }
         }
         $strlen = $db->sum('sentences.strlen');
         $strlen = $db->sum('sentences.strlen');
 
 
-        if(is_null($strlen) || $strlen===0){
+        if (is_null($strlen) || $strlen === 0) {
             return 0;
             return 0;
         }
         }
         #计算已完成百分比
         #计算已完成百分比
         $percent = 0;
         $percent = 0;
-        if(($view==='page' && !empty($request->get('pages'))) || $view==='percent' ){
+        if (($view === 'page' && !empty($request->get('pages'))) || $view === 'percent') {
             #计算完成的句子在巴利语句子表中的字符串长度百分比
             #计算完成的句子在巴利语句子表中的字符串长度百分比
-            $db = Sentence::select(['book_id','paragraph','word_start','word_end'])
-                ->where('channel_uid',$request->get('channel'))
-                ->where('book_id','>=',$request->get('book'))
-                ->where('paragraph','>=',$request->get('from'))
-                ->where('paragraph','<=',$to);
-            if(!empty($date)){
-                $db = $db->whereDate('created_at','=',$date);
+            $db = Sentence::select(['book_id', 'paragraph', 'word_start', 'word_end'])
+                ->where('channel_uid', $request->get('channel'))
+                ->where('book_id', '>=', $request->get('book'))
+                ->where('paragraph', '>=', $request->get('from'))
+                ->where('paragraph', '<=', $to);
+            if (!empty($date)) {
+                $db = $db->whereDate('created_at', '=', $date);
             }
             }
             $sentFinished = $db->get();
             $sentFinished = $db->get();
             #查询这些句子的总共等效巴利语字符数
             #查询这些句子的总共等效巴利语字符数
-            $allStrLen = PaliSentence::where('book',$request->get('book'))
-                            ->where('paragraph','>=',$request->get('from'))
-                            ->where('paragraph','<=',$to)
-                            ->sum('length');
+            $allStrLen = PaliSentence::where('book', $request->get('book'))
+                ->where('paragraph', '>=', $request->get('from'))
+                ->where('paragraph', '<=', $to)
+                ->sum('length');
             $para_strlen = 0;
             $para_strlen = 0;
 
 
             foreach ($sentFinished as $sent) {
             foreach ($sentFinished as $sent) {
                 # code...
                 # code...
-				$key_sent_id = $sent->book_id.'-'.$sent->paragraph.'-'.$sent->word_start.'-'.$sent->word_end;
-				$para_strlen += RedisClusters::remember('pali-sent/strlen/'.$key_sent_id,
-                                    config('mint.cache.expire') ,
-                                    function() use($sent) {
-                                        return PaliSentence::where('book',$sent->book_id)
-                                                ->where('paragraph',$sent->paragraph)
-                                                ->where('word_begin',$sent->word_start)
-                                                ->where('word_end',$sent->word_end)
-                                                ->value('length');
-				});
+                $key_sent_id = $sent->book_id . '-' . $sent->paragraph . '-' . $sent->word_start . '-' . $sent->word_end;
+                $para_strlen += RedisClusters::remember(
+                    'pali-sent/strlen/' . $key_sent_id,
+                    config('mint.cache.expire'),
+                    function () use ($sent) {
+                        return PaliSentence::where('book', $sent->book_id)
+                            ->where('paragraph', $sent->paragraph)
+                            ->where('word_begin', $sent->word_start)
+                            ->where('word_end', $sent->word_end)
+                            ->value('length');
+                    }
+                );
             }
             }
 
 
             $percent = $para_strlen / $allStrLen;
             $percent = $para_strlen / $allStrLen;
@@ -145,16 +133,16 @@ class SentenceInfoController extends Controller
         switch ($view) {
         switch ($view) {
             case 'page':
             case 'page':
                 # 输出已经完成的页数
                 # 输出已经完成的页数
-                if(!empty($request->get('pages'))){
+                if (!empty($request->get('pages'))) {
                     #给了页码,用百分比计算
                     #给了页码,用百分比计算
                     $resulte = $percent * $request->get('pages');
                     $resulte = $percent * $request->get('pages');
-                }else{
+                } else {
                     #没给页码,用每页字符数计算
                     #没给页码,用每页字符数计算
                     $resulte = $strlen / $pageStrLen;
                     $resulte = $strlen / $pageStrLen;
                 }
                 }
                 break;
                 break;
             case 'percent': //百分比
             case 'percent': //百分比
-                $resulte = sprintf('%.2f',$percent);
+                $resulte = sprintf('%.2f', $percent);
                 break;
                 break;
             case 'strlen':
             case 'strlen':
             default:
             default:
@@ -163,11 +151,11 @@ class SentenceInfoController extends Controller
                 break;
                 break;
         }
         }
         #保留小数点后两位
         #保留小数点后两位
-        $resulte = sprintf('%.2f',$resulte);
+        $resulte = sprintf('%.2f', $resulte);
         return $resulte;
         return $resulte;
     }
     }
     /**
     /**
-    * 输出一张图片显示进度
+     * 输出一张图片显示进度
      * Display the specified resource.
      * Display the specified resource.
      *
      *
      * @param  \App\Models\Sentence  $sentence
      * @param  \App\Models\Sentence  $sentence
@@ -182,7 +170,7 @@ class SentenceInfoController extends Controller
         switch ($request->get('view')) {
         switch ($request->get('view')) {
             case 'percent':
             case 'percent':
                 # code...
                 # code...
-                $resulte = $resulte*100;
+                $resulte = $resulte * 100;
                 $svg .= "<rect id='frontground' x='0' y='0' width='100' height='25' fill='#cccccc' ></rect>";
                 $svg .= "<rect id='frontground' x='0' y='0' width='100' height='25' fill='#cccccc' ></rect>";
                 $svg .= "<text id='bg_text'  x='5' y='21' fill='#006600' style='font-size:25px;'>$resulte%</text>";
                 $svg .= "<text id='bg_text'  x='5' y='21' fill='#006600' style='font-size:25px;'>$resulte%</text>";
                 $svg .= "<rect id='background' x='0' y='0' width='100' height='25' fill='#006600' clip-path='url(#textClipPath)'></rect>";
                 $svg .= "<rect id='background' x='0' y='0' width='100' height='25' fill='#006600' clip-path='url(#textClipPath)'></rect>";
@@ -199,8 +187,8 @@ class SentenceInfoController extends Controller
         }
         }
         $svg .= "</svg>";
         $svg .= "</svg>";
 
 
-        return response($svg,200,[
-            'Content-Type'=>'image/svg+xml'
+        return response($svg, 200, [
+            'Content-Type' => 'image/svg+xml'
         ]);
         ]);
     }
     }
 
 
@@ -222,50 +210,50 @@ class SentenceInfoController extends Controller
         # page
         # page
         # percent
         # percent
         $view = 'strlen';
         $view = 'strlen';
-        if($request->has('view')){
-            $view =$request->get('view');
+        if ($request->has('view')) {
+            $view = $request->get('view');
         }
         }
-        if($request->has('type')){
-            $view =$request->get('type');
+        if ($request->has('type')) {
+            $view = $request->get('type');
         }
         }
 
 
 
 
 
 
-        $pagePix = ($imgHeight-$xAxisOffset)/$maxPage;
-        $dayPix = ($imgWidth-$yAxisOffset)/$maxDay;
+        $pagePix = ($imgHeight - $xAxisOffset) / $maxPage;
+        $dayPix = ($imgWidth - $yAxisOffset) / $maxDay;
 
 
         ob_clean();
         ob_clean();
         ob_start();
         ob_start();
         $channel = $request->get('channel');
         $channel = $request->get('channel');
         $from = $request->get('from');
         $from = $request->get('from');
-        if ($request->has('to')){
+        if ($request->has('to')) {
             $to = $request->get('to');
             $to = $request->get('to');
-        }else{
-            $chapterLen = PaliText::where('book',$request->get('book'))->where('paragraph',$from)->value('chapter_len');
+        } else {
+            $chapterLen = PaliText::where('book', $request->get('book'))->where('paragraph', $from)->value('chapter_len');
             $to =  $from + $chapterLen - 1;
             $to =  $from + $chapterLen - 1;
             $this->_endParagraph = $to;
             $this->_endParagraph = $to;
         }
         }
 
 
-        $img = imagecreate($imgWidth,$imgHeight) or die('create image fail ');
+        $img = imagecreate($imgWidth, $imgHeight) or die('create image fail ');
 
 
         #颜色定义
         #颜色定义
         //background color
         //background color
-        imagecolorallocate($img,255,255,255);
-        $color = imagecolorallocate($img,0,0,0);
-        $gray = imagecolorallocate($img,180,180,180);
-        $dataLineColor = imagecolorallocate($img,50,50,255);
+        imagecolorallocate($img, 255, 255, 255);
+        $color = imagecolorallocate($img, 0, 0, 0);
+        $gray = imagecolorallocate($img, 180, 180, 180);
+        $dataLineColor = imagecolorallocate($img, 50, 50, 255);
 
 
 
 
 
 
-        $max=0;
+        $max = 0;
         $values = [];
         $values = [];
         #按天获取数据
         #按天获取数据
-        for($i = 1; $i <= $maxDay; $i++){
+        for ($i = 1; $i <= $maxDay; $i++) {
             $day = strtotime("today -{$i} day");
             $day = strtotime("today -{$i} day");
-            $date = date("Y-m-d",$day);
-            $current = $this->getSentProgress($request,$date);
+            $date = date("Y-m-d", $day);
+            $current = $this->getSentProgress($request, $date);
             $values[] = $current;
             $values[] = $current;
-            if($max < $current){
+            if ($max < $current) {
                 $max = $current;
                 $max = $current;
             }
             }
         }
         }
@@ -275,114 +263,110 @@ class SentenceInfoController extends Controller
         * 小于1000 满刻度是是500的整倍数
         * 小于1000 满刻度是是500的整倍数
         */
         */
 
 
-        if($max < $yMin){
+        if ($max < $yMin) {
             $yMax = $yMin;
             $yMax = $yMin;
-        }else{
+        } else {
             $len = strlen($max);
             $len = strlen($max);
-            $yMax = pow(10,$len);
-            if($max < $yMax/2){
+            $yMax = pow(10, $len);
+            if ($max < $yMax / 2) {
                 $yMax = $yMax / 2;
                 $yMax = $yMax / 2;
             }
             }
         }
         }
         //根据满刻度像素数 计算缩放比例
         //根据满刻度像素数 计算缩放比例
-        $yPix = $imgHeight - $xAxisOffset;//y轴实际像素数
+        $yPix = $imgHeight - $xAxisOffset; //y轴实际像素数
         $rate = $yPix / $yMax;
         $rate = $yPix / $yMax;
 
 
         $svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" class=\"bi bi-alarm-fill\" viewBox=\"0 0 $imgWidth $imgHeight\">";
         $svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" class=\"bi bi-alarm-fill\" viewBox=\"0 0 $imgWidth $imgHeight\">";
 
 
         //绘制坐标轴
         //绘制坐标轴
-        imageline($img,0,$imgHeight-$xAxisOffset,$imgWidth,$imgHeight-$xAxisOffset,$color);
-        imageline($img,$yAxisOffset,$imgHeight,$yAxisOffset,0,$color);
+        imageline($img, 0, $imgHeight - $xAxisOffset, $imgWidth, $imgHeight - $xAxisOffset, $color);
+        imageline($img, $yAxisOffset, $imgHeight, $yAxisOffset, 0, $color);
         // x 轴
         // x 轴
-        $y=$imgHeight-$xAxisOffset+1;
+        $y = $imgHeight - $xAxisOffset + 1;
         $svg .= "<line x1='$yAxisOffset'  y1='$y' x2='$imgWidth'   y2='$y' style='stroke:#666666;'></line>";
         $svg .= "<line x1='$yAxisOffset'  y1='$y' x2='$imgWidth'   y2='$y' style='stroke:#666666;'></line>";
         // y 轴
         // y 轴
         $x = $yAxisOffset - 1;
         $x = $yAxisOffset - 1;
-        $svg .= "<line x1='$x'  y1='0' x2='$x'   y2='".($imgHeight-$xAxisOffset)."' style='stroke:#666666;'></line>";
+        $svg .= "<line x1='$x'  y1='0' x2='$x'   y2='" . ($imgHeight - $xAxisOffset) . "' style='stroke:#666666;'></line>";
         //绘制x轴刻度线
         //绘制x轴刻度线
-        for($i=0; $i<$maxDay; $i++){
-            $space= ($imgWidth-$yAxisOffset)/$maxDay;
-            $x=$imgWidth-$i*$space - $space/2;
-            $dayOffset = $maxDay-$i;
+        for ($i = 0; $i < $maxDay; $i++) {
+            $space = ($imgWidth - $yAxisOffset) / $maxDay;
+            $x = $imgWidth - $i * $space - $space / 2;
+            $dayOffset = $maxDay - $i;
             $date = strtotime("today -{$i} day");
             $date = strtotime("today -{$i} day");
-            $day = date("d",$date);
-            imageline($img,$x,($imgHeight-$xAxisOffset),$x,($imgHeight-$xAxisOffset+5),$gray);
-            imagestring($img,5,$x,($imgHeight-$xAxisOffset-2),$day,$color);
+            $day = date("d", $date);
+            imageline($img, $x, ($imgHeight - $xAxisOffset), $x, ($imgHeight - $xAxisOffset + 5), $gray);
+            imagestring($img, 5, $x, ($imgHeight - $xAxisOffset - 2), $day, $color);
 
 
-            $y = $imgHeight-$xAxisOffset+1;
+            $y = $imgHeight - $xAxisOffset + 1;
             $height = 5;
             $height = 5;
-            $svg .= "<line x1='$x'  y1='$y' x2='$x'   y2='".($y+$height)."' style='stroke:#666666;'></line>";
-            $svg .= "<text x='".($x-5)."' y='".($y+12)."' style='font-size:8px;'>$day</text>";
+            $svg .= "<line x1='$x'  y1='$y' x2='$x'   y2='" . ($y + $height) . "' style='stroke:#666666;'></line>";
+            $svg .= "<text x='" . ($x - 5) . "' y='" . ($y + 12) . "' style='font-size:8px;'>$day</text>";
         }
         }
 
 
 
 
         //绘制y轴刻度线 将y轴五等分
         //绘制y轴刻度线 将y轴五等分
         $step = $yMax / 5 * $rate;
         $step = $yMax / 5 * $rate;
-        for ($i=1; $i < 5; $i++) {
+        for ($i = 1; $i < 5; $i++) {
             # code...
             # code...
             $yValue = $yMax / 5 * $i;
             $yValue = $yMax / 5 * $i;
-            if($yValue>=1000000){
-                $yValue = ($yValue / 1000000 ).'m';
-            }else if($yValue>=1000){
-                $yValue = ($yValue / 1000 ).'k';
+            if ($yValue >= 1000000) {
+                $yValue = ($yValue / 1000000) . 'm';
+            } else if ($yValue >= 1000) {
+                $yValue = ($yValue / 1000) . 'k';
             }
             }
             $x = $yAxisOffset;
             $x = $yAxisOffset;
-            $y = $imgHeight-$yAxisOffset-$i*$step;
-            $svg .= "<line x1='$x'  y1='$y' x2='".($x - 5)."'   y2='$y' style='stroke:#666666;'></line>";
-            $svg .= "<text x='".($x-18)."' y='".($y+4)."' style='font-size:8px;'>$yValue</text>";
+            $y = $imgHeight - $yAxisOffset - $i * $step;
+            $svg .= "<line x1='$x'  y1='$y' x2='" . ($x - 5) . "'   y2='$y' style='stroke:#666666;'></line>";
+            $svg .= "<text x='" . ($x - 18) . "' y='" . ($y + 4) . "' style='font-size:8px;'>$yValue</text>";
         }
         }
-        for($i=1;$i < $maxPage/$yLineSpace;$i++){
-            $space= ($imgHeight-$xAxisOffset)/$maxPage*$yLineSpace;
-            $y=$imgHeight-$yAxisOffset-$i*$space;
-            imageline($img,$yAxisOffset,$y,$imgWidth,$y,$gray);
-            imagestring($img,5,0,$y-5,$i*$yLineSpace,$color);
+        for ($i = 1; $i < $maxPage / $yLineSpace; $i++) {
+            $space = ($imgHeight - $xAxisOffset) / $maxPage * $yLineSpace;
+            $y = $imgHeight - $yAxisOffset - $i * $space;
+            imageline($img, $yAxisOffset, $y, $imgWidth, $y, $gray);
+            imagestring($img, 5, 0, $y - 5, $i * $yLineSpace, $color);
         }
         }
-// 绘制柱状图
-        $rectWidth = $dayPix*0.9;
+        // 绘制柱状图
+        $rectWidth = $dayPix * 0.9;
         $last = 0;
         $last = 0;
         foreach ($values as $key => $value) {
         foreach ($values as $key => $value) {
             # code...
             # code...
-            $value = $value*$rate;
+            $value = $value * $rate;
             $x = $imgWidth - ($dayPix * $key + $yAxisOffset);
             $x = $imgWidth - ($dayPix * $key + $yAxisOffset);
             $y = $imgHeight - $xAxisOffset - $value;
             $y = $imgHeight - $xAxisOffset - $value;
             $svg .= "<rect x='$x' y='$y' height='{$value}' width='{$rectWidth}' style='stroke:#006600; fill: #006600'/>";
             $svg .= "<rect x='$x' y='$y' height='{$value}' width='{$rectWidth}' style='stroke:#006600; fill: #006600'/>";
-            if($key>0){
-                imageline($img,($imgWidth - $key * $dayPix),$imgHeight - $xAxisOffset - $value,($imgWidth-($key - 1)*$dayPix),$imgHeight-$xAxisOffset-$last,$dataLineColor);
+            if ($key > 0) {
+                imageline($img, ($imgWidth - $key * $dayPix), $imgHeight - $xAxisOffset - $value, ($imgWidth - ($key - 1) * $dayPix), $imgHeight - $xAxisOffset - $last, $dataLineColor);
             }
             }
             $last = $value;
             $last = $value;
         }
         }
 
 
-    $svg .= "</svg>";
+        $svg .= "</svg>";
 
 
         imagegif($img);
         imagegif($img);
         imagedestroy($img);
         imagedestroy($img);
 
 
         $content = ob_get_clean();
         $content = ob_get_clean();
-        return response($svg,200,[
-            'Content-Type'=>'image/svg+xml'
+        return response($svg, 200, [
+            'Content-Type' => 'image/svg+xml'
         ]);
         ]);
     }
     }
 
 
     /**
     /**
      * Display the specified resource.
      * Display the specified resource.
-     *
-     * @param  \App\Models\Sentence  $sentence
-     * @return \Illuminate\Http\Response
-     */
-    public function show(Sentence $sentence)
-    {
-        //
-    }
-
-    /**
-     * Show the form for editing the specified resource.
-     *
-     * @param  \App\Models\Sentence  $sentence
+     * @param  \Illuminate\Http\Request  $request
+     * @param  string  $sentenceId
      * @return \Illuminate\Http\Response
      * @return \Illuminate\Http\Response
      */
      */
-    public function edit(Sentence $sentence)
+    public function show(Request $request, string $sentenceId)
     {
     {
         //
         //
+        $sentence = Sentence::where('book_id', $request->get('book'))
+            ->where('paragraph', $request->get('par'))
+            ->where('word_start', $request->get('start'))
+            ->where('word_end', $request->get('end'))
+            ->where('channel_uid', $request->get('channel'))
+            ->firstOrFail();
+        return $this->ok(new SentResource($sentence));
     }
     }
 
 
     /**
     /**

+ 8 - 0
api-v8/config/mint.php

@@ -102,6 +102,14 @@ return [
     'ai' => [
     'ai' => [
         'assistant' => 'test161',
         'assistant' => 'test161',
         'default' => 'kimi',
         'default' => 'kimi',
+        'logo' => [
+            'gemini' => 'gemini-color.png',
+            'grok' => 'grok.png',
+            'Claude' => 'claude-color.png',
+            'api.openai.com' => 'openai.png',
+            'qwen' => 'qwen-color.png',
+            'deepseek' => 'deepseek-color.png'
+        ]
     ],
     ],
     'mq' => [
     'mq' => [
         'loop_limit' => [
         'loop_limit' => [

BIN
api-v8/public/assets/images/avatar/claude-color.png


BIN
api-v8/public/assets/images/avatar/deepseek-color.png


BIN
api-v8/public/assets/images/avatar/doubao-color.png


BIN
api-v8/public/assets/images/avatar/gemini-color.png


BIN
api-v8/public/assets/images/avatar/grok.png


BIN
api-v8/public/assets/images/avatar/kimi-color.png


BIN
api-v8/public/assets/images/avatar/openai.png


BIN
api-v8/public/assets/images/avatar/qwen-color.png


+ 43 - 0
api-v8/resources/mustache/my_han_crop.tpl

@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+	<head>
+    <style type="text/css">
+.img{
+	max-height: 1000px;
+    max-width: 750px;
+    overflow: hidden;
+	padding: 0 8px 8px 0;
+}
+.img:hover{
+	overflow: scroll;
+	scrollbar-width: thin;
+	scrollbar-color: rgba(0, 0, 0, 0.5) transparent;
+}
+.dict{
+	width: 880px;
+}
+	</style>
+</head>
+  <body>
+    <h3>Page {{page}}</h3>
+<div style="display: flex;">
+<div>
+	<table>
+{{#words}}
+      <tr>
+        <td>{{spell}}</td>
+        <td><img src="img/{{spell}}.png" /></td>
+      </tr>
+{{/words}}
+    </table>
+</div>
+<div>
+{{#dict}}
+<div class="img">
+	<img class="dict" src="{{img}}">
+</div>
+{{/dict}}
+</div>
+</div>
+  </body>
+</html>

+ 1 - 0
api-v8/routes/api.php

@@ -289,4 +289,5 @@ Route::group(['prefix' => 'v2'], function () {
     Route::apiResource('model-log', ModelLogController::class);
     Route::apiResource('model-log', ModelLogController::class);
     Route::apiResource('sentence-attachment', SentenceAttachmentController::class);
     Route::apiResource('sentence-attachment', SentenceAttachmentController::class);
     Route::apiResource('email-certification', EmailCertificationController::class);
     Route::apiResource('email-certification', EmailCertificationController::class);
+    Route::apiResource('sentence-info', SentenceInfoController::class);
 });
 });

+ 8 - 2
dashboard-v4/dashboard/src/components/auth/User.tsx

@@ -36,7 +36,9 @@ const UserWidget = ({
         <Avatar
         <Avatar
           size={"small"}
           size={"small"}
           src={avatar}
           src={avatar}
-          style={{ backgroundColor: getAvatarColor(nickName) }}
+          style={
+            avatar ? undefined : { backgroundColor: getAvatarColor(nickName) }
+          }
         >
         >
           {nickName?.slice(0, 2)}
           {nickName?.slice(0, 2)}
         </Avatar>
         </Avatar>
@@ -56,7 +58,11 @@ const UserWidget = ({
             <Avatar
             <Avatar
               size="large"
               size="large"
               src={avatar}
               src={avatar}
-              style={{ backgroundColor: getAvatarColor(nickName) }}
+              style={
+                avatar
+                  ? undefined
+                  : { backgroundColor: getAvatarColor(nickName) }
+              }
             >
             >
               {nickName?.slice(0, 2)}
               {nickName?.slice(0, 2)}
             </Avatar>
             </Avatar>