Просмотр исходного кода

Merge branch 'development' of github.com:iapt-platform/mint into development

Jeremy Zheng 9 месяцев назад
Родитель
Сommit
78e968e818

+ 11 - 26
api-v8/app/Http/Api/MdRender.php

@@ -6,6 +6,7 @@ use Illuminate\Support\Str;
 use App\Models\Channel;
 use Illuminate\Support\Facades\Log;
 use App\Tools\Markdown;
+//use App\Services\TemplateRender;
 
 define("STACK_DEEP", 8);
 
@@ -297,6 +298,7 @@ class MdRender
             foreach ($channelId as $key => $id) {
                 $channelInfo[] = Channel::where('uid', $id)->first();
             }
+
             $tplRender = new TemplateRender(
                 $props,
                 $channelInfo,
@@ -308,6 +310,13 @@ class MdRender
             );
             $tplRender->options($this->options);
             $tplProps = $tplRender->render($tpl_name);
+
+            /*
+            $tplProps = TemplateRender::name($tpl_name)
+                ->options($this->options)
+                ->param($props)
+                ->render();
+                */
             if ($this->options['format'] === 'react' && $tplProps) {
                 $props = $doc->createAttribute("props");
                 $props->nodeValue = $tplProps['props'];
@@ -333,35 +342,11 @@ class MdRender
                     return '';
                 }
                 break;
-            case 'html':
-                if (isset($tplProps)) {
-                    if (is_array($tplProps)) {
-                        return '';
-                    } else {
-                        return $tplProps;
-                    }
-                } else {
-                    Log::error('tplProps undefine');
-                    return '';
-                }
-                break;
-            case 'tex':
-                if (isset($tplProps)) {
-                    if (is_array($tplProps)) {
-                        return '';
-                    } else {
-                        return $tplProps;
-                    }
-                } else {
-                    Log::error('tplProps undefine');
-                    return '';
-                }
-                break;
             default:
-                /**text simple markdown */
+                /**html tex text simple markdown */
                 if (isset($tplProps)) {
                     if (is_array($tplProps)) {
-                        return '';
+                        return $tplProps[0];
                     } else {
                         return $tplProps;
                     }

+ 11 - 0
api-v8/app/Services/RabbitMQService.php

@@ -99,6 +99,16 @@ class RabbitMQService
         }
         $arguments = new AMQPTable($workerArgs);
 
+        $this->channel->queue_declare(
+            $queueName,
+            false,  // passive
+            true,   // durable
+            false,  // exclusive
+            false,  // auto_delete
+            false,  // nowait
+            $arguments
+        );
+        /*
         // 检查队列是否存在
         try {
             $this->channel->queue_declare(
@@ -129,6 +139,7 @@ class RabbitMQService
                 throw $e;
             }
         }
+            */
     }
 
     public function publishMessage(string $queueName, array $data): bool

+ 66 - 0
api-v8/app/Services/TemplateRender.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Services;
+
+use App\Services\Templates\TemplateInterface;
+use InvalidArgumentException;
+
+class TemplateRender
+{
+    protected string $templateName;
+    protected array $params = [];
+    protected TemplateInterface $template;
+
+    // 定义默认公共参数
+    protected array $options = [
+        'format' => 'react', // 默认格式为 react
+    ];
+
+    public static function name(string $templateName): self
+    {
+        $instance = new self();
+        $instance->templateName = $templateName;
+
+        return $instance;
+    }
+
+    public function param(array $params): self
+    {
+        $this->params = $params;
+        return $this;
+    }
+    public function options(array $options): self
+    {
+        $this->options = $options;
+        return $this;
+    }
+
+    public function render(): array
+    {
+        // 解析模板类
+        $this->resolveTemplate();
+
+        // 设置参数并渲染
+        return $this->template
+            ->setParams($this->params)
+            ->setOptions($this->options)
+            ->render();
+    }
+
+    protected function resolveTemplate(): void
+    {
+        // 模板名称到类的映射(可以用配置文件替代)
+        $templateMap = [
+            'cf' => \App\Services\Templates\ConfidenceTemplate::class,
+            'nissaya' => \App\Services\Templates\NissayaTemplate::class,
+            'term' => \App\Services\Templates\TermTemplate::class,
+        ];
+
+        if (!isset($templateMap[$this->templateName])) {
+            throw new InvalidArgumentException("Template {$this->templateName} not found.");
+        }
+
+        // 通过服务容器解析模板类
+        $this->template = app($templateMap[$this->templateName]);
+    }
+}

+ 33 - 0
api-v8/app/Services/Templates/AbstractTemplate.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Services\Templates;
+
+abstract class AbstractTemplate implements TemplateInterface
+{
+    protected array $params = [];
+    protected array $options = [];
+
+    public function setParams(array $params): self
+    {
+        $this->params = $params;
+        return $this;
+    }
+    public function setOptions(array $options): self
+    {
+        $this->options = $options;
+        return $this;
+    }
+    protected  function getParam(string $name, int $id, string $default = ''): string
+    {
+        if (isset($this->params[$name])) {
+            return trim($this->params[$name]);
+        } else if (isset($this->params["{$id}"])) {
+            return trim($this->params["{$id}"]);
+        } else {
+            return $default;
+        }
+    }
+
+
+    abstract public function render(): array;
+}

+ 43 - 0
api-v8/app/Services/Templates/ConfidenceTemplate.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace App\Services\Templates;
+
+class ConfidenceTemplate extends AbstractTemplate
+{
+    public function render(): array
+    {
+        // 示例:处理 email 模板的渲染逻辑
+        $value = $this->getParam('value', 1, '0');
+
+        // 根据 format 调整渲染逻辑
+        $props = ['value' => $value];
+        $output = [];
+        switch ($this->options['format']) {
+            case 'react':
+                $output = [
+                    'props' => base64_encode(\json_encode($props)),
+                    'html' => '',
+                    'tag' => 'span',
+                    'tpl' => 'cf',
+                ];
+                break;
+            case 'unity':
+                $output = [
+                    'props' => base64_encode(\json_encode($props)),
+                    'tpl' => 'cf',
+                ];
+                break;
+            case 'markdown':
+                $output = ["`$value`"];
+                break;
+            case 'html':
+                $output = ["<span>{$value}</span>"];
+                break;
+            default:
+                $output = [$value];
+                break;
+        }
+
+        return $output;
+    }
+}

+ 53 - 0
api-v8/app/Services/Templates/NissayaTemplate.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Services\Templates;
+
+use App\Tools\Tools;
+
+class NissayaTemplate extends AbstractTemplate
+{
+    public function render(): array
+    {
+
+        $pali =  $this->getParam("pali", 1);
+        $meaning = $this->getParam("meaning", 2);
+        $innerString = "";
+        $props = [
+            "pali" => $pali,
+            "meaning" => $meaning,
+            "lang" => $this->options['lang'],
+        ];
+        switch ($this->options['format']) {
+            case 'react':
+                $output = [
+                    'props' => base64_encode(\json_encode($props)),
+                    'html' => $innerString,
+                    'tag' => 'span',
+                    'tpl' => 'nissaya',
+                ];
+                break;
+            case 'unity':
+                $output = [
+                    'props' => base64_encode(\json_encode($props)),
+                    'tpl' => 'nissaya',
+                ];
+                break;
+            case 'text':
+                $output = $pali . '၊' . $meaning;
+                break;
+            case 'tex':
+                $output = $pali . '၊' . $meaning;
+                break;
+            case 'simple':
+                $output = $pali . '၊' . $meaning;
+                break;
+            case 'prompt':
+                $output = Tools::MyToRm($pali) . ':' . $meaning;
+                break;
+            default:
+                $output = $pali . '၊' . $meaning;
+                break;
+        }
+        return $output;
+    }
+}

+ 10 - 0
api-v8/app/Services/Templates/TemplateInterface.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Services\Templates;
+
+interface TemplateInterface
+{
+    public function setParams(array $params): self;
+    public function setOptions(array $options): self;
+    public function render(): array;
+}

+ 268 - 0
api-v8/app/Services/Templates/TermTemplate.php

@@ -0,0 +1,268 @@
+<?php
+
+namespace App\Services\Templates;
+
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Str;
+use App\Models\DhammaTerm;
+use App\Models\Channel;
+use App\Http\Api\ChannelApi;
+use App\Http\Api\MdRender;
+
+
+class TermTemplate extends AbstractTemplate
+{
+    protected $glossaryKey = 'glossary';
+
+    public function render(): array
+    {
+        $word = $this->getParam("word", 1);
+
+        $props = $this->getTermProps($word, '');
+
+        $output = $props['word'];
+        switch ($this->options['format']) {
+            case 'react':
+                $output = [
+                    'props' => base64_encode(\json_encode($props)),
+                    'html' => $props['innerHtml'],
+                    'tag' => 'span',
+                    'tpl' => 'term',
+                ];
+                break;
+            case 'unity':
+                $output = [
+                    'props' => base64_encode(\json_encode($props)),
+                    'tpl' => 'term',
+                ];
+                break;
+            case 'html':
+                if (isset($props["meaning"])) {
+                    $GLOBALS[$this->glossaryKey][$props["word"]] = $props['meaning'];
+
+                    $key = 'term-' . $props["word"];
+                    $termHead = "<a href='#'>" . $props['meaning'] . "</a>";
+
+                    if (isset($GLOBALS[$key])) {
+                        $output = $termHead;
+                    } else {
+                        $GLOBALS[$key] = 1;
+                        $output = $termHead . '(<em>' . $props["word"] . '</em>)';
+                    }
+                } else {
+                    $output = $props["word"];
+                }
+                break;
+            case 'text':
+                if (isset($props["meaning"])) {
+                    $key = 'term-' . $props["word"];
+                    if (isset($GLOBALS[$key])) {
+                        $output = $props["meaning"];
+                    } else {
+                        $GLOBALS[$key] = 1;
+                        $output = $props["meaning"] . '(' . $props["word"] . ')';
+                    }
+                } else {
+                    $output = $props["word"];
+                }
+                break;
+            case 'tex':
+                if (isset($props["meaning"])) {
+                    $key = 'term-' . $props["word"];
+                    if (isset($GLOBALS[$key])) {
+                        $output = $props["meaning"];
+                    } else {
+                        $GLOBALS[$key] = 1;
+                        $output = $props["meaning"] . '(' . $props["word"] . ')';
+                    }
+                } else {
+                    $output = $props["word"];
+                }
+                break;
+            case 'simple':
+                if (isset($props["meaning"])) {
+                    $output = $props["meaning"];
+                } else {
+                    $output = $props["word"];
+                }
+                break;
+            case 'markdown':
+                if (isset($props["meaning"])) {
+                    $key = 'term-' . $props["word"];
+                    if (isset($GLOBALS[$key]) && $GLOBALS[$key] === 1) {
+                        $GLOBALS[$key]++;
+                        $output = $props["meaning"];
+                    } else {
+                        $GLOBALS[$key] = 1;
+                        $output = $props["meaning"] . '(' . $props["word"] . ')';
+                    }
+                } else {
+                    $output = $props["word"];
+                }
+                //如果有内容且第一次出现,显示为脚注
+                if (!empty($props["note"]) && $GLOBALS[$key] === 1) {
+                    if (isset($GLOBALS['note_sn'])) {
+                        $GLOBALS['note_sn']++;
+                    } else {
+                        $GLOBALS['note_sn'] = 1;
+                        $GLOBALS['note'] = array();
+                    }
+                    $content = $props["note"];
+                    $output .= '[^' . $GLOBALS['note_sn'] . ']';
+                    $GLOBALS['note'][] = [
+                        'sn' => $GLOBALS['note_sn'],
+                        'trigger' => '',
+                        'content' => $content,
+                    ];
+                }
+                break;
+            default:
+                if (isset($props["meaning"])) {
+                    $output = $props["meaning"];
+                } else {
+                    $output = $props["word"];
+                }
+                break;
+        }
+        return $output;
+    }
+
+    public function getTermProps($word, $tag = null, $channel = null)
+    {
+        if ($channel && !empty($channel)) {
+            $channelId = $channel;
+        } else {
+            if (count($this->channel_id) > 0) {
+                $channelId = $this->channel_id[0];
+            } else {
+                $channelId = null;
+            }
+        }
+
+        if (count($this->channelInfo) === 0) {
+            if (!empty($channel)) {
+                $channelInfo = Channel::where('uid', $channel)->first();
+                if (!$channelInfo) {
+                    unset($channelInfo);
+                }
+            }
+            if (!isset($channelInfo)) {
+                Log::warning('channel is null');
+                $output = [
+                    "word" => $word,
+                    'innerHtml' => '',
+                ];
+                return $output;
+            }
+        } else {
+            $channelInfo = $this->channelInfo[0];
+        }
+
+        if (Str::isUuid($channelId)) {
+            $lang = Channel::where('uid', $channelId)->value('lang');
+            if (!empty($lang)) {
+                $langFamily = explode('-', $lang)[0];
+            } else {
+                $langFamily = 'zh';
+            }
+            $this->info("term:{$word} 先查属于这个channel 的", 'term');
+            $this->info('channel id' . $channelId, 'term');
+            $table = DhammaTerm::where("word", $word)
+                ->where('channal', $channelId);
+            if ($tag && !empty($tag)) {
+                $table = $table->where('tag', $tag);
+            }
+            $tplParam = $table->orderBy('updated_at', 'desc')
+                ->first();
+            $studioId = $channelInfo->owner_uid;
+        } else {
+            $tplParam = false;
+            $lang = '';
+            $langFamily = '';
+            $studioId = $this->studioId;
+        }
+
+        if (!$tplParam) {
+            if (Str::isUuid($studioId)) {
+                /**
+                 * 没有,再查这个studio的
+                 * 按照语言过滤
+                 * 完全匹配的优先
+                 * 语族匹配也行
+                 */
+                Log::debug("没有-再查这个studio的", 'term');
+                $table = DhammaTerm::where("word", $word);
+                if (!empty($tag)) {
+                    $table = $table->where('tag', $tag);
+                }
+                $termsInStudio = $table->where('owner', $channelInfo->owner_uid)
+                    ->orderBy('updated_at', 'desc')
+                    ->get();
+                if (count($termsInStudio) > 0) {
+                    $list = array();
+                    foreach ($termsInStudio as $key => $term) {
+                        if (empty($term->channal)) {
+                            if ($term->language === $lang) {
+                                $list[$term->guid] = 2;
+                            } else if (strpos($term->language, $langFamily) !== false) {
+                                $list[$term->guid] = 1;
+                            }
+                        }
+                    }
+                    if (count($list) > 0) {
+                        arsort($list);
+                        foreach ($list as $key => $one) {
+                            foreach ($termsInStudio as $term) {
+                                if ($term->guid === $key) {
+                                    $tplParam = $term;
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (!$tplParam) {
+            Log::debug("没有,再查社区", 'term');
+            $community_channel = ChannelApi::getSysChannel("_community_term_zh-hans_");
+            $table = DhammaTerm::where("word", $word);
+            if (!empty($tag)) {
+                $table = $table->where('tag', $tag);
+            }
+            $tplParam = $table->where('channal', $community_channel)
+                ->first();
+            if ($tplParam) {
+                $isCommunity = true;
+            } else {
+                Log::debug("查社区没有", 'term');
+            }
+        }
+        $output = [
+            "word" => $word,
+            "parentChannelId" => $channelId,
+            "parentStudioId" => $channelInfo->owner_uid,
+        ];
+        $innerString = $output["word"];
+        if ($tplParam) {
+            $output["id"] = $tplParam->guid;
+            $output["meaning"] = $tplParam->meaning;
+            $output["channel"] = $tplParam->channal;
+            if (!empty($tplParam->note)) {
+                $mdRender = new MdRender(['format' => $this->options['format']]);
+                $output['note'] = $mdRender->convert($tplParam->note, $this->channel_id);
+            }
+            if (isset($isCommunity)) {
+                $output["isCommunity"] = true;
+            }
+            $innerString = "{$output["meaning"]}({$output["word"]})";
+            if (!empty($tplParam->other_meaning)) {
+                $output["meaning2"] = $tplParam->other_meaning;
+            }
+        }
+        $output['innerHtml'] = $innerString;
+        return $output;
+    }
+}

+ 24 - 0
dashboard-v4/dashboard/src/components/template/Confidence.tsx

@@ -0,0 +1,24 @@
+import { Tag } from "antd";
+
+interface IQaCtl {
+  value?: string;
+}
+const ConfidenceCtl = ({ value = "0%" }: IQaCtl) => {
+  const confidence = parseFloat(value.replace("%", "")); // 结果为 90
+  return <Tag color={confidence < 90 ? "red" : "green"}>{value}</Tag>;
+};
+
+interface IWidget {
+  props: string;
+}
+const Widget = ({ props }: IWidget) => {
+  const prop = JSON.parse(atob(props)) as IQaCtl;
+  console.log(prop);
+  return (
+    <>
+      <ConfidenceCtl {...prop} />
+    </>
+  );
+};
+
+export default Widget;

+ 3 - 0
dashboard-v4/dashboard/src/components/template/MdTpl.tsx

@@ -1,6 +1,7 @@
 import { GrammarPopShell } from "../dict/GrammarPop";
 import Ai from "./Ai";
 import Article from "./Article";
+import Confidence from "./Confidence";
 import DictPreferenceEditor from "./DictPreferenceEditor";
 import Exercise from "./Exercise";
 import GrammarTermLookup from "./GrammarTermLookup";
@@ -72,6 +73,8 @@ const Widget = ({ tpl, props, children }: IWidgetMdTpl) => {
       return props ? <DictPreferenceEditor props={props} /> : <>无效的参数</>;
     case "ai":
       return <Ai props={props ? props : ""} />;
+    case "cf":
+      return <Confidence props={props ? props : ""} />;
     default:
       return <>未定义模版({tpl})</>;
   }