7272 <p >Ollama 正在思考中,请稍候...</p >
7373 </div >
7474
75- <div v-else-if =" aiError && !aiRawExplanation" class =" error-message" >
75+ <div v-else-if =" aiError && !aiRawExplanation && aiExamples.length === 0 " class =" error-message" >
7676 {{ aiError }}
7777 <button @click =" fetchAiExplanation" style =" margin-left : 10px ; background : none ; border : none ; text-decoration : underline ; color : inherit ; cursor : pointer ;" >重试</button >
7878 </div >
7979
80- <div v-if =" aiRawExplanation" class =" ai-content markdown-body" v-html =" aiExplanation" ></div >
80+ <div v-if =" aiExamples.length > 0" class =" ai-module" >
81+ <h4 class =" module-title" >💬 实用例句</h4 >
82+ <div class =" examples-grid" >
83+ <div v-for =" (ex, idx) in aiExamples" :key =" idx" class =" example-box" >
84+ <div class =" ex-japanese" >{{ ex.japanese }}</div >
85+ <div class =" ex-kana" >{{ ex.kana }}</div >
86+ <div class =" ex-chinese" >{{ ex.chinese }}</div >
87+ </div >
88+ </div >
89+ </div >
90+
91+ <div v-if =" aiRawExplanation" class =" ai-module mt-4" >
92+ <h4 class =" module-title" >📖 词义解析</h4 >
93+ <div class =" ai-content markdown-body" v-html =" aiExplanation" ></div >
94+ </div >
8195 </div >
8296
8397 <!-- 结果展示 -->
@@ -209,6 +223,7 @@ const form = ref({
209223const result = ref (null );
210224const aiRawExplanation = ref (' ' );
211225const verificationStatus = ref ({});
226+ const aiExamples = ref ([]);
212227const loading = ref (false );
213228const loadingAi = ref (false );
214229const aiProgress = ref (0 );
@@ -323,6 +338,7 @@ const conjugate = async () => {
323338 aiRawExplanation .value = ' ' ;
324339 aiError .value = ' ' ;
325340 verificationStatus .value = {};
341+ aiExamples .value = [];
326342
327343 if (! form .value .verb || ! form .value .verb .trim ()) {
328344 error .value = ' 请输入动词' ;
@@ -333,20 +349,17 @@ const conjugate = async () => {
333349 return ;
334350 }
335351
336- // 记录原始输入,用于后续判断是否需要更新输入框
337- const originalInput = form .value .verb .trim ();
338-
339352 loading .value = true ;
340353 try {
341354 const response = await axios .get (' /api/conjugate' , {
342355 params: {
343- verb: originalInput
356+ verb: form . value . verb
344357 }
345358 });
346359 result .value = response .data ;
347360
348361 // 如果返回了合法的 dictionaryForm,将其同步回输入框(包含汉字转换)
349- if (result .value .dictionaryForm && originalInput !== result . value . dictionaryForm ) {
362+ if (result .value .dictionaryForm ) {
350363 form .value .verb = result .value .dictionaryForm ;
351364 }
352365
@@ -373,6 +386,7 @@ const fetchAiExplanation = async () => {
373386 aiError .value = ' ' ;
374387 aiRawExplanation .value = ' ' ;
375388 verificationStatus .value = {};
389+ aiExamples .value = [];
376390
377391 try {
378392 startProgress ();
@@ -430,7 +444,10 @@ const fetchAiExplanation = async () => {
430444 try {
431445 // 如果代码块完整,直接解析
432446 const parsed = JSON .parse (jsonMatch[1 ]);
433- verificationStatus .value = parsed;
447+ verificationStatus .value = parsed .verification || parsed;
448+ if (parsed .examples ) {
449+ aiExamples .value = parsed .examples ;
450+ }
434451 aiRawExplanation .value = fullAiText .substring (jsonMatch .index + jsonMatch[0 ].length ).trim ();
435452 } catch (e) {
436453 // JSON 解析失败说明还在流式输出 JSON,尝试用部分匹配提前点亮 ✅
@@ -441,16 +458,18 @@ const fetchAiExplanation = async () => {
441458 const isCorrectMatch = item .match (/ "isCorrect"\s * :\s * (true| false)/ );
442459 if (keyMatch && isCorrectMatch) {
443460 const key = keyMatch[1 ];
444- const isCorrect = isCorrectMatch[1 ] === ' true' ;
445- // 简单提取 correction(如果不完整可能提取不到,但主要是为了尽早显示正确状态)
446- const correctionMatch = item .match (/ "correction"\s * :\s * "([^ "] * )"/ );
447- const correction = correctionMatch ? correctionMatch[1 ] : " " ;
448-
449- if (! verificationStatus .value [key]) {
450- verificationStatus .value = {
451- ... verificationStatus .value ,
452- [key]: { isCorrect, correction }
453- };
461+ if (key !== ' verification' && key !== ' examples' ) {
462+ const isCorrect = isCorrectMatch[1 ] === ' true' ;
463+ // 简单提取 correction(如果不完整可能提取不到,但主要是为了尽早显示正确状态)
464+ const correctionMatch = item .match (/ "correction"\s * :\s * "([^ "] * )"/ );
465+ const correction = correctionMatch ? correctionMatch[1 ] : " " ;
466+
467+ if (! verificationStatus .value [key]) {
468+ verificationStatus .value = {
469+ ... verificationStatus .value ,
470+ [key]: { isCorrect, correction }
471+ };
472+ }
454473 }
455474 }
456475 }
@@ -768,6 +787,50 @@ const fetchAiExplanation = async () => {
768787 border- radius: 2px ;
769788}
770789
790+ .ai - module {
791+ margin- top: 20px ;
792+ border- top: 1px solid #edf2f7;
793+ padding- top: 15px ;
794+ }
795+
796+ .module - title {
797+ color: #4a5568 ;
798+ font- size: 1 .1em ;
799+ margin- top: 0 ;
800+ margin- bottom: 15px ;
801+ }
802+
803+ .examples - grid {
804+ display: flex;
805+ flex- direction: column;
806+ gap: 12px ;
807+ }
808+
809+ .example - box {
810+ background: #f8fafc;
811+ padding: 15px ;
812+ border- radius: 8px ;
813+ border- left: 4px solid #667eea ;
814+ }
815+
816+ .ex - japanese {
817+ font- size: 1 .2em ;
818+ font- weight: 600 ;
819+ color: #2d3748 ;
820+ margin- bottom: 4px ;
821+ }
822+
823+ .ex - kana {
824+ font- size: 0 .9em ;
825+ color: #718096 ;
826+ margin- bottom: 8px ;
827+ }
828+
829+ .ex - chinese {
830+ font- size: 1em ;
831+ color: #4a5568 ;
832+ }
833+
771834.ai - loading {
772835 display: flex;
773836 align- items: center;
0 commit comments