Extension for ui.appen.com.cn

A new extension

Size

6.6 KB

Version

1.0.3

Created

Apr 5, 2026

Updated

7 days ago

1// ==UserScript==
2// @name		Extension for ui.appen.com.cn
3// @description		A new extension
4// @version		1.0.3
5// @match		https://*.ui.appen.com.cn/*
6// @icon		https://ui.appen.com.cn/public/assets/favicon.png
7// ==/UserScript==
8(function() {
9    'use strict';
10    
11    // 半角标点符号到全角标点符号的映射
12    const punctuationMap = {
13        ',': ',',
14        '.': '。',
15        '?': '?',
16        '!': '!',
17        ':': ':',
18        ';': ';',
19        '(': '(',
20        ')': ')',
21        '[': '【',
22        ']': '】',
23        '{': '{',
24        '}': '}',
25        '"': '"',
26        "'": ''',
27        '<': '〈',
28        '>': '〉',
29        '&': '&',
30        '%': '%',
31        '$': '$',
32        '#': '#',
33        '@': '@',
34        '~': '~',
35        '`': '`',
36        '^': '^',
37        '*': '*',
38        '_': '_',
39        '-': '-',
40        '+': '+',
41        '=': '=',
42        '|': '|',
43        '\\': '\',
44        '/': '/'
45    };
46    
47    // 转换函数:将半角标点转换为全角
48    function convertToFullWidth(text) {
49        let result = '';
50        for (let i = 0; i < text.length; i++) {
51            const char = text[i];
52            if (punctuationMap[char]) {
53                result += punctuationMap[char];
54            } else {
55                result += char;
56            }
57        }
58        return result;
59    }
60    
61    // 处理输入事件
62    function handleInput(event) {
63        const element = event.target;
64        
65        // 只处理文本输入框和文本区域
66        if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.isContentEditable) {
67            const cursorPos = element.selectionStart || 0;
68            const originalValue = element.value || element.textContent || '';
69            const convertedValue = convertToFullWidth(originalValue);
70            
71            // 只有当值发生改变时才更新
72            if (originalValue !== convertedValue) {
73                console.log('标点符号转换:', originalValue, '->', convertedValue);
74                
75                if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
76                    element.value = convertedValue;
77                    // 尝试保持光标位置
78                    try {
79                        element.setSelectionRange(cursorPos, cursorPos);
80                    } catch (e) {
81                        // 忽略错误
82                    }
83                } else if (element.isContentEditable) {
84                    element.textContent = convertedValue;
85                }
86            }
87        }
88    }
89    
90    // 使用 MutationObserver 监听 DOM 变化
91    function observeDOM() {
92        const observer = new MutationObserver((mutations) => {
93            // 为每个新增的节点添加事件监听
94            mutations.forEach((mutation) => {
95                mutation.addedNodes.forEach((node) => {
96                    if (node.nodeType === Node.ELEMENT_NODE) {
97                        // 为新增元素添加输入监听
98                        if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA') {
99                            node.addEventListener('input', handleInput);
100                        }
101                        // 查找子元素中的输入框
102                        const inputs = node.querySelectorAll ? node.querySelectorAll('input, textarea, [contenteditable="true"]') : [];
103                        inputs.forEach((input) => {
104                            input.addEventListener('input', handleInput);
105                        });
106                    }
107                });
108            });
109        });
110        
111        observer.observe(document.body, {
112            childList: true,
113            subtree: true
114        });
115        
116        console.log('标点符号自动转换扩展已启动');
117    }
118    
119    // 为现有的输入框添加监听
120    function addListenersToExistingInputs() {
121        const inputs = document.querySelectorAll('input, textarea, [contenteditable="true"]');
122        inputs.forEach((input) => {
123            input.addEventListener('input', handleInput);
124        });
125        
126        // 尝试监听 iframe 内的内容
127        setTimeout(() => {
128            const iframes = document.querySelectorAll('iframe');
129            iframes.forEach((iframe) => {
130                try {
131                    if (iframe.contentDocument) {
132                        const iframeInputs = iframe.contentDocument.querySelectorAll('input, textarea, [contenteditable="true"]');
133                        iframeInputs.forEach((input) => {
134                            input.addEventListener('input', handleInput);
135                        });
136                        
137                        // 也监听 iframe 内的 DOM 变化
138                        const iframeObserver = new MutationObserver((mutations) => {
139                            mutations.forEach((mutation) => {
140                                mutation.addedNodes.forEach((node) => {
141                                    if (node.nodeType === Node.ELEMENT_NODE) {
142                                        if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA') {
143                                            node.addEventListener('input', handleInput);
144                                        }
145                                        const newInputs = node.querySelectorAll ? node.querySelectorAll('input, textarea, [contenteditable="true"]') : [];
146                                        newInputs.forEach((input) => {
147                                            input.addEventListener('input', handleInput);
148                                        });
149                                    }
150                                });
151                            });
152                        });
153                        
154                        iframeObserver.observe(iframe.contentDocument.body, {
155                            childList: true,
156                            subtree: true
157                        });
158                    }
159                } catch (e) {
160                    console.log('无法访问iframe内容(可能是跨域限制):', e.message);
161                }
162            });
163        }, 1000);
164    }
165    
166    // 初始化
167    function init() {
168        console.log('初始化标点符号自动转换扩展...');
169        addListenersToExistingInputs();
170        observeDOM();
171    }
172    
173    // 等待页面加载完成
174    if (document.readyState === 'loading') {
175        document.addEventListener('DOMContentLoaded', init);
176    } else {
177        init();
178    }
179    
180    // 同时也监听页面完全加载事件
181    window.addEventListener('load', () => {
182        setTimeout(init, 500);
183    });
184})();