chengjie 1 miesiąc temu
rodzic
commit
ccaeea27e1

+ 1 - 1
src/test/kill-port.js

@@ -2,7 +2,7 @@ import { exec as execCallback } from 'child_process';
2 2
 import { promisify } from 'util';
3 3
 
4 4
 const exec = promisify(execCallback);
5
-const port = 3000; // 可修改为需要监听的端口
5
+const port = 3010; // 可修改为需要监听的端口
6 6
 
7 7
 const getCommand = (port) => {
8 8
   return process.platform === 'win32'

+ 3 - 0
src/util/constant/index.js

@@ -115,6 +115,9 @@ export default {
115 115
             },{
116 116
                 Word: "智者乐水",
117 117
                 Sound: "智者乐(yao4)水",
118
+            },{
119
+                Word: "绷着脸",
120
+                Sound: "绷(beng3)着脸",
118 121
             }, {
119 122
                 Word: "(bo)",
120 123
                 Sound: "卜(bo5)",

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

@@ -0,0 +1,119 @@
1
+// 为 UserID=2 的雅思卡片补充 ContentType=3 例句
2
+// 逻辑:从 ContentType=2 提取单词 -> 在雅思 Words(BookID 212-217) 取 ExampleSentence JSON -> 写入 ContentType=3
3
+// 用法:
4
+//   DRY=1 node update_card_examples.js   # 预检,打印匹配情况,不写库
5
+//   node update_card_examples.js         # 正式写入
6
+
7
+import { query } from '../../../src/util/db.js';
8
+
9
+const DRY = process.env.DRY === '1';
10
+const USER_ID = 2;
11
+const MIN_CARD_ID = 1671933;
12
+const BOOK_IDS = [212, 213, 214, 215, 216, 217];
13
+
14
+function extractWord(content) {
15
+  if (!content) return null;
16
+  // 1) [读 src='...text=WORD&...'] 中的 text= 参数
17
+  const m1 = content.match(/text=([^&\s'"]+)/);
18
+  if (m1) {
19
+    try {
20
+      const w = decodeURIComponent(m1[1]).trim();
21
+      if (w) return w;
22
+    } catch {
23
+      /* ignore */
24
+    }
25
+  }
26
+  // 2) 兜底:行首 "WORD 的基本中文释义"
27
+  const m2 = content.match(/^([A-Za-z][A-Za-z'’.\-\s]*?)\s*的基本中文释义/);
28
+  if (m2) return m2[1].trim();
29
+  return null;
30
+}
31
+
32
+async function main() {
33
+  const cards = await query(
34
+    `select MiaoguoCardID from kylx365_db.MiaoguoCard where UserID=? and MiaoguoCardID>=? order by MiaoguoCardID`,
35
+    [USER_ID, MIN_CARD_ID]
36
+  );
37
+  console.log(`目标卡片数: ${cards.length}`);
38
+  if (!cards.length) return;
39
+
40
+  const cardIds = cards.map((c) => c.MiaoguoCardID);
41
+  const inSql = '(' + cardIds.join(',') + ')';
42
+  const contents = await query(
43
+    `select MiaoguoContentID, MiaoguoCardID, ContentType, Content from kylx365_db.MiaoguoContent where MiaoguoCardID in ${inSql} and ContentType in (2,3) order by MiaoguoCardID, ContentType`
44
+  );
45
+
46
+  // 建立 card -> {2: row, 3: row}
47
+  const map = new Map();
48
+  for (const r of contents) {
49
+    if (!map.has(r.MiaoguoCardID)) map.set(r.MiaoguoCardID, {});
50
+    map.get(r.MiaoguoCardID)[r.ContentType] = r;
51
+  }
52
+
53
+  // 收集所有要查的单词
54
+  const wordToCards = new Map(); // lowerWord -> [{cardId, content3Id}]
55
+  for (const [cardId, rec] of map) {
56
+    const c2 = rec[2];
57
+    if (!c2) continue;
58
+    const w = extractWord(c2.Content);
59
+    if (!w) {
60
+      console.warn(`  ✗ 无法提取单词 card=${cardId}`);
61
+      continue;
62
+    }
63
+    const c3 = rec[3];
64
+    if (!c3) {
65
+      console.warn(`  ✗ 缺少 ContentType=3 行 card=${cardId}`);
66
+      continue;
67
+    }
68
+    const key = w.toLowerCase();
69
+    if (!wordToCards.has(key)) wordToCards.set(key, []);
70
+    wordToCards.get(key).push({ cardId, content3Id: c3.MiaoguoContentID, word: w });
71
+  }
72
+
73
+  // 一次性查雅思例句
74
+  const words = [...wordToCards.keys()];
75
+  const examples = new Map();
76
+  if (words.length) {
77
+    const rows = await query(
78
+      `select Word, ExampleSentence from kylx365_db.Words where BookID in (${BOOK_IDS.join(',')}) and LOWER(Word) in (?)`,
79
+      [words]
80
+    );
81
+    for (const r of rows) examples.set(r.Word.toLowerCase(), r.ExampleSentence);
82
+  }
83
+
84
+  let matched = 0,
85
+    unmatched = 0,
86
+    updated = 0,
87
+    skipped = 0;
88
+  for (const [, list] of wordToCards) {
89
+    for (const item of list) {
90
+      const ex = examples.get(item.word.toLowerCase());
91
+      if (!ex) {
92
+        unmatched++;
93
+        console.warn(`  ✗ 雅思词库无例句: "${item.word}" (card=${item.cardId})`);
94
+        continue;
95
+      }
96
+      matched++;
97
+      if (DRY) {
98
+        console.log(`  · ${item.word} (card=${item.cardId}) -> 例句 ${ex.length} 字符`);
99
+        continue;
100
+      }
101
+      await query('update kylx365_db.MiaoguoContent set Content=? where MiaoguoContentID=?', [
102
+        ex,
103
+        item.content3Id,
104
+      ]);
105
+      updated++;
106
+    }
107
+  }
108
+
109
+  console.log(
110
+    `\n预检=${DRY ? '是' : '否'} | 卡片派生词 ${wordToCards.size} | 匹配例句 ${matched} | 无例句 ${unmatched} | 已写入 ${updated}`
111
+  );
112
+}
113
+
114
+main()
115
+  .then(() => process.exit(0))
116
+  .catch((e) => {
117
+    console.error(e);
118
+    process.exit(1);
119
+  });