ascript 1.3.27__py3-none-win_amd64.whl

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.
Files changed (177) hide show
  1. ascript/__init__.py +8 -0
  2. ascript/hooks/__init__.py +0 -0
  3. ascript/hooks/hook-ascript.py +2 -0
  4. ascript/windows/__init__.py +29 -0
  5. ascript/windows/daos/__init__.py +0 -0
  6. ascript/windows/daos/screen.py +143 -0
  7. ascript/windows/hardware/__init__.py +5 -0
  8. ascript/windows/hardware/keyboard.py +279 -0
  9. ascript/windows/hardware/logitech_driver.py +179 -0
  10. ascript/windows/hardware/mouse.py +308 -0
  11. ascript/windows/license/__init__.py +16 -0
  12. ascript/windows/license/achttp.cp310-win_amd64.pyd +0 -0
  13. ascript/windows/license/achttp.cp311-win_amd64.pyd +0 -0
  14. ascript/windows/license/achttp.cp312-win_amd64.pyd +0 -0
  15. ascript/windows/license/achttp.cp313-win_amd64.pyd +0 -0
  16. ascript/windows/license/achttp.cp314-win_amd64.pyd +0 -0
  17. ascript/windows/license/achttp.cp38-win_amd64.pyd +0 -0
  18. ascript/windows/license/achttp.cp39-win_amd64.pyd +0 -0
  19. ascript/windows/media/__init__.py +0 -0
  20. ascript/windows/resources/__init__.py +0 -0
  21. ascript/windows/resources/libs/logitech/x64/LogitechGkeyEnginesWrapper.dll +0 -0
  22. ascript/windows/resources/libs/logitech/x86/LogitechGkeyEnginesWrapper.dll +0 -0
  23. ascript/windows/resources/templates/__init__.py +0 -0
  24. ascript/windows/resources/templates/__init__py.win.template +51 -0
  25. ascript/windows/resources/templates/build.as.win.template +14 -0
  26. ascript/windows/resources/templates/build.py +71 -0
  27. ascript/windows/resources/templates/logo_windows.ico +0 -0
  28. ascript/windows/resources/templates/windows/main.py +50 -0
  29. ascript/windows/resources/templates/windows/pyproject.toml +44 -0
  30. ascript/windows/resources/templates/windows/res/img/logo.ico +0 -0
  31. ascript/windows/screen/__init__.py +13 -0
  32. ascript/windows/screen/as_cv.py +382 -0
  33. ascript/windows/screen/canny.py +128 -0
  34. ascript/windows/screen/code_scanner.py +72 -0
  35. ascript/windows/screen/color_algorithms.py +277 -0
  36. ascript/windows/screen/find_colors.py +251 -0
  37. ascript/windows/screen/find_images.py +217 -0
  38. ascript/windows/screen/ocr/__init__.py +4 -0
  39. ascript/windows/screen/ocr/ocr.py +223 -0
  40. ascript/windows/screen/ocr/rapidocr_hook.py +301 -0
  41. ascript/windows/screen/ocrx.py +169 -0
  42. ascript/windows/screen/screen_core.py +139 -0
  43. ascript/windows/store/__init__.py +21 -0
  44. ascript/windows/system/__init__.py +8 -0
  45. ascript/windows/system/device.py +355 -0
  46. ascript/windows/system/easy_print.py +115 -0
  47. ascript/windows/system/env.py +492 -0
  48. ascript/windows/system/exception/__init__.py +1 -0
  49. ascript/windows/system/key_value.py +145 -0
  50. ascript/windows/system/pip.py +175 -0
  51. ascript/windows/system/r.py +165 -0
  52. ascript/windows/system/runtime.py +62 -0
  53. ascript/windows/tools/__init__.py +27 -0
  54. ascript/windows/tools/__main__.py +21 -0
  55. ascript/windows/tools/action.json +33 -0
  56. ascript/windows/tools/action.py +168 -0
  57. ascript/windows/tools/colors_tool.py +391 -0
  58. ascript/windows/tools/config.py +26 -0
  59. ascript/windows/tools/dumptool.py +18 -0
  60. ascript/windows/tools/eel_api.py +495 -0
  61. ascript/windows/tools/gpplug/__init__.py +0 -0
  62. ascript/windows/tools/gpplug/plug.py +70 -0
  63. ascript/windows/tools/mouse_catch.py +168 -0
  64. ascript/windows/tools/plug_manager.py +38 -0
  65. ascript/windows/tools/tool_api.py +906 -0
  66. ascript/windows/tools/tool_window.py +56 -0
  67. ascript/windows/tools/uia_worker.py +365 -0
  68. ascript/windows/tools/web/app_store_window.html +481 -0
  69. ascript/windows/tools/web/colors.html +532 -0
  70. ascript/windows/tools/web/css/screen.css +1342 -0
  71. ascript/windows/tools/web/css/viewtree.css +357 -0
  72. ascript/windows/tools/web/flot_control.html +195 -0
  73. ascript/windows/tools/web/img/ico/favicon.png +0 -0
  74. ascript/windows/tools/web/img/ico/paintpalette.png +0 -0
  75. ascript/windows/tools/web/img/svg/find_colors.svg +1 -0
  76. ascript/windows/tools/web/img/svg/find_images.svg +1 -0
  77. ascript/windows/tools/web/img/svg/illustration-6.svg +89 -0
  78. ascript/windows/tools/web/img/svg/img_default.svg +1 -0
  79. ascript/windows/tools/web/img/svg/ocr.svg +1 -0
  80. ascript/windows/tools/web/js/screen/colors.js +466 -0
  81. ascript/windows/tools/web/js/screen/gp_plug.js +108 -0
  82. ascript/windows/tools/web/js/screen/image_mouse.js +464 -0
  83. ascript/windows/tools/web/js/screen/img_view.js +558 -0
  84. ascript/windows/tools/web/js/screen/plug.js +246 -0
  85. ascript/windows/tools/web/js/screen/screen.js +690 -0
  86. ascript/windows/tools/web/js/screen/screen_api.js +778 -0
  87. ascript/windows/tools/web/js/screen/screen_maker.js +10 -0
  88. ascript/windows/tools/web/js/utils/map.js +73 -0
  89. ascript/windows/tools/web/js/utils/upload.js +157 -0
  90. ascript/windows/tools/web/js/viewtree/niv_js.js +27 -0
  91. ascript/windows/tools/web/js/viewtree/vtree.js +1510 -0
  92. ascript/windows/tools/web/libs/bootstrap/css/bootstrap.min.css +6 -0
  93. ascript/windows/tools/web/libs/bootstrap/js/bootstrap.bundle.min.js +7 -0
  94. ascript/windows/tools/web/libs/bootstrap-icons/0-circle.svg +4 -0
  95. ascript/windows/tools/web/libs/bootstrap-icons/0-square.svg +4 -0
  96. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.css +2078 -0
  97. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.json +2052 -0
  98. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.min.css +5 -0
  99. ascript/windows/tools/web/libs/bootstrap-icons/font/bootstrap-icons.scss +2090 -0
  100. ascript/windows/tools/web/libs/bootstrap-icons/font/fonts/bootstrap-icons.woff +0 -0
  101. ascript/windows/tools/web/libs/bootstrap-icons/font/fonts/bootstrap-icons.woff2 +0 -0
  102. ascript/windows/tools/web/libs/feather-icons/dist/feather.min.js +13 -0
  103. ascript/windows/tools/web/libs/feather-icons/dist/icons.json +1 -0
  104. ascript/windows/tools/web/libs/jquery/core.js +399 -0
  105. ascript/windows/tools/web/libs/jquery/jquery.js +10598 -0
  106. ascript/windows/tools/web/libs/jquery/jquery.min.js +4 -0
  107. ascript/windows/tools/web/libs/jquery/jquery.min.js.zip +0 -0
  108. ascript/windows/tools/web/libs/jquery/jquery.slim.js +8495 -0
  109. ascript/windows/tools/web/libs/jquery/jquery.slim.min.js +2 -0
  110. ascript/windows/tools/web/libs/jquery-menu/jquery.contextMenu.js +2134 -0
  111. ascript/windows/tools/web/libs/jquery-menu/jquery.contextMenu.min.css +16 -0
  112. ascript/windows/tools/web/libs/jquery-zTree/css/zTreeStyle.css +97 -0
  113. ascript/windows/tools/web/libs/jquery-zTree/img/diy/1_close.png +0 -0
  114. ascript/windows/tools/web/libs/jquery-zTree/img/diy/1_open.png +0 -0
  115. ascript/windows/tools/web/libs/jquery-zTree/img/diy/2.png +0 -0
  116. ascript/windows/tools/web/libs/jquery-zTree/img/diy/3.png +0 -0
  117. ascript/windows/tools/web/libs/jquery-zTree/img/diy/4.png +0 -0
  118. ascript/windows/tools/web/libs/jquery-zTree/img/diy/5.png +0 -0
  119. ascript/windows/tools/web/libs/jquery-zTree/img/diy/6.png +0 -0
  120. ascript/windows/tools/web/libs/jquery-zTree/img/diy/7.png +0 -0
  121. ascript/windows/tools/web/libs/jquery-zTree/img/diy/8.png +0 -0
  122. ascript/windows/tools/web/libs/jquery-zTree/img/diy/9.png +0 -0
  123. ascript/windows/tools/web/libs/jquery-zTree/img/line_conn.gif +0 -0
  124. ascript/windows/tools/web/libs/jquery-zTree/img/loading.gif +0 -0
  125. ascript/windows/tools/web/libs/jquery-zTree/img/tree-node-btn.png +0 -0
  126. ascript/windows/tools/web/libs/jquery-zTree/img/zTreeStandard.gif +0 -0
  127. ascript/windows/tools/web/libs/jquery-zTree/img/zTreeStandard.png +0 -0
  128. ascript/windows/tools/web/libs/jquery-zTree/js/jquery.ztree.all.min.js +3 -0
  129. ascript/windows/tools/web/libs/treeview/css/jquery.treeview.css +79 -0
  130. ascript/windows/tools/web/libs/treeview/img/file.png +0 -0
  131. ascript/windows/tools/web/libs/treeview/img/ico_loading.png +0 -0
  132. ascript/windows/tools/web/libs/treeview/img/icon4.png +0 -0
  133. ascript/windows/tools/web/libs/treeview/img/icon5.png +0 -0
  134. ascript/windows/tools/web/libs/treeview/img/icon6.png +0 -0
  135. ascript/windows/tools/web/libs/treeview/img/py.png +0 -0
  136. ascript/windows/tools/web/libs/treeview/img/treeview-black-line.gif +0 -0
  137. ascript/windows/tools/web/libs/treeview/img/treeview-black.gif +0 -0
  138. ascript/windows/tools/web/libs/treeview/img/treeview-default-line.gif +0 -0
  139. ascript/windows/tools/web/libs/treeview/img/treeview-default.gif +0 -0
  140. ascript/windows/tools/web/libs/treeview/img/treeview-famfamfam-line.gif +0 -0
  141. ascript/windows/tools/web/libs/treeview/img/treeview-famfamfam.gif +0 -0
  142. ascript/windows/tools/web/libs/treeview/img/treeview-gray-line.gif +0 -0
  143. ascript/windows/tools/web/libs/treeview/img/treeview-gray.gif +0 -0
  144. ascript/windows/tools/web/libs/treeview/img/treeview-red-line.gif +0 -0
  145. ascript/windows/tools/web/libs/treeview/img/treeview-red.gif +0 -0
  146. ascript/windows/tools/web/libs/treeview/js/jquery.treeview.edit.js +37 -0
  147. ascript/windows/tools/web/libs/treeview/js/jquery.treeview.js +250 -0
  148. ascript/windows/tools/web/license_window.html +255 -0
  149. ascript/windows/tools/web/plugs/a.html +653 -0
  150. ascript/windows/tools/web/plugs/demo.html +52 -0
  151. ascript/windows/tools/web/plugs/find_colors.html +629 -0
  152. ascript/windows/tools/web/plugs/find_images.html +699 -0
  153. ascript/windows/tools/web/plugs/rapidocr.html +954 -0
  154. ascript/windows/tools/web/vtree.html +496 -0
  155. ascript/windows/tools/webview/assets/index-HymBPl-I.css +1 -0
  156. ascript/windows/tools/webview/assets/index-PqA_m8tL.js +17 -0
  157. ascript/windows/tools/webview/index.html +13 -0
  158. ascript/windows/ui/__init__.py +6 -0
  159. ascript/windows/ui/app_store_window.py +272 -0
  160. ascript/windows/ui/draw_window.py +231 -0
  161. ascript/windows/ui/flot_test.py +297 -0
  162. ascript/windows/ui/flot_window.py +488 -0
  163. ascript/windows/ui/license_window.py +111 -0
  164. ascript/windows/ui/web_window.py +466 -0
  165. ascript/windows/utils/__init__.py +0 -0
  166. ascript/windows/utils/node_utils.py +20 -0
  167. ascript/windows/utils/screen_utils.py +280 -0
  168. ascript/windows/window/Selector.py +1015 -0
  169. ascript/windows/window/Window.py +747 -0
  170. ascript/windows/window/__init__.py +5 -0
  171. ascript/windows/window/launcher.py +213 -0
  172. ascript/windows/window/uia_runtime.py +26 -0
  173. ascript-1.3.27.dist-info/METADATA +41 -0
  174. ascript-1.3.27.dist-info/RECORD +177 -0
  175. ascript-1.3.27.dist-info/WHEEL +5 -0
  176. ascript-1.3.27.dist-info/entry_points.txt +2 -0
  177. ascript-1.3.27.dist-info/top_level.txt +1 -0
@@ -0,0 +1,481 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN" style="background-color: #1e1e1e !important;">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="color-scheme" content="dark">
7
+ <title>AScript Store</title>
8
+ <link href="./libs/bootstrap/css/bootstrap.min.css" rel="stylesheet">
9
+ <style>
10
+ :root {
11
+ --vs-bg-main: #1e1e1e;
12
+ --vs-bg-side: #252526;
13
+ --vs-border: #333333;
14
+ --vs-accent: #007acc;
15
+ --vs-text: #888888;
16
+ --vs-text-light: #cccccc;
17
+ --vs-input-bg: #3c3c3c;
18
+ --vs-error: #f48771;
19
+ --vs-stop: #e51400;
20
+ }
21
+
22
+ html, body {
23
+ height: 100%; margin: 0; padding: 0;
24
+ background-color: #1e1e1e !important;
25
+ color: var(--vs-text-light);
26
+ font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
27
+ overflow: hidden; display: flex; flex-direction: column;
28
+ user-select: none;
29
+ }
30
+
31
+ /* --- 加载层 --- */
32
+ #init-loader {
33
+ position: fixed; top: 0; left: 0; right: 0; bottom: 0;
34
+ background-color: #1e1e1e;
35
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
36
+ z-index: 99999;
37
+ transition: opacity 0.3s ease-out;
38
+ }
39
+ .loader-text { margin-top: 15px; color: #666; font-size: 11px; letter-spacing: 2px; }
40
+
41
+ .spinner {
42
+ width: 22px; height: 22px;
43
+ border: 2px solid rgba(255, 255, 255, 0.15);
44
+ border-top-color: #ffffff;
45
+ border-radius: 50%;
46
+ animation: spin 0.8s linear infinite;
47
+ }
48
+ .spinner-sm { width: 14px; height: 14px; border-width: 2px; margin-right: 6px; }
49
+ @keyframes spin { to { transform: rotate(360deg); } }
50
+
51
+ /* --- 首页样式 --- */
52
+ #home-page, #detail-page {
53
+ display: none; height: 100%;
54
+ background-color: #1e1e1e;
55
+ }
56
+ #home-page { flex-direction: column; align-items: center; justify-content: center; }
57
+ .search-wrapper { width: 520px; text-align: center; }
58
+ .logo { font-size: 32px; font-weight: 300; margin-bottom: 30px; letter-spacing: 2px; color: #eee; }
59
+ .logo b { color: var(--vs-accent); font-weight: 600; }
60
+
61
+ /* 搜索框基础样式 */
62
+ .search-bar {
63
+ display: flex;
64
+ background: var(--vs-input-bg);
65
+ border: 1px solid var(--vs-border);
66
+ border-radius: 4px; padding: 4px;
67
+ transition: border-color 0.2s;
68
+ }
69
+ /* 空输入时的红圈提醒 */
70
+ .search-bar.error { border-color: var(--vs-error) !important; }
71
+ .search-bar:focus-within { border-color: var(--vs-accent); }
72
+
73
+ .search-bar input { flex: 1; background: transparent; border: none; color: white; padding: 8px 15px; outline: none; font-size: 14px; }
74
+ .btn-search { background: var(--vs-accent); color: white; border: none; padding: 0 20px; border-radius: 2px; cursor: pointer; display: flex; align-items: center; }
75
+ #search-error { color: var(--vs-error); font-size: 12px; margin-top: 12px; min-height: 18px; }
76
+ .history-container { margin-top: 40px; width: 100%; display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
77
+ .history-tag { background: var(--vs-bg-side); border: 1px solid var(--vs-border); padding: 5px 15px; border-radius: 20px; font-size: 12px; color: #888; cursor: pointer; transition: 0.2s; }
78
+ .history-tag:hover { border-color: var(--vs-accent); color: white; }
79
+
80
+ /* --- 详情页样式 --- */
81
+ #detail-page { flex-direction: column; }
82
+ .nav-header { background: var(--vs-bg-side); padding: 12px 20px; border-bottom: 1px solid var(--vs-border); display: flex; align-items: center; }
83
+ .back-link { color: var(--vs-accent); cursor: pointer; font-size: 13px; text-decoration: none; }
84
+ header { background-color: var(--vs-bg-side); padding: 20px 28px; border-bottom: 1px solid var(--vs-border); }
85
+ main { flex: 1; padding: 28px; overflow-y: auto; display: flex; flex-direction: column; }
86
+ .meta-group { display: flex; gap: 40px; margin-bottom: 15px; }
87
+ .meta-label { font-size: 11px; color: #555; text-transform: uppercase; font-weight: bold; margin-bottom: 4px; display: block; }
88
+ .meta-value { font-family: 'Consolas', monospace; font-size: 14px; color: var(--vs-accent); }
89
+ #desc-container { flex: 1; font-size: 14px; line-height: 1.8; color: #999; margin-bottom: 20px; }
90
+ #desc-container b { color: #ccc; }
91
+ .auth-panel { border-top: 1px solid var(--vs-border); padding-top: 20px; margin-top: auto; }
92
+ .vs-input-group { display: flex; background: var(--vs-input-bg); border: 1px solid transparent; height: 38px; border-radius: 2px; }
93
+ .vs-input-group.error { border-color: var(--vs-error); }
94
+ .vs-input-group:focus-within { border-color: var(--vs-accent); }
95
+ #license-key { background: transparent; border: none; color: white; padding: 0 12px; flex: 1; font-size: 13px; outline: none; }
96
+ .btn-action { background: var(--vs-accent); color: white; border: none; padding: 0 16px; font-size: 12px; cursor: pointer; }
97
+
98
+ /* --- 运行按钮优化 --- */
99
+ .btn-launch {
100
+ flex: 1; border: none; padding: 16px;
101
+ font-weight: 400; font-size: 13px;
102
+ letter-spacing: 0.5px;
103
+ background: #333; color: #666;
104
+ transition: background 0.3s, color 0.3s;
105
+ position: relative; overflow: hidden; z-index: 1;
106
+ opacity: 1 !important;
107
+ }
108
+ .no-transition { transition: none !important; }
109
+ .btn-launch:not(:disabled) { background: var(--vs-accent); color: white; cursor: pointer; }
110
+ .btn-launch.btn-stop { background: var(--vs-stop) !important; color: white !important; }
111
+ .btn-launch.deploying { background: #2d2d2d !important; color: #ffffff !important; }
112
+
113
+ .progress-bg {
114
+ position: absolute; top: 0; left: 0; bottom: 0;
115
+ width: 0%; background: var(--vs-accent);
116
+ z-index: -1; transition: width 0.1s linear;
117
+ }
118
+ .btn-text { position: relative; z-index: 2; }
119
+
120
+ .btn-clear { width: 50px; background: #333; color: #888; border: 1px solid var(--vs-border); display: flex; align-items: center; justify-content: center; transition: 0.2s; }
121
+ .btn-clear:hover { background: #444; color: var(--vs-error); border-color: var(--vs-error); }
122
+ </style>
123
+ </head>
124
+ <body>
125
+
126
+ <div id="init-loader">
127
+ <div class="spinner"></div>
128
+ <div class="loader-text">ASCRIPT ENGINE CONNECTING</div>
129
+ </div>
130
+
131
+ <div id="home-page">
132
+ <div class="search-wrapper">
133
+ <div class="logo">AScript <b>STORE</b></div>
134
+ <div id="search-bar-container" class="search-bar">
135
+ <input type="text" id="search-input" placeholder="请输入小程序 ID 搜索..." spellcheck="false"
136
+ oninput="document.getElementById('search-bar-container').classList.remove('error')"
137
+ onkeyup="if(event.keyCode==13) handleSearch()">
138
+ <button class="btn-search" id="search-btn" onclick="handleSearch()">搜索</button>
139
+ </div>
140
+ <div id="search-error"></div>
141
+ <div class="history-container" id="history-list"></div>
142
+ </div>
143
+ </div>
144
+
145
+ <div id="detail-page">
146
+ <div class="nav-header" id="nav-header"><span class="back-link" onclick="goBack()">❮ 返回搜索列表</span></div>
147
+ <header>
148
+ <div class="d-flex justify-content-between align-items-center">
149
+ <h1 id="app-name" style="font-size: 1.1rem; margin:0; color:#fff;">--</h1>
150
+ <div id="price-tag" style="font-size: 10px; padding: 2px 8px; border: 1px solid #333;">--</div>
151
+ </div>
152
+ </header>
153
+ <main>
154
+ <div class="meta-group">
155
+ <div><span class="meta-label">应用 ID</span><span id="view-app-id" class="meta-value">--</span></div>
156
+ <div><span class="meta-label">开发作者</span><span id="view-app-auth" class="meta-value">--</span></div>
157
+ </div>
158
+ <div id="desc-container">--</div>
159
+ <div id="auth-section" class="auth-panel" style="display: none;">
160
+ <div id="active-info" style="display: none; margin-bottom: 12px;">
161
+ <div class="d-flex align-items-center justify-content-between">
162
+ <div><span style="color: #4ade80; font-size: 12px;">● 授权验证成功</span><span id="card-expire" style="color: #666; font-size: 11px; margin-left:10px;"></span></div>
163
+ <button class="btn-action" style="background:none; text-decoration:underline; font-size:11px;" onclick="resetAuth()">更换卡密</button>
164
+ </div>
165
+ </div>
166
+ <div id="input-area">
167
+ <div class="vs-input-group" id="input-container">
168
+ <input type="text" id="license-key" placeholder="输入激活码以解锁专业功能" autocomplete="off">
169
+ <button class="btn-action" id="activate-btn" onclick="handleActivate()">激活</button>
170
+ </div>
171
+ <div id="expire-msg" class="text-danger mt-2" style="display:none; font-size: 11px;"></div>
172
+ </div>
173
+ </div>
174
+ </main>
175
+ <footer style="padding: 15px 28px; background: var(--vs-bg-side); border-top: 1px solid var(--vs-border);">
176
+ <div class="d-flex gap-2">
177
+ <button id="enter-btn" class="btn-launch" disabled onclick="handleMainAction()">
178
+ <div id="btn-progress" class="progress-bg"></div>
179
+ <span id="btn-text" class="btn-text">立即运行程序系统</span>
180
+ </button>
181
+ <button id="clear-btn" class="btn-clear" style="display:none;" title="清理并重置环境" onclick="handleClearEnv()">
182
+ <svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/><path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/></svg>
183
+ </button>
184
+ </div>
185
+ </footer>
186
+ </div>
187
+
188
+ <script>
189
+ let currentApp = null;
190
+ let isSingleAppMode = false;
191
+ let statusTimer = null;
192
+ let isDeploying = false;
193
+ let lastKnownRunning = false;
194
+
195
+ // 诊断:直连 pywebview 桥接写日志,不走 callPython(callPython 本身可能是故障点)
196
+ function _jslog(m) {
197
+ try { window.pywebview.api.call_internal('_diag', ['JS: ' + m]); } catch (e) {}
198
+ }
199
+ let _initStarted = false;
200
+ _jslog('inline script started, callPython=' + (typeof window.callPython)
201
+ + ', pywebview=' + (typeof window.pywebview));
202
+
203
+ window.updateDownloadProgress = function(percent) {
204
+ const progressBg = document.getElementById('btn-progress');
205
+ const btnText = document.getElementById('btn-text');
206
+ if (progressBg) progressBg.style.width = percent + '%';
207
+ if (btnText) btnText.innerText = `正在获取资源... ${percent}%`;
208
+ }
209
+
210
+ // 核心修复逻辑:搜索处理
211
+ async function handleSearch(manualId) {
212
+ const input = document.getElementById('search-input');
213
+ const searchBar = document.getElementById('search-bar-container');
214
+ const btn = document.getElementById('search-btn');
215
+ const err = document.getElementById('search-error');
216
+ const appId = manualId || input.value.trim();
217
+
218
+ if (!appId) {
219
+ searchBar.classList.add('error'); // 触发红圈提醒
220
+ err.innerText = "请输入小程序 ID 后再进行搜索";
221
+ return;
222
+ } else {
223
+ searchBar.classList.remove('error');
224
+ }
225
+
226
+ btn.disabled = true;
227
+ btn.innerHTML = '<div class="spinner spinner-sm"></div>';
228
+ err.innerText = "";
229
+
230
+ try {
231
+ const res = await window.callPython("get_app_info", String(appId));
232
+ if (res.code === 1) {
233
+ await renderDetailPage(res.data);
234
+ hideLoader();
235
+ } else {
236
+ err.innerText = res.msg;
237
+ if (manualId && isSingleAppMode) {
238
+ isSingleAppMode = false;
239
+ document.getElementById('home-page').style.display = 'flex';
240
+ await refreshHistory();
241
+ }
242
+ hideLoader();
243
+ }
244
+ } catch (e) { err.innerText = "网络连接异常"; hideLoader(); }
245
+ finally { btn.disabled = false; btn.innerText = "搜索"; }
246
+ }
247
+
248
+ // 状态更新与运行逻辑保持之前的“不模糊”修复方案
249
+ function updateButtonState(isRunning) {
250
+ const btn = document.getElementById('enter-btn');
251
+ const btnText = document.getElementById('btn-text');
252
+ const progressBg = document.getElementById('btn-progress');
253
+ const clearBtn = document.getElementById('clear-btn');
254
+ lastKnownRunning = isRunning;
255
+
256
+ if (isDeploying) return;
257
+
258
+ btn.classList.add('no-transition');
259
+ btn.classList.remove('deploying');
260
+ progressBg.style.width = '0%';
261
+ btn.offsetHeight;
262
+ btn.classList.remove('no-transition');
263
+
264
+ if (isRunning) {
265
+ btn.disabled = false;
266
+ btnText.innerText = "停止程序系统运行";
267
+ btn.classList.add('btn-stop');
268
+ clearBtn.style.display = 'none';
269
+ } else {
270
+ btn.classList.remove('btn-stop');
271
+ const isAuth = (currentApp.is_free === 1) || document.getElementById('active-info').style.display === 'block';
272
+
273
+ if (isAuth) {
274
+ btn.disabled = false;
275
+ btnText.innerText = "立即运行程序系统";
276
+ clearBtn.style.display = 'flex';
277
+ } else {
278
+ btn.disabled = true;
279
+ btnText.innerText = "请先激活专业版";
280
+ clearBtn.style.display = 'none';
281
+ }
282
+ }
283
+ }
284
+
285
+ async function handleMainAction() {
286
+ const btn = document.getElementById('enter-btn');
287
+ const btnText = document.getElementById('btn-text');
288
+ const progressBg = document.getElementById('btn-progress');
289
+
290
+ // 如果是停止逻辑,保持不变
291
+ if (btn.classList.contains('btn-stop') || lastKnownRunning) {
292
+ await window.callPython("stop_app", String(currentApp.id));
293
+ updateButtonState(false);
294
+ return;
295
+ }
296
+
297
+ // 运行逻辑
298
+ isDeploying = true;
299
+ btn.disabled = true;
300
+ btn.classList.add('deploying');
301
+ progressBg.style.width = '0%';
302
+ btnText.innerText = "正在检查资源...";
303
+
304
+ try {
305
+ const dlRes = await window.callPython("download_app", currentApp);
306
+ if (dlRes.code === 1) {
307
+ progressBg.style.width = '100%';
308
+ btnText.innerText = "环境部署中,请稍候...";
309
+
310
+ // 执行启动
311
+ const startRes = await window.callPython("start_app", currentApp);
312
+
313
+ // --- 关键修复:衔接逻辑 ---
314
+ if (startRes && startRes.code === 1) {
315
+ // 1. 立即强制更新 UI 为运行状态,不等待轮询
316
+ lastKnownRunning = true;
317
+ isDeploying = false; // 结束部署状态
318
+ updateButtonState(true); // 强制渲染为“停止按钮”样式
319
+
320
+ // 2. 这里的动画衔接:让进度条满格后再消失
321
+ setTimeout(() => {
322
+ progressBg.style.width = '0%';
323
+ }, 500);
324
+ } else {
325
+ throw new Error(startRes.msg || "启动失败");
326
+ }
327
+ } else {
328
+ alert(dlRes.msg);
329
+ isDeploying = false;
330
+ updateButtonState(false);
331
+ }
332
+ } catch(e) {
333
+ console.error(e);
334
+ alert("启动异常: " + (e.message || e));
335
+ isDeploying = false;
336
+ updateButtonState(false);
337
+ }
338
+ }
339
+
340
+ // 其余函数 (init, goBack, renderDetailPage等) 全部保持不变...
341
+ async function init() {
342
+ if (_initStarted) { _jslog('init() re-entry blocked'); return; }
343
+ _initStarted = true;
344
+ _jslog('init() START');
345
+ try {
346
+ _jslog('init: before refreshHistory');
347
+ await refreshHistory();
348
+ _jslog('init: before get_init_config');
349
+ const config = await window.callPython("get_init_config");
350
+ _jslog('init: get_init_config -> ' + JSON.stringify(config));
351
+ if (config && config.default_id) {
352
+ isSingleAppMode = true;
353
+ await handleSearch(config.default_id);
354
+ } else {
355
+ isSingleAppMode = false;
356
+ document.getElementById('home-page').style.display = 'flex';
357
+ requestAnimationFrame(() => { setTimeout(hideLoader, 50); });
358
+ }
359
+ _jslog('init() DONE');
360
+ } catch (e) { _jslog('init() CATCH: ' + e); hideLoader(); }
361
+ }
362
+
363
+ async function refreshHistory() {
364
+ const history = await window.callPython("get_history");
365
+ const listDom = document.getElementById('history-list');
366
+ listDom.innerHTML = (history || []).map(item => `
367
+ <div class="history-tag" onclick="handleSearch('${item.id}')">${item.name}</div>
368
+ `).join('');
369
+ }
370
+
371
+ async function renderDetailPage(data) {
372
+ currentApp = data;
373
+ document.getElementById('home-page').style.display = 'none';
374
+ document.getElementById('detail-page').style.display = 'flex';
375
+ document.getElementById('nav-header').style.display = isSingleAppMode ? 'none' : 'flex';
376
+ document.getElementById('app-name').innerText = data.name;
377
+ document.getElementById('view-app-id').innerText = data.id;
378
+ document.getElementById('view-app-auth').innerText = data.auth || "官方认证";
379
+ document.getElementById('desc-container').innerHTML = data.desc;
380
+
381
+ const authSection = document.getElementById('auth-section');
382
+ if (data.is_free === 1) {
383
+ document.getElementById('price-tag').innerText = "社区免费版";
384
+ document.getElementById('price-tag').style.color = "#28a745";
385
+ authSection.style.display = 'none';
386
+ } else {
387
+ document.getElementById('price-tag').innerText = "专业授权版";
388
+ document.getElementById('price-tag').style.color = "#ffbf00";
389
+ authSection.style.display = 'block';
390
+ const cached = await window.callPython("get_cached_key", String(data.id));
391
+ if (cached) {
392
+ document.getElementById('license-key').value = cached;
393
+ await handleActivate(cached);
394
+ }
395
+ }
396
+ startStatusPolling();
397
+ }
398
+
399
+ function startStatusPolling() {
400
+ if(statusTimer) clearInterval(statusTimer);
401
+ checkNow();
402
+ statusTimer = setInterval(checkNow, 1500);
403
+ async function checkNow() {
404
+ if (currentApp && !isDeploying) {
405
+ try {
406
+ const res = await window.callPython("check_status", String(currentApp.id));
407
+ updateButtonState(!!res.running);
408
+ } catch(e) { console.error("Poll error", e); }
409
+ }
410
+ }
411
+ }
412
+
413
+ function hideLoader() {
414
+ _jslog('hideLoader called');
415
+ const loader = document.getElementById('init-loader');
416
+ if (loader.style.display === 'none') return;
417
+ loader.style.opacity = '0';
418
+ setTimeout(() => { loader.style.display = 'none'; }, 300);
419
+ }
420
+
421
+ async function handleClearEnv() {
422
+ if (!confirm("确定要删除虚拟环境并重置吗?下次启动将重新部署。")) return;
423
+ const res = await window.callPython("clear_env", String(currentApp.id));
424
+ alert(res.msg);
425
+ }
426
+
427
+ async function handleActivate(keyOverride = null) {
428
+ const keyInput = document.getElementById('license-key');
429
+ const btn = document.getElementById('activate-btn');
430
+ const expireMsg = document.getElementById('expire-msg');
431
+ const container = document.getElementById('input-container');
432
+ const key = keyOverride || keyInput.value.trim();
433
+ if (!key) return;
434
+ btn.disabled = true;
435
+ btn.innerHTML = '<div class="spinner spinner-sm"></div>';
436
+ expireMsg.style.display = 'none';
437
+ container.classList.remove('error');
438
+ try {
439
+ const res = await window.callPython("activate_key", String(currentApp.id), String(key));
440
+ if (res && res.code === 1 && res.data && res.data.status === 1) {
441
+ document.getElementById('active-info').style.display = 'block';
442
+ document.getElementById('input-area').style.display = 'none';
443
+ document.getElementById('card-expire').innerText = "到期: " + res.data.expire;
444
+ updateButtonState(lastKnownRunning);
445
+ } else {
446
+ container.classList.add('error');
447
+ expireMsg.style.display = 'block';
448
+ expireMsg.innerText = res.msg || "授权码无效";
449
+ }
450
+ } finally {
451
+ btn.disabled = false;
452
+ btn.innerText = '激活';
453
+ }
454
+ }
455
+
456
+ function resetAuth() {
457
+ document.getElementById('active-info').style.display = 'none';
458
+ document.getElementById('input-area').style.display = 'block';
459
+ document.getElementById('license-key').value = "";
460
+ updateButtonState(lastKnownRunning);
461
+ }
462
+
463
+ function goBack() {
464
+ if(statusTimer) clearInterval(statusTimer);
465
+ document.getElementById('detail-page').style.display = 'none';
466
+ document.getElementById('home-page').style.display = 'flex';
467
+ refreshHistory();
468
+ }
469
+
470
+ // 同时兼容两种时序:注入早于本脚本时直接执行,否则等待事件
471
+ _jslog('script bottom, callPython=' + (typeof window.callPython));
472
+ if (window.callPython) {
473
+ _jslog('taking direct init() path');
474
+ init();
475
+ } else {
476
+ _jslog('registering onPythonReady listener');
477
+ window.addEventListener('onPythonReady', init);
478
+ }
479
+ </script>
480
+ </body>
481
+ </html>