聚水潭商品打印+

☑️辅助码;☑️扫码直接打印;☑️查看库存及订单信息;🖱设置焦点到输入框

  1. // ==UserScript==
  2. // @name 聚水潭商品打印+
  3. // @namespace http://tampermonkey.net/
  4. // @version 4.5
  5. // @description ☑️辅助码;☑️扫码直接打印;☑️查看库存及订单信息;🖱设置焦点到输入框
  6. // @author ShiShiBits
  7. // @match https://www.erp321.com/app/wms/print/V2/SkuPrintNV.aspx
  8. // @grant none
  9. // @run-at document-idle
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // ================= 专业配置 =================
  16. const CONFIG = {
  17. // 复选框配置
  18. checkboxes: [
  19. { selector: '#skuInputPrint', expected: true },
  20. { selector: '#printMode', expected: true },
  21. { selector: '#sku_id', expected: false },
  22. { selector: '#multi_other_code', expected: true }
  23. ],
  24.  
  25. // 输入框配置
  26. inputs: [
  27. { selector: '#multiSearchCode', needFocus: true }
  28. ],
  29.  
  30. // 系统参数
  31. maxRetry: 30, // 最大重试次数
  32. checkInterval: 400, // 检查间隔(ms)
  33. delay: 150 // 操作延迟(ms)
  34. };
  35.  
  36. // ================= 状态管理器 =================
  37. let retryCount = 0;
  38. const successMap = new Map();
  39. const focusMap = new Map();
  40.  
  41. // ================= 核心控制引擎 =================
  42. const FormController = {
  43. init() {
  44. this.setupObserver();
  45. this.initialCheck();
  46. this.startRetryMechanism();
  47. },
  48.  
  49. setupObserver() {
  50. new MutationObserver(mutations => {
  51. mutations.forEach(mutation => {
  52. if (mutation.type === 'childList') {
  53. this.handleNewNodes(mutation.addedNodes);
  54. }
  55. });
  56. }).observe(document, {
  57. childList: true,
  58. subtree: true,
  59. attributes: true,
  60. attributeFilter: ['id', 'checked', 'class']
  61. });
  62. },
  63.  
  64. initialCheck() {
  65. setTimeout(() => {
  66. this.batchCheck();
  67. this.processInputs();
  68. }, CONFIG.delay * 2);
  69. },
  70.  
  71. batchCheck() {
  72. CONFIG.checkboxes.forEach(config => {
  73. if (!successMap.get(config.selector)) {
  74. this.processCheckbox(config);
  75. }
  76. });
  77. },
  78.  
  79. processInputs() {
  80. CONFIG.inputs.forEach(inputConfig => {
  81. if (!focusMap.get(inputConfig.selector)) {
  82. this.focusInput(inputConfig);
  83. }
  84. });
  85. },
  86.  
  87. handleNewNodes(nodes) {
  88. nodes.forEach(node => {
  89. if (node.nodeType === 1) {
  90. // 处理复选框
  91. CONFIG.checkboxes.forEach(config => {
  92. if (node.matches(config.selector)) {
  93. this.processCheckbox(config);
  94. }
  95. });
  96.  
  97. // 处理输入框
  98. CONFIG.inputs.forEach(inputConfig => {
  99. if (node.matches(inputConfig.selector)) {
  100. this.focusInput(inputConfig);
  101. }
  102. });
  103. }
  104. });
  105. },
  106.  
  107. // ======== 修复的复选框处理逻辑 ========
  108. processCheckbox(config) {
  109. try {
  110. const { selector, expected } = config;
  111. const checkbox = document.querySelector(selector);
  112.  
  113. // 元素存在性验证
  114. if (!checkbox) {
  115. successMap.set(selector, false);
  116. return;
  117. }
  118.  
  119. // 状态验证
  120. if (checkbox.checked === expected) {
  121. if (!successMap.get(selector)) {
  122. console.log(`[CHECKBOX] ${selector} 状态已正确`);
  123. successMap.set(selector, true);
  124. }
  125. return;
  126. }
  127.  
  128. // 执行操作流程
  129. this.triggerNativeAction(checkbox, expected);
  130. this.scheduleStateUpdate(checkbox, expected);
  131. this.finalVerification(checkbox, config);
  132.  
  133. } catch (error) {
  134. console.error(`[ERROR] 处理 ${config.selector} 时发生异常:`, error);
  135. successMap.set(config.selector, false);
  136. }
  137. },
  138.  
  139. triggerNativeAction(checkbox, expected) {
  140. // 确保状态变化
  141. if (checkbox.checked !== expected) {
  142. checkbox.click();
  143. }
  144.  
  145. // 触发必要事件
  146. ['click', 'change', 'input'].forEach(type => {
  147. checkbox.dispatchEvent(new Event(type, { bubbles: true }));
  148. });
  149. },
  150.  
  151. scheduleStateUpdate(checkbox, expected) {
  152. setTimeout(() => {
  153. if (checkbox.checked !== expected) {
  154. checkbox.checked = expected;
  155. this.triggerFrameworkEvents(checkbox);
  156. }
  157. }, CONFIG.delay);
  158. },
  159.  
  160. triggerFrameworkEvents(checkbox) {
  161. // React支持
  162. const reactProps = Object.keys(checkbox).find(k => k.startsWith('__reactProps'));
  163. if (reactProps?.onChange) {
  164. const event = new Event('change', { bubbles: true });
  165. Object.defineProperty(event, 'target', { value: checkbox });
  166. reactProps.onChange(event);
  167. }
  168.  
  169. // Vue支持
  170. const vueProps = Object.keys(checkbox).find(k => k.startsWith('__vue__'));
  171. if (vueProps?.$emit) {
  172. vueProps.$emit('input', checkbox.checked);
  173. vueProps.$emit('change', checkbox.checked);
  174. }
  175. },
  176.  
  177. finalVerification(checkbox, config) {
  178. setTimeout(() => {
  179. const success = checkbox.checked === config.expected;
  180. successMap.set(config.selector, success);
  181. console.log(`[CHECKBOX] ${config.selector}: ${success ? '成功 ✔️' : '失败 ✖️'}`);
  182.  
  183. // 失败时自动重试
  184. if (!success && retryCount < CONFIG.maxRetry) {
  185. this.processCheckbox(config);
  186. }
  187. }, CONFIG.delay * 2);
  188. },
  189.  
  190. // 输入框聚焦方法
  191. focusInput(inputConfig) {
  192. try {
  193. const { selector, needFocus } = inputConfig;
  194. if (!needFocus) return;
  195.  
  196. const input = document.querySelector("#skustock");
  197. if (!input) return;
  198.  
  199. input.focus({ preventScroll: true });
  200. this.triggerFrameworkEvents(input);
  201. focusMap.set(selector, true);
  202. console.log(`[FOCUS] ${selector} 聚焦成功`);
  203.  
  204. // 修复方法调用方式
  205. this.addFocusProtection(input);
  206. } catch (error) {
  207. console.error(`[FOCUS-ERROR] ${inputConfig.selector} 处理异常:`, error);
  208. }
  209. },
  210.  
  211. // 新增焦点保护方法 (修复位置)
  212. addFocusProtection(input) {
  213. // 保存原始方法引用
  214. const originalBlur = input.blur.bind(input);
  215.  
  216. // 重写blur方法
  217. input.blur = (...args) => {
  218. console.log('[FOCUS-PROTECT] 检测到失焦操作');
  219. // 取消默认行为
  220. // return false;
  221. return originalBlur(...args);
  222. };
  223.  
  224. // 使用箭头函数保持this指向
  225. const checkFocus = () => {
  226. if (document.activeElement !== input) {
  227. console.log('[FOCUS-CHECK] 重新聚焦输入框');
  228. input.focus({ preventScroll: true });
  229. }
  230. };
  231.  
  232. // 添加自动重聚焦定时器
  233. let checkCount = 0;
  234. const timer = setInterval(() => {
  235. if (checkCount++ < 5) {
  236. checkFocus();
  237. } else {
  238. clearInterval(timer);
  239. console.log('[FOCUS-PROTECT] 结束自动聚焦保护');
  240. input.blur = originalBlur; // 恢复原始方法
  241. }
  242. }, 2000);
  243. },
  244.  
  245. startRetryMechanism() {
  246. const timer = setInterval(() => {
  247. if (retryCount++ < CONFIG.maxRetry) {
  248. this.batchCheck();
  249. this.processInputs();
  250. } else {
  251. clearInterval(timer);
  252. console.log('[SYSTEM] 终止重试,最终状态:', {
  253. checkboxes: Array.from(successMap),
  254. inputs: Array.from(focusMap)
  255. });
  256. }
  257. }, CONFIG.checkInterval);
  258. }
  259. };
  260.  
  261. // 获取元素并设置宽度和高度为500px
  262. var spModeSkupicElement = document.getElementById("sp_mode_skupic");
  263. if (spModeSkupicElement) {
  264. spModeSkupicElement.style.width = "500px";
  265. spModeSkupicElement.style.height = "500px";
  266. }
  267.  
  268. // ================= 启动系统 =================
  269. FormController.init();
  270.  
  271. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址