chengjie преди 1 месец
родител
ревизия
d914581f59
променени са 2 файла, в които са добавени 103 реда и са изтрити 1 реда
  1. 9 1
      src/api/miaoguo/miaoguoController.js
  2. 94 0
      秒过知识库更新/04-英语词书导入/ielts/fill_card_examples.js

+ 9 - 1
src/api/miaoguo/miaoguoController.js

@@ -5385,7 +5385,15 @@ export async function AddMiaoguoCard(ctx) {
5385 5385
     if (param.VisitType) {
5386 5386
         createSource = Decrypt(param.VisitType, config.urlSecrets.aes_key, config.urlSecrets.aes_iv);
5387 5387
         if (createSource == "web") {
5388
-            param.ID = Decrypt(param.ID, config.urlSecrets.aes_key, config.urlSecrets.aes_iv);
5388
+            // 新增卡片时客户端传原始 ID(如 0)而非加密串,解密会失败;
5389
+            // 解密失败时保留原值,新增卡走 Type=add 分支即可。
5390
+            if (param.ID) {
5391
+                try {
5392
+                    param.ID = Decrypt(param.ID, config.urlSecrets.aes_key, config.urlSecrets.aes_iv);
5393
+                } catch (e) {
5394
+                    // ID 未加密(新增卡),保持原值
5395
+                }
5396
+            }
5389 5397
             delete param.VisitType;
5390 5398
             ctx.query.Type = param.Type;
5391 5399
             delete param.Type;

+ 94 - 0
秒过知识库更新/04-英语词书导入/ielts/fill_card_examples.js

@@ -0,0 +1,94 @@
1
+// 为雅思卡片(UserID=2, MiaoguoCardID>=1671933)的 ContentType=2 补充例句
2
+// 例句来源: kylx365_db.Words.ExampleSentence (BookID 212-217, 每词5句)
3
+// 渲染格式参照"其余单词"卡片: 例句:\n[读]英文句[/读]\n中文翻译
4
+import { query } from '../../../src/util/db.js';
5
+import { stringUtils } from '../../../src/util/stringClass.js';
6
+
7
+function extractWord(content) {
8
+  // 优先从音频URL提取: gettts?...&text=regent&...
9
+  let m = content.match(/text=([^&]+)/);
10
+  if (m && m[1]) return decodeURIComponent(m[1]).trim();
11
+  // 兜底: "regent 的基本中文释义"
12
+  m = content.match(/^(.*?)\s*的基本中文释义/);
13
+  if (m && m[1]) return m[1].trim();
14
+  return null;
15
+}
16
+
17
+// 高亮单词(参照 build.test31.js / 已有雅思卡片格式: [线]word[/线])
18
+function highlightWord(sentence, word) {
19
+  const forms = stringUtils.getWordAllForms(word);
20
+  let sent = sentence;
21
+  for (const form of forms) {
22
+    if (sent.indexOf(form) >= 0) {
23
+      sent = sent.replace(form, '[线]' + form + '[/线]');
24
+      break;
25
+    }
26
+  }
27
+  return sent;
28
+}
29
+
30
+// 渲染格式与"其余单词"雅思卡片一致: 例句:\n英文(高亮单词)\n中文\n\n...
31
+function buildExampleBlock(sentences, word) {
32
+  const lines = sentences.map(s => highlightWord(s.Sentence, word) + '\n' + s.Translate);
33
+  return '\n例句:\n' + lines.join('\n\n') + '\n\n';
34
+}
35
+
36
+async function run({ dryRun = false } = {}) {
37
+  // 1) 取目标卡片
38
+  const cards = await query(
39
+    'SELECT MiaoguoCardID FROM kylx365_db.MiaoguoCard where UserID=2 and MiaoguoCardID>=1671933 order by MiaoguoCardID'
40
+  );
41
+  const ids = cards.map(r => r.MiaoguoCardID);
42
+  console.log('目标卡片数:', ids.length);
43
+
44
+  let updated = 0, skipped = 0, noWord = 0, noSrc = 0;
45
+  for (const cid of ids) {
46
+    const rows = await query(
47
+      'select Content from kylx365_db.MiaoguoContent where MiaoguoCardID=? and ContentType=2',
48
+      [cid]
49
+    );
50
+    if (!rows.length) { noWord++; console.log('  跳过(无ContentType=2):', cid); continue; }
51
+    let content = rows[0].Content;
52
+    if (content.includes('例句:')) { skipped++; continue; }
53
+
54
+    const word = extractWord(content);
55
+    if (!word) { noWord++; console.log('  跳过(无法提取单词):', cid); continue; }
56
+
57
+    // 2) 查 Words.ExampleSentence
58
+    const ws = await query(
59
+      'select ExampleSentence from kylx365_db.Words where BookID in (212,213,214,215,216,217) and Word=? limit 1',
60
+      [word]
61
+    );
62
+    if (!ws.length || !ws[0].ExampleSentence) { noSrc++; console.log('  跳过(无例句源):', cid, word); continue; }
63
+
64
+    let parsed;
65
+    try { parsed = JSON.parse(ws[0].ExampleSentence); }
66
+    catch (e) { noSrc++; console.log('  跳过(JSON解析失败):', cid, word); continue; }
67
+
68
+    const sentences = (parsed.Sentences || []).filter(s => s.Sentence && s.Translate);
69
+    if (!sentences.length) { noSrc++; console.log('  跳过(例句为空):', cid, word); continue; }
70
+
71
+    const block = buildExampleBlock(sentences, word);
72
+    const newContent = content.replace(/\s*$/, '') + block;
73
+
74
+    if (dryRun) {
75
+      console.log(`\n=== [预览] Card ${cid}  word=${word}  例句数=${sentences.length} ===`);
76
+      console.log(newContent.slice(0, 700));
77
+    } else {
78
+      await query(
79
+        'update kylx365_db.MiaoguoContent set Content=? where MiaoguoCardID=? and ContentType=2',
80
+        [newContent, cid]
81
+      );
82
+      updated++;
83
+      if (updated <= 2) {
84
+        console.log(`\n=== [已写] Card ${cid}  word=${word}  例句数=${sentences.length} ===`);
85
+        console.log(newContent.slice(0, 700));
86
+      }
87
+    }
88
+  }
89
+  console.log(`\n完成. updated=${updated} skipped(已有例句)=${skipped} noWord=${noWord} noSrc=${noSrc}`);
90
+  process.exit(0);
91
+}
92
+
93
+const dryRun = process.argv.includes('--dry');
94
+run({ dryRun }).catch(e => { console.error(e); process.exit(1); });