@yangrunchi/a_6 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,7 +40,7 @@
40
40
  └── {模块文件夹}/
41
41
  ├── Panel/ -- 存放多个 UI.lua 文件(可选)
42
42
  ├── Items/ -- 存放 Item 文件,命名以 Item.lua 结尾(可选)
43
- └── {XXX}UI.lua -- UI 文件必须以 UI.lua 结尾
43
+ └── UI{XXX}.lua -- UI 文件必须以 UI{XXX}.lua 开头
44
44
  命名示例
45
45
  类型 命名格式 示例
46
46
  普通面板 UI{XXX}.lua UIBagPanel.lua
@@ -54,7 +54,7 @@
54
54
  dev/GUIExport/bag/UIMainBag.lua dev/GUILayout/bag/UIMainBagPanel.lua
55
55
  dev/GUIExport/bag/UISubBag.lua dev/GUILayout/bag/UISubBagPanel.lua
56
56
 
57
- 若以UI{XXX}.lua后缀结尾 --> 则首次自动生成GUILayout 目录下的 lua 文件。
57
+ 若以UI{XXX}.lua 前缀开头 --> 则首次自动生成GUILayout 目录下的 lua 文件。
58
58
 
59
59
  模版类型 —— 区分单独面板和子面板,减少重复代码
60
60
 
@@ -66,20 +66,20 @@
66
66
  ID = 41600,
67
67
 
68
68
  OBJ_PATH = "GUILayout/R/UIWingPanel",
69
- UI_PATH = "R/WingUI",
69
+ UI_PATH = "R/UIWing",
70
70
  UI_Name = "翅膀"
71
71
  }
72
72
 
73
73
  -- 打开方式
74
74
  ssrUIManager:OPEN(ssrObjCfg.Wing)
75
75
  ```
76
- #### 类型二:子面板(依赖通用一级背景框 ComOneBgOBJ
76
+ #### 类型二:子面板(依赖通用一级背景框 UIComOneBgPanel
77
77
  - **适用**:UISub{XXX}.lua
78
78
  - **模版**:A4_template_2.txt
79
79
  - **目的**:
80
- 依赖通用一级背景框的模版 ,就是把子界面拼接组装到 ComOneBgOBJ 里面,更灵活些。
80
+ 依赖通用一级背景框的模版 ,就是把子界面拼接组装到 UIComOneBgPanel 里面,更灵活些。
81
81
  - **注意事项**:
82
- 1、通用一级框 ComOneBgOBJ , 包含 遮罩 背景 关闭 问号 页签(有无都支持) 红点 等,能用一级背景框,尽量使用。
82
+ 1、通用一级框 UIComOneBgPanel , 包含 遮罩 背景 关闭 问号 页签(有无都支持) 红点 等,能用一级背景框,尽量使用。
83
83
 
84
84
  2、子界面 【垂直水平居中】 推荐使用节点
85
85
  第一种:基础容器 + 节点 —— 【N多元素 放2级节点里面】
@@ -107,8 +107,8 @@
107
107
  OBJ_ORDER = { ssrObjCfg.Mail },
108
108
  --OBJ_DESCRIBE = { "41400" }, 没有页签注释
109
109
  OBJ_TITLE = { "96000" },
110
- OBJ_PATH = "GUILayout/R/Com/ComOneBgOBJ",
111
- UI_PATH = "R/Com/ComOneBgUI",
110
+ OBJ_PATH = "GUILayout/R/Com/UIComOneBgPanel",
111
+ UI_PATH = "R/Com/UIComOneBg",
112
112
  }
113
113
  -- 打开方式
114
114
  ssrUIManager:OPEN(ssrObjCfg.Mail)
@@ -163,8 +163,8 @@
163
163
  OBJ_DESCRIBE = { "强化", "升星", "镶嵌", "洗炼" }, -- OBJ_DESCRIBE 数字 按钮名字是图片 ,否则按钮名字是中文
164
164
  OBJ_TITLE = { "1049", "1049", "1049", "1049" },
165
165
 
166
- OBJ_PATH = "GUILayout/R/Com/ComOneBgOBJ",
167
- UI_PATH = "R/Com/ComOneBgUI",
166
+ OBJ_PATH = "GUILayout/R/Com/UIComOneBgPanel",
167
+ UI_PATH = "R/Com/UIComOneBg",
168
168
  }
169
169
 
170
170
  -- 打开方式(自动选中对应页签)
@@ -253,7 +253,7 @@
253
253
  ssrRedMgr:SetRed(ssrObjCfg.NiepanZB.ID, isRed, 参数1)
254
254
  ssrRedMgr:SetRed(ssrObjCfg.NiepanZB.ID, isRed, 参数2)
255
255
 
256
- -- 注意:参数格式为 NiepanData、XiLianData、ChenghaoData 等 Vo 对象
256
+ -- 注意:参考格式为 NiepanData、XiLianData、ChenghaoData 等 Vo 对象
257
257
 
258
258
  ```
259
259
 
@@ -265,11 +265,24 @@
265
265
 
266
266
  ### 方式一:VSCode 任务集成 + 快捷键安装脚本
267
267
 
268
- **配置文件:** `dev/.vscode/project-keys.json`
268
+ **配置文件:** `a_tools/a_node/Tools/project-keys.json`
269
269
  **启用快捷键:终端执行** `node a_tools/a_node/Tools/install-keys.js`
270
270
  **禁用快捷键:终端执行** `node a_tools/a_node/Tools/uninstall-keys.js`
271
271
  `修改 project-keys.json 后,必须重新执行【启用快捷键】`
272
272
 
273
273
  ### 方式二:远程执行脚本(适合非 VSCode 用户)无需安装 VSCode,打开浏览器即可使用
274
274
 
275
- ### 远程地址:http://10.13.0.26:8080/
275
+ ### 远程地址:http://10.13.0.26:9964/
276
+
277
+
278
+ cd a_tools/a_node
279
+ npm login # 先登录 npm 账号
280
+ npm publish # 发布
281
+
282
+ npm config set //registry.npmjs.org/:_authToken=ck_fovt6rin8irk.KCuiWzbxfGUfPwFAmFWRVrILcfO9p2bq5yzjHP73ucw
283
+
284
+ #检查 token 是否生效:
285
+ npm whoami
286
+ npm view @yangrunchi/a_6
287
+ npm publish --access public
288
+
@@ -6,6 +6,7 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const { execSync } = require('child_process');
9
+ const { getSVNAuthor } = require('../Tools/svn-utils');
9
10
 
10
11
  // ==================== 配置 ====================
11
12
  const projectRoot = require('../Tools/project-root')();
@@ -56,10 +57,14 @@ try {
56
57
  const configPath = path.join(__dirname, '../AutoCode/A1_996_config.json');
57
58
  if (fs.existsSync(configPath)) {
58
59
  config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
59
- console.log('✅ 已加载配置, 作者:', config.author);
60
60
  }
61
61
  } catch (err) { }
62
62
 
63
+ // 自动获取 SVN 账户名(覆盖 config.author)
64
+ const projectRootForAuthor = path.resolve(__dirname, '../../..');
65
+ config.author = getSVNAuthor(projectRootForAuthor, config.author);
66
+ console.log('✅ 已加载配置, 作者:', config.author);
67
+
63
68
  // 需要排除的文件(不生成 require 语句)
64
69
  const excludeFiles = new Set(['template', 'example', 'test']);
65
70
  console.log('\n🚀 开始生成 TableMgr.lua...');
@@ -75,20 +80,6 @@ function getDateTime() {
75
80
 
76
81
  // ==================== SVN 辅助函数 ====================
77
82
 
78
- /**
79
- * 获取 SVN 用户名(当前登录的 SVN 用户)
80
- */
81
- function getSvnUsername() {
82
- try {
83
- const output = execSync(`svn info --show-item last-changed-author`, {
84
- encoding: 'utf8',
85
- stdio: ['pipe', 'pipe', 'ignore']
86
- }).trim();
87
- if (output) return output;
88
- } catch (err) { }
89
- return process.env.USERNAME || process.env.USER || config.author || 'unknown';
90
- }
91
-
92
83
  /**
93
84
  * 执行 SVN 更新(版本2风格)
94
85
  * @param {string} dirPath 目录路径
@@ -173,7 +164,7 @@ function commitTableMgrToSvn() {
173
164
  statusOutput.trim().startsWith('A'));
174
165
 
175
166
  if (needCommit) {
176
- const svnUser = getSvnUsername();
167
+ const svnUser = config.author;
177
168
  const isNewFile = !fs.existsSync(tableMgrPath) || statusOutput.trim().startsWith('A');
178
169
  const commitMessage = isNewFile ?
179
170
  `[Auto] ${svnUser} -首次创建 TableMgr.lua - ${getDateTime()}` :
@@ -1,7 +1,7 @@
1
1
  // -- 作者: 杨润池
2
- // -- 日期: 2026年0421
3
- // -- 版本: 1.2
4
- // -- 描述: 自动生成代码 (支持 UI/UISub/UIMain 前缀)
2
+ // -- 日期: 2026年0624
3
+ // -- 版本: 1.3
4
+ // -- 描述: 自动生成代码 (支持 UI/UISub/UIMain 前缀,作者自动获取 SVN 账户名)
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
@@ -18,6 +18,9 @@ try {
18
18
  process.exit(1);
19
19
  }
20
20
 
21
+ // 导入 SVN 工具函数
22
+ const { getSVNAuthor } = require('../Tools/svn-utils');
23
+
21
24
  // 读取 MainUI 模板(默认模板)
22
25
  const templatePath = path.join(__dirname, 'A4_template_1.txt');
23
26
  let templateMain = '';
@@ -43,10 +46,11 @@ try {
43
46
  const projectRoot = require('../Tools/project-root')();
44
47
  const guiExportDir = path.join(projectRoot, 'dev/GUIExport');
45
48
  const guiLayoutDir = path.join(projectRoot, 'dev/GUILayout');
46
- const author = config.author;
49
+ const author = getSVNAuthor(projectRoot, config.author);
47
50
 
48
51
  console.log(`[DEBUG] guiExportDir: ${guiExportDir}`);
49
52
  console.log(`[DEBUG] guiLayoutDir: ${guiLayoutDir}`);
53
+ console.log(`[DEBUG] author: ${author}`);
50
54
 
51
55
  function getDateTime() {
52
56
  const d = new Date();
@@ -64,16 +68,16 @@ function generate(uiFilePath) {
64
68
 
65
69
  console.log(`[DEBUG] uiFileName: ${uiFileName}`);
66
70
 
67
- // 修正: 检查文件名是否包含 UIUISubUIMain 前缀
68
- const hasUIPrefix = uiFileName.startsWith('UI');
71
+ // 检查文件名是否符合 UI/UISub/UIMain 前缀规则(互斥判断,避免 UI 误匹配 UIMain/UISub)
69
72
  const hasUISubPrefix = uiFileName.startsWith('UISub');
70
73
  const hasUIMainPrefix = uiFileName.startsWith('UIMain');
74
+ const hasUIPrefix = uiFileName.startsWith('UI') && !hasUISubPrefix && !hasUIMainPrefix;
71
75
 
72
76
  const isValidUI = hasUIPrefix || hasUISubPrefix || hasUIMainPrefix;
73
77
 
74
78
  if (!isValidUI) {
75
79
  console.log(`[SKIP] Not a valid UI file: ${uiFileName}`);
76
- console.log(`[INFO] Expected file starting with: UI, UISub, or UIMain`);
80
+ console.log(`[INFO] Expected file starting with: UI{XXX}, UIMain{XXX}, or UISub{XXX}`);
77
81
  return false;
78
82
  }
79
83
 
@@ -106,16 +110,20 @@ function generate(uiFilePath) {
106
110
  console.log(`[MKDIR] ${path.relative(guiLayoutDir, dir)}`);
107
111
  }
108
112
 
109
- // 判断模板类型
113
+ // 判断模板类型:UISub → SubUI 模板,UI/UIMain → MainUI 模板
110
114
  let selectedTemplate = templateMain;
111
115
  let templateType = "MainUI";
116
+ let prefixType = "UI";
112
117
 
113
118
  if (hasUISubPrefix) {
114
119
  selectedTemplate = templateSub;
115
120
  templateType = "SubUI";
121
+ prefixType = "UISub";
122
+ } else if (hasUIMainPrefix) {
123
+ prefixType = "UIMain";
116
124
  }
117
125
 
118
- console.log(`[INFO] Using ${templateType} template (prefix: ${hasUISubPrefix ? 'UISub' : (hasUIMainPrefix ? 'UIMain' : 'UI')})`);
126
+ console.log(`[INFO] Using ${templateType} template (prefix: ${prefixType})`);
119
127
 
120
128
  // 替换模板变量
121
129
  const content = selectedTemplate
@@ -84,10 +84,10 @@ fs.watch(watchDir, { recursive: true }, (eventType, filename) => {
84
84
  return;
85
85
  }
86
86
 
87
- // 检查文件名是否以 UIUISubUIMain 开头
88
- const hasUIPrefix = baseName.startsWith('UI');
87
+ // 检查文件名是否符合 UI/UISub/UIMain 前缀规则(互斥判断,避免 UI 误匹配 UIMain/UISub)
89
88
  const hasUISubPrefix = baseName.startsWith('UISub');
90
89
  const hasUIMainPrefix = baseName.startsWith('UIMain');
90
+ const hasUIPrefix = baseName.startsWith('UI') && !hasUISubPrefix && !hasUIMainPrefix;
91
91
 
92
92
  const isValidUI = hasUIPrefix || hasUISubPrefix || hasUIMainPrefix;
93
93
 
@@ -7,6 +7,7 @@ const fs = require('fs');
7
7
  const path = require('path');
8
8
  const { execSync } = require('child_process');
9
9
  const os = require('os');
10
+ const { getSVNAuthor } = require('../Tools/svn-utils');
10
11
 
11
12
  // ==================== 配置 ====================
12
13
  const projectRoot = require('../Tools/project-root')();
@@ -71,12 +72,16 @@ try {
71
72
  if (fs.existsSync(configPath)) {
72
73
  const configContent = fs.readFileSync(configPath, 'utf-8');
73
74
  config = JSON.parse(configContent);
74
- console.log('✅ 已加载配置, 作者:', config.author);
75
75
  }
76
76
  } catch (err) {
77
77
  console.log('⚠️ 未找到配置文件,使用默认配置');
78
78
  }
79
79
 
80
+ // 自动获取 SVN 账户名(覆盖 config.author)
81
+ const projectRootForAuthor = path.resolve(__dirname, '../../..');
82
+ config.author = getSVNAuthor(projectRootForAuthor, config.author);
83
+ console.log('✅ 已加载配置, 作者:', config.author);
84
+
80
85
  console.log('🚀 开始生成 funcData 类...');
81
86
  console.log('📁 协议文件:', bPath);
82
87
  console.log('📁 数据类输出目录:', funcDataDir);
@@ -10,7 +10,7 @@ const svnUtils = require('../Tools/svn-utils');
10
10
  // ==================== 配置 ====================
11
11
  const projectRoot = require('../Tools/project-root')();
12
12
 
13
- const ProjecPath = path.join(projectRoot, '..', 'Project');
13
+ const ProjecPath = path.join(projectRoot, '..');
14
14
 
15
15
  console.log('🚀 开始执行协议同步流程...');
16
16
  console.log('📁 当前工作目录:', __dirname);
@@ -1,117 +1,207 @@
1
1
  // -- 作者: 杨润池
2
2
  // -- 日期: 2025年10月25日
3
- // -- 版本: 2.0
4
- // -- 描述: 添加快捷键
3
+ // -- 版本: 2.2
4
+ // -- 描述: 多编辑器快捷键同步工具(VS Code / CodeBuddy CN / Cursor)
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
- function installProjectKeys() {
10
- try {
11
- // 1. 检查项目配置文件是否存在
12
- const projectKeysPath = path.join(__dirname, 'project-keys.json');
13
- if (!fs.existsSync(projectKeysPath)) {
14
- console.log('❌ 项目快捷键配置文件不存在:', projectKeysPath);
15
- console.log('💡 请创建 .vscode/project-keys.json 文件');
16
- return false;
9
+ // ============================================================
10
+ // 获取所有已安装编辑器的 keybindings.json 路径
11
+ // ============================================================
12
+ function getEditorPaths() {
13
+ const editors = [];
14
+ const platform = process.platform;
15
+ const home = process.env.HOME || process.env.USERPROFILE || '';
16
+ const appData = process.env.APPDATA || (platform === 'darwin'
17
+ ? path.join(home, 'Library', 'Application Support')
18
+ : path.join(home, '.config'));
19
+
20
+ function addEditor(name, dirName) {
21
+ const editorPath = path.join(appData, dirName, 'User', 'keybindings.json');
22
+ const editorDir = path.dirname(editorPath);
23
+ if (fs.existsSync(editorDir)) {
24
+ editors.push({ name, path: editorPath });
17
25
  }
26
+ }
18
27
 
19
- // 2. 读取项目配置
20
- let projectKeys;
21
- try {
22
- const projectKeysContent = fs.readFileSync(projectKeysPath, 'utf8');
23
- projectKeys = JSON.parse(projectKeysContent);
24
- } catch (error) {
25
- console.log('❌ 读取项目快捷键配置失败:', error.message);
26
- return false;
27
- }
28
+ // 按优先级检测编辑器
29
+ addEditor('VS Code', 'Code');
30
+ addEditor('CodeBuddy CN', 'CodeBuddy CN');
31
+ addEditor('CodeBuddy', 'CodeBuddy');
32
+ addEditor('Cursor', 'Cursor');
33
+
34
+ // 如果 CodeBuddy CN 和 CodeBuddy 同时存在,只保留 CN 版本
35
+ const hasCN = editors.some(e => e.name === 'CodeBuddy CN');
36
+ if (hasCN) {
37
+ const idx = editors.findIndex(e => e.name === 'CodeBuddy');
38
+ if (idx !== -1) editors.splice(idx, 1);
39
+ }
28
40
 
29
- // 3. 确定全局快捷键文件路径
30
- const globalKeysPath = path.join(
31
- process.env.APPDATA ||
32
- (process.platform === 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.config'),
33
- 'Code/User/keybindings.json'
34
- );
35
-
36
- // 4. 确保目录存在
37
- const globalKeysDir = path.dirname(globalKeysPath);
38
- if (!fs.existsSync(globalKeysDir)) {
39
- fs.mkdirSync(globalKeysDir, { recursive: true });
40
- }
41
+ return editors;
42
+ }
41
43
 
42
- // 5. 读取或创建全局配置
44
+ // ============================================================
45
+ // 安装快捷键到单个编辑器
46
+ // ============================================================
47
+ function installToEditor(editor, projectKeys, projectName) {
48
+ try {
49
+ console.log(`\n📝 正在配置 ${editor.name}...`);
50
+ console.log(` 路径: ${editor.path}`);
51
+
52
+ // 读取或创建配置
43
53
  let globalKeys = [];
44
- if (fs.existsSync(globalKeysPath)) {
54
+ if (fs.existsSync(editor.path)) {
45
55
  try {
46
- const globalKeysContent = fs.readFileSync(globalKeysPath, 'utf8');
47
- globalKeys = JSON.parse(globalKeysContent);
56
+ const content = fs.readFileSync(editor.path, 'utf8');
57
+ globalKeys = JSON.parse(content);
48
58
  if (!Array.isArray(globalKeys)) {
49
- console.log('⚠️ 全局快捷键配置不是数组格式,重置为数组');
59
+ console.log(` ⚠️ 配置不是数组格式,重置`);
50
60
  globalKeys = [];
51
61
  }
52
- } catch (error) {
53
- console.log('⚠️ 读取全局快捷键配置失败,创建新配置:', error.message);
62
+ } catch (e) {
63
+ console.log(` ⚠️ 读取失败,创建新配置: ${e.message}`);
54
64
  globalKeys = [];
55
65
  }
56
66
  }
57
67
 
58
- // 6. 获取项目名称用于条件
59
- const projectName = path.basename(process.cwd());
60
- console.log(`📁 项目名称: ${projectName}`);
61
-
62
- // 7. 移除已存在的本项目快捷键(避免重复)
63
- const existingKeysCount = globalKeys.length;
64
- globalKeys = globalKeys.filter(item =>
65
- !(item.when && item.when.includes(projectName))
66
- );
67
- const removedCount = existingKeysCount - globalKeys.length;
68
- if (removedCount > 0) {
69
- console.log(`🗑️ 移除了 ${removedCount} 个已存在的项目快捷键`);
68
+ // 移除本项目已有快捷键(避免重复)
69
+ const before = globalKeys.length;
70
+ globalKeys = globalKeys.filter(item => {
71
+ if (item.when && typeof item.when === 'string') {
72
+ return !item.when.includes(projectName);
73
+ }
74
+ return true;
75
+ });
76
+ const removed = before - globalKeys.length;
77
+ if (removed > 0) {
78
+ console.log(` 🗑️ 移除 ${removed} 个已有快捷键`);
70
79
  }
71
80
 
72
- // 8. 添加新的项目快捷键
73
- if (projectKeys.shortcuts && Array.isArray(projectKeys.shortcuts)) {
74
- projectKeys.shortcuts.forEach((shortcut, index) => {
75
- // 深拷贝避免修改原对象
76
- const newShortcut = JSON.parse(JSON.stringify(shortcut));
81
+ // 添加新快捷键
82
+ if (!projectKeys.shortcuts || !Array.isArray(projectKeys.shortcuts)) {
83
+ console.log(` ❌ 缺少 shortcuts 数组`);
84
+ return false;
85
+ }
77
86
 
78
- // 添加条件限制
79
- if (!newShortcut.when) {
80
- newShortcut.when = `resourcePath =~ /${projectName}/`;
81
- }
87
+ let added = 0;
88
+ projectKeys.shortcuts.forEach((sc, i) => {
89
+ const ns = JSON.parse(JSON.stringify(sc)); // 深拷贝
82
90
 
83
- globalKeys.push(newShortcut);
84
- console.log(`✅ 添加快捷键 ${index + 1}: ${newShortcut.key} -> ${newShortcut.command}`);
85
- });
86
- } else {
87
- console.log('❌ 项目配置中缺少 shortcuts 数组');
91
+ // 智能合并 when 条件
92
+ if (!ns.when) {
93
+ ns.when = `resourcePath =~ /${projectName}/`;
94
+ } else if (!ns.when.includes(projectName)) {
95
+ ns.when = `(${ns.when}) && resourcePath =~ /${projectName}/`;
96
+ }
97
+
98
+ globalKeys.push(ns);
99
+ added++;
100
+ console.log(` ✅ [${i + 1}] ${ns.key} → ${ns.command}`);
101
+ });
102
+
103
+ // 确保目录存在
104
+ const dir = path.dirname(editor.path);
105
+ if (!fs.existsSync(dir)) {
106
+ fs.mkdirSync(dir, { recursive: true });
107
+ }
108
+
109
+ // 写回
110
+ fs.writeFileSync(editor.path, JSON.stringify(globalKeys, null, 4));
111
+ console.log(` ✅ ${editor.name} 完成! 添加 ${added} 个快捷键`);
112
+ return true;
113
+
114
+ } catch (error) {
115
+ console.log(` ❌ ${editor.name} 失败: ${error.message}`);
116
+ return false;
117
+ }
118
+ }
119
+
120
+ // ============================================================
121
+ // 主入口
122
+ // ============================================================
123
+ function installProjectKeys() {
124
+ try {
125
+ console.log('='.repeat(56));
126
+ console.log(' 🚀 项目快捷键同步工具 v2.2');
127
+ console.log('='.repeat(56));
128
+
129
+ // 1. 读取项目配置
130
+ const projectKeysPath = path.join(__dirname, 'project-keys.json');
131
+ if (!fs.existsSync(projectKeysPath)) {
132
+ console.log(`❌ 配置文件不存在: ${projectKeysPath}`);
133
+ console.log('💡 请在同目录下创建 project-keys.json');
88
134
  return false;
89
135
  }
90
136
 
91
- // 9. 写回全局配置
137
+ let projectKeys;
92
138
  try {
93
- fs.writeFileSync(globalKeysPath, JSON.stringify(globalKeys, null, 4));
94
- console.log(`🎉 项目快捷键安装成功! 共添加 ${projectKeys.shortcuts.length} 个快捷键`);
95
- console.log(`📝 全局配置文件: ${globalKeysPath}`);
96
- return true;
97
- } catch (error) {
98
- console.log('❌ 写入全局快捷键配置失败:', error.message);
139
+ projectKeys = JSON.parse(fs.readFileSync(projectKeysPath, 'utf8'));
140
+ console.log('✅ 项目配置读取成功');
141
+ } catch (e) {
142
+ console.log(`❌ JSON 解析失败: ${e.message}`);
99
143
  return false;
100
144
  }
101
145
 
146
+ // 2. 项目名称
147
+ const projectName = path.basename(process.cwd());
148
+ console.log(`📁 项目: ${projectName}`);
149
+ console.log(`📋 快捷键数量: ${projectKeys.shortcuts ? projectKeys.shortcuts.length : 0}`);
150
+
151
+ // 3. 显示快捷键列表
152
+ if (projectKeys.shortcuts && projectKeys.shortcuts.length > 0) {
153
+ console.log('\n📌 将要安装:');
154
+ projectKeys.shortcuts.forEach((sc, i) => {
155
+ console.log(` ${i + 1}. ${sc.key} → ${sc.command}${sc.args ? ` (${sc.args})` : ''}`);
156
+ });
157
+ }
158
+
159
+ // 4. 检测编辑器
160
+ const editors = getEditorPaths();
161
+ if (editors.length === 0) {
162
+ console.log('\n⚠️ 未检测到已安装的编辑器');
163
+ console.log('💡 支持: VS Code, CodeBuddy CN, CodeBuddy, Cursor');
164
+ return false;
165
+ }
166
+
167
+ console.log(`\n🔍 检测到 ${editors.length} 个编辑器:`);
168
+ editors.forEach(e => console.log(` ✅ ${e.name}`));
169
+
170
+ // 5. 同步
171
+ console.log('\n🚀 开始同步...');
172
+ console.log('-'.repeat(56));
173
+
174
+ let success = 0;
175
+ editors.forEach(e => {
176
+ if (installToEditor(e, projectKeys, projectName)) success++;
177
+ });
178
+
179
+ // 6. 总结
180
+ console.log('\n' + '='.repeat(56));
181
+ console.log(`🎉 同步完成! 成功: ${success}/${editors.length}`);
182
+ console.log('='.repeat(56));
183
+ console.log('💡 可能需要重启编辑器或执行 "Reload Window" 才能生效');
184
+
185
+ return success === editors.length;
186
+
102
187
  } catch (error) {
103
- console.log('💥 安装过程中发生未知错误:', error.message);
188
+ console.log(`💥 未知错误: ${error.message}`);
189
+ console.error(error);
104
190
  return false;
105
191
  }
106
192
  }
107
193
 
108
- // 执行安装
194
+ // ============================================================
195
+ // 执行
196
+ // ============================================================
109
197
  if (require.main === module) {
110
198
  installProjectKeys();
111
199
  }
112
200
 
113
201
  module.exports = installProjectKeys;
114
202
 
115
- //Preferences: Open Keyboard Shortcuts
116
-
117
- //node a_tools/a_node/Tools/install-keys.js
203
+ // 使用方法:
204
+ // node a_tools/a_node/Tools/install-keys.js
205
+ // 支持的编辑器:
206
+ // VS Code / CodeBuddy CN / CodeBuddy / Cursor
207
+ // 自动检测已安装的编辑器并同步快捷键
@@ -1,10 +1,11 @@
1
1
  // -- 作者: 杨润池
2
2
  // -- 日期: 2025年10月25日
3
- // -- 版本: 2.0
4
- // -- 描述: SVN 工具
3
+ // -- 版本: 2.1
4
+ // -- 描述: SVN 工具函数集
5
5
 
6
6
  const fs = require('fs');
7
7
  const { execSync, spawnSync } = require('child_process');
8
+
8
9
  // 详细检测 SVN 是否可用
9
10
  function checkSvnEnvironment() {
10
11
  const pathEnv = process.env.PATH || '';
@@ -98,8 +99,6 @@ function cleanDirectory(targetPath) {
98
99
  return true;
99
100
  }
100
101
 
101
- // console.log(`🗑️ 清理目录: ${targetPath}`);
102
-
103
102
  // 使用 rd /s /q 命令强制删除目录(Windows)
104
103
  if (process.platform === 'win32') {
105
104
  execSync(`rd /s /q "${targetPath}"`, { stdio: 'inherit' });
@@ -116,11 +115,62 @@ function cleanDirectory(targetPath) {
116
115
  }
117
116
  }
118
117
 
118
+ /**
119
+ * 获取当前 SVN 仓库的账户名
120
+ * @param {string} projectRoot - 项目根目录路径
121
+ * @param {string} [fallbackAuthor] - SVN 不可用时回退的作者名
122
+ * @returns {string} SVN 账户名或回退作者名
123
+ */
124
+ function getSVNAuthor(projectRoot, fallbackAuthor) {
125
+ try {
126
+ // 获取当前仓库的地址(用于匹配 svn auth 中的 realm)
127
+ const reposUrl = execSync(`svn info --show-item=repos-root-url "${projectRoot}"`, {
128
+ encoding: 'utf-8'
129
+ }).trim();
130
+
131
+ // 提取仓库主机地址(如 "192.168.13.64"),兼容有无端口号、不同协议
132
+ const reposHost = reposUrl.replace(/^[a-z]+:\/\//, '').split(':')[0];
133
+
134
+ // 解析 svn auth 输出,匹配当前仓库的用户名
135
+ const authOutput = execSync('svn auth --non-interactive', {
136
+ encoding: 'utf-8'
137
+ });
138
+
139
+ // 按分隔线分割每个认证条目
140
+ const entries = authOutput.split(/^-{3,}$/m);
141
+ for (const entry of entries) {
142
+ const realmMatch = entry.match(/Authentication realm:\s*<([^>]+)>/);
143
+ if (realmMatch) {
144
+ // 提取 realm 中的主机地址进行匹配
145
+ const realmHost = realmMatch[1].replace(/^[a-z]+:\/\//, '').split(':')[0];
146
+ if (realmHost === reposHost) {
147
+ const userMatch = entry.match(/Username:\s*(.+)/);
148
+ if (userMatch) {
149
+ return userMatch[1].trim();
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ // fallback: 取 svn auth 中最后一个用户名(最近使用的)
156
+ const userLines = authOutput.match(/Username:\s*(.+)/g);
157
+ if (userLines && userLines.length > 0) {
158
+ return userLines[userLines.length - 1].replace(/Username:\s*/, '').trim();
159
+ }
160
+ } catch (e) {
161
+ // SVN 命令失败时忽略,回退到传入的 fallbackAuthor
162
+ }
163
+
164
+ // 最终回退:使用传入的回退作者名
165
+ return fallbackAuthor || '';
166
+ }
167
+
119
168
  // 导出所有函数
120
169
  module.exports = {
121
170
  checkSvnEnvironment,
122
171
  isSvnAvailable,
123
172
  runCommand,
124
173
  runCommit,
125
- cleanDirectory
126
- };
174
+ cleanDirectory,
175
+ getSVNAuthor
176
+ };
@@ -1,65 +1,195 @@
1
1
  // -- 作者: 杨润池
2
2
  // -- 日期: 2025年10月25日
3
- // -- 版本: 2.0
4
- // -- 描述: 删除快捷键
3
+ // -- 版本: 2.2
4
+ // -- 描述: 多编辑器快捷键卸载工具(VS Code / CodeBuddy CN / Cursor)
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
- function uninstallProjectKeys() {
9
+ // ============================================================
10
+ // 获取所有已安装编辑器的 keybindings.json 路径
11
+ // ============================================================
12
+ function getEditorPaths() {
13
+ const editors = [];
14
+ const platform = process.platform;
15
+ const home = process.env.HOME || process.env.USERPROFILE || '';
16
+ const appData = process.env.APPDATA || (platform === 'darwin'
17
+ ? path.join(home, 'Library', 'Application Support')
18
+ : path.join(home, '.config'));
19
+
20
+ function addEditor(name, dirName) {
21
+ const editorPath = path.join(appData, dirName, 'User', 'keybindings.json');
22
+ const editorDir = path.dirname(editorPath);
23
+ if (fs.existsSync(editorDir)) {
24
+ editors.push({ name, path: editorPath });
25
+ }
26
+ }
27
+
28
+ addEditor('VS Code', 'Code');
29
+ addEditor('CodeBuddy CN', 'CodeBuddy CN');
30
+ addEditor('CodeBuddy', 'CodeBuddy');
31
+ addEditor('Cursor', 'Cursor');
32
+
33
+ // 如果 CodeBuddy CN 和 CodeBuddy 同时存在,只保留 CN
34
+ const hasCN = editors.some(e => e.name === 'CodeBuddy CN');
35
+ if (hasCN) {
36
+ const idx = editors.findIndex(e => e.name === 'CodeBuddy');
37
+ if (idx !== -1) editors.splice(idx, 1);
38
+ }
39
+
40
+ return editors;
41
+ }
42
+
43
+ // ============================================================
44
+ // 从单个编辑器卸载项目快捷键
45
+ // ============================================================
46
+ function uninstallFromEditor(editor, projectName) {
10
47
  try {
11
- // 确定全局快捷键文件路径
12
- const globalKeysPath = path.join(
13
- process.env.APPDATA ||
14
- (process.platform === 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.config'),
15
- 'Code/User/keybindings.json'
16
- );
17
-
18
- if (!fs.existsSync(globalKeysPath)) {
19
- console.log('ℹ️ 全局快捷键配置文件不存在,无需卸载');
48
+ console.log(`\n📝 正在处理 ${editor.name}...`);
49
+ console.log(` 路径: ${editor.path}`);
50
+
51
+ if (!fs.existsSync(editor.path)) {
52
+ console.log(` ℹ️ 配置文件不存在,跳过`);
20
53
  return true;
21
54
  }
22
55
 
23
- // 读取全局配置
56
+ // 读取配置
24
57
  let globalKeys = [];
25
58
  try {
26
- const globalKeysContent = fs.readFileSync(globalKeysPath, 'utf8');
27
- globalKeys = JSON.parse(globalKeysContent);
59
+ const content = fs.readFileSync(editor.path, 'utf8');
60
+ globalKeys = JSON.parse(content);
28
61
  if (!Array.isArray(globalKeys)) {
29
- console.log('⚠️ 全局快捷键配置不是数组格式,重置为数组');
30
- globalKeys = [];
62
+ console.log(` ⚠️ 配置不是数组格式,跳过`);
63
+ return true;
31
64
  }
32
- } catch (error) {
33
- console.log('读取全局快捷键配置失败:', error.message);
65
+ } catch (e) {
66
+ console.log(` 读取失败: ${e.message}`);
34
67
  return false;
35
68
  }
36
69
 
37
- // 获取项目名称
38
- const projectName = path.basename(process.cwd());
39
-
40
- // 移除本项目相关的快捷键
41
- const initialCount = globalKeys.length;
42
- globalKeys = globalKeys.filter(item =>
43
- !(item.when && item.when.includes(projectName))
44
- );
45
- const removedCount = initialCount - globalKeys.length;
46
-
47
- // 写回全局配置
48
- fs.writeFileSync(globalKeysPath, JSON.stringify(globalKeys, null, 4));
49
- console.log(`🗑️ 卸载完成! 移除了 ${removedCount} 个项目快捷键`);
70
+ // 移除本项目快捷键
71
+ const before = globalKeys.length;
72
+ globalKeys = globalKeys.filter(item => {
73
+ if (item.when && typeof item.when === 'string') {
74
+ return !item.when.includes(projectName);
75
+ }
76
+ return true;
77
+ });
78
+ const removed = before - globalKeys.length;
79
+
80
+ // 写回 或 删除空文件
81
+ if (globalKeys.length === 0) {
82
+ fs.unlinkSync(editor.path);
83
+ console.log(` 🗑️ 配置已清空,已删除文件`);
84
+ } else {
85
+ fs.writeFileSync(editor.path, JSON.stringify(globalKeys, null, 4));
86
+ }
87
+ console.log(` ✅ ${editor.name} 卸载完成! 移除 ${removed} 个快捷键`);
88
+
89
+ if (removed === 0) {
90
+ console.log(` ℹ️ 没有找到本项目的快捷键`);
91
+ }
92
+
50
93
  return true;
51
94
 
52
95
  } catch (error) {
53
- console.log('💥 卸载过程中发生错误:', error.message);
96
+ console.log(` ❌ ${editor.name} 失败: ${error.message}`);
97
+ return false;
98
+ }
99
+ }
100
+
101
+ // ============================================================
102
+ // 主入口
103
+ // ============================================================
104
+ function uninstallProjectKeys() {
105
+ try {
106
+ console.log('='.repeat(56));
107
+ console.log(' 🗑️ 项目快捷键卸载工具 v2.2');
108
+ console.log('='.repeat(56));
109
+
110
+ // 项目名称
111
+ const projectName = path.basename(process.cwd());
112
+ console.log(`📁 项目: ${projectName}`);
113
+
114
+ // 检测编辑器
115
+ const editors = getEditorPaths();
116
+ if (editors.length === 0) {
117
+ console.log('\n⚠️ 未检测到已安装的编辑器');
118
+ console.log('💡 支持: VS Code, CodeBuddy CN, CodeBuddy, Cursor');
119
+ return false;
120
+ }
121
+
122
+ console.log(`\n🔍 检测到 ${editors.length} 个编辑器:`);
123
+ editors.forEach(e => console.log(` ✅ ${e.name}`));
124
+
125
+ // 仅处理存在配置文件的编辑器
126
+ const withConfig = editors.filter(e => fs.existsSync(e.path));
127
+ const noConfig = editors.filter(e => !fs.existsSync(e.path));
128
+
129
+ if (noConfig.length > 0) {
130
+ console.log(`\nℹ️ ${noConfig.length} 个编辑器无配置文件,将跳过:`);
131
+ noConfig.forEach(e => console.log(` - ${e.name}`));
132
+ }
133
+
134
+ if (withConfig.length === 0) {
135
+ console.log('\nℹ️ 所有编辑器都无配置文件,无需卸载');
136
+ return true;
137
+ }
138
+
139
+ // 卸载
140
+ console.log('\n🚀 开始卸载...');
141
+ console.log('-'.repeat(56));
142
+
143
+ let success = 0;
144
+ let totalRemoved = 0;
145
+
146
+ // 先统计每个编辑器中要移除的快捷键数量
147
+ withConfig.forEach(e => {
148
+ try {
149
+ const content = fs.readFileSync(e.path, 'utf8');
150
+ const keys = JSON.parse(content);
151
+ if (Array.isArray(keys)) {
152
+ const count = keys.filter(item =>
153
+ item.when && typeof item.when === 'string' && item.when.includes(projectName)
154
+ ).length;
155
+ if (count > 0) {
156
+ console.log(` 📋 ${e.name}: 将移除 ${count} 个快捷键`);
157
+ }
158
+ }
159
+ } catch (_) { /* ignore */ }
160
+ });
161
+
162
+ // 执行卸载
163
+ withConfig.forEach(e => {
164
+ if (uninstallFromEditor(e, projectName)) success++;
165
+ });
166
+
167
+ // 总结
168
+ console.log('\n' + '='.repeat(56));
169
+ console.log(`🎉 卸载完成! 处理: ${success}/${withConfig.length} 个编辑器`);
170
+ console.log('='.repeat(56));
171
+ console.log('💡 可能需要重启编辑器或执行 "Reload Window" 才能生效');
172
+
173
+ return success === withConfig.length;
174
+
175
+ } catch (error) {
176
+ console.log(`💥 未知错误: ${error.message}`);
177
+ console.error(error);
54
178
  return false;
55
179
  }
56
180
  }
57
181
 
58
- // 执行卸载
182
+ // ============================================================
183
+ // 执行
184
+ // ============================================================
59
185
  if (require.main === module) {
60
186
  uninstallProjectKeys();
61
187
  }
62
188
 
63
189
  module.exports = uninstallProjectKeys;
64
190
 
65
- //node a_tools/a_node/Tools/uninstall-keys.js
191
+ // 使用方法:
192
+ // node a_tools/a_node/Tools/uninstall-keys.js
193
+ // 支持的编辑器:
194
+ // VS Code / CodeBuddy CN / CodeBuddy / Cursor
195
+ // 自动检测并移除所有编辑器中的本项目快捷键
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
6
- <title>BAT脚本管理器 - 远程执行控制台</title>
6
+ <title>盟约传奇 一键工具</title>
7
7
  <style>
8
8
  * {
9
9
  box-sizing: border-box;
@@ -594,7 +594,7 @@
594
594
  let localTaskRunning = false; // 本地发起任务是否在执行
595
595
  let pendingEndTimer = null;
596
596
 
597
- const WS_URL = `ws://${window.location.hostname}:8080`;
597
+ const WS_URL = `ws://${window.location.hostname}:9964`;
598
598
 
599
599
  // DOM 元素
600
600
  const authOverlay = document.getElementById('authOverlay');
@@ -1,42 +1,26 @@
1
1
  [
2
2
  {
3
- "id": "1776933313049",
4
- "name": "打配置",
5
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-csvcfg.bat",
3
+ "id": "1782186651373",
4
+ "name": "一键配置",
5
+ "path": "G:\\MengYueChuanQi996\\Project\\996M2_Client\\a_tools\\a_node\\run-csvcfg.bat",
6
6
  "args": "",
7
- "addedBy": "qwe1234",
8
- "addedAt": "2026-04-23T08:35:13.049Z"
9
- },
10
- {
11
- "id": "1776937917012",
12
- "name": "同步协议",
13
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-sync.bat",
14
- "args": "",
15
- "addedBy": "qqww123",
16
- "addedAt": "2026-04-23T09:51:57.012Z"
17
- },
18
- {
19
- "id": "1777254823830",
20
- "name": "启动客服端",
21
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-client.bat",
22
- "args": "",
23
- "addedBy": "yrc001",
24
- "addedAt": "2026-04-27T01:53:43.830Z"
7
+ "addedBy": "admin",
8
+ "addedAt": "2026-06-23T03:50:51.373Z"
25
9
  },
26
10
  {
27
- "id": "1777254878031",
28
- "name": "自动生成代码",
29
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-autoCode.bat",
11
+ "id": "1782186676214",
12
+ "name": "一键协议",
13
+ "path": "G:/MengYueChuanQi996/Project/996M2_Client/a_tools/a_node/run-sync.bat",
30
14
  "args": "",
31
- "addedBy": "yrc001",
32
- "addedAt": "2026-04-27T01:54:38.031Z"
15
+ "addedBy": "admin",
16
+ "addedAt": "2026-06-23T03:51:16.214Z"
33
17
  },
34
18
  {
35
- "id": "1781243927262",
36
- "name": "9963工程(📁 G:/NiePanChuanQi/Project)SVN更新",
37
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-svn.bat",
19
+ "id": "1782186725524",
20
+ "name": "9964工程(📁 G:/MengYueChuanQi996/Project)SVN更新",
21
+ "path": "G:/MengYueChuanQi996/Project/996M2_Client/a_tools/a_node/run-svn.bat",
38
22
  "args": "",
39
23
  "addedBy": "admin",
40
- "addedAt": "2026-06-12T05:58:47.262Z"
24
+ "addedAt": "2026-06-23T03:52:05.524Z"
41
25
  }
42
26
  ]
@@ -7,7 +7,7 @@ const crypto = require('crypto');
7
7
  const http = require('http');
8
8
  const os = require('os');
9
9
 
10
- const PORT = 8080;
10
+ const PORT = 9964;
11
11
  const USER_FILE = path.join(__dirname, 'users.json');
12
12
 
13
13
  const onlineUsers = new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yangrunchi/a_6",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "996M2 客户端 Node.js 工具集 — 协议同步、自动生成代码、CSV配置、SVN管理、BAT脚本管理器",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -1,4 +0,0 @@
1
- @echo off
2
- cd /d "%~dp0"
3
- node server.js
4
- pause