You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

344 lines
11 KiB

12 months ago
12 months ago
12 months ago
4 weeks ago
12 months ago
4 weeks ago
4 weeks ago
4 weeks ago
12 months ago
4 weeks ago
12 months ago
4 weeks ago
12 months ago
4 weeks ago
4 weeks ago
4 weeks ago
12 months ago
12 months ago
12 months ago
4 weeks ago
12 months ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
12 months ago
4 weeks ago
12 months ago
12 months ago
11 months ago
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>消毒API测试页面</title>
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  7. <script src="./vue.global.js"></script>
  8. <script src="./dayjs/dayjs.min.js"></script>
  9. <script src="./dayjs/plugin/customParseFormat.js"></script>
  10. <script src="./dayjs/plugin/weekday.js"></script>
  11. <script src="./dayjs/plugin/localeData.js"></script>
  12. <script src="./dayjs/plugin/weekOfYear.js"></script>
  13. <script src="./dayjs/plugin/weekYear.js"></script>
  14. <script src="./dayjs/plugin/advancedFormat.js"></script>
  15. <script src="./dayjs/plugin/quarterOfYear.js"></script>
  16. <script src="./ant-design-vue/antd.min.js"></script>
  17. <link href="./ant-design-vue/reset.min.css" rel="stylesheet">
  18. <script src="./virtual-keyboard.js"></script>
  19. </head>
  20. <body>
  21. <div id="app" class="h-full">
  22. <a-row class="h-full">
  23. <a-col :span="3">
  24. <div style="display:flex;padding:5px;">
  25. <a-input v-model:value="wsUrl" style="margin-right:5px;"></a-input>
  26. <a-button v-if="null === ws" @click="actionConnect">连接</a-button>
  27. <a-button v-else @click="actionDisconnect">断开</a-button>
  28. </div>
  29. <a-menu mode="inline" :items="actionMenuItems" @click="actionGroupMenuItemClick"></a-menu>
  30. </a-col>
  31. <!-- -->
  32. <a-col :span="15" style="background-color: #f1f1f1;display:flex;flex-direction: column;">
  33. <div v-if="null !== actionActiveGroup"
  34. style="height:0;flex-grow: 1;overflow-y: auto;margin-bottom: 10px;padding: 10px;">
  35. <div v-for="item in actionActiveGroup.items" class="action"
  36. style="margin-bottom: 5px;background:white;padding:5px;border-radius: 5px; ">
  37. <!-- 按键 -->
  38. <a-button ghost type="primary"
  39. style="margin-right: 5px; min-width:230px ;font-weight: bold; text-align: left;"
  40. @click="actionActionExecute(item)">
  41. {{item.fnDispName}}</a-button>
  42. <!-- 参数 -->
  43. <div v-for="param in item.params" style="margin-right: 10px; width:150px ">
  44. <a-select v-if="item.paramInfoMap[param].isEnum" style=" width:150px" v-model:value="item.values[param]"
  45. :placeholder="param" :dropdownMatchSelectWidth="false">
  46. <!-- -->
  47. <a-select-option v-for="enumValue in item.paramInfoMap[param].enumValues" :key="enumValue"
  48. :value="enumValue">{{enumValue}}</a-select-option>
  49. <!-- -->
  50. </a-select>
  51. <a-input v-else v-model:value="item.values[param]" :placeholder="param"
  52. @click="showKeyboard(item.values, param)"></a-input>
  53. </div>
  54. </div>
  55. </div>
  56. </a-col>
  57. <a-col :span="6" style="height: 100%;display: flex;flex-direction: column;">
  58. <div style="text-align: right; padding:10px;">
  59. <a-button @click="actionClearLogs">清空日志</a-button>
  60. </div>
  61. <div style="height:0;flex-grow:1;overflow-y: auto;">
  62. <a-collapse>
  63. <a-collapse-panel v-for="(entry,index) in logs" :key="index" :header="entry.title">
  64. <div style="white-space: pre-wrap;">
  65. {{entry.content}}
  66. </div>
  67. </a-collapse-panel>
  68. </a-collapse>
  69. </div>
  70. <div style="padding:10px;">
  71. <div style="margin-bottom: 5px;height: 600px; overflow-y: auto;">
  72. <a-collapse>
  73. <a-collapse-panel v-for="(entry,index) in reports" :key="index" :header="entry.title">
  74. <div style="white-space: pre-wrap;">
  75. {{entry.content}}
  76. </div>
  77. </a-collapse-panel>
  78. </a-collapse>
  79. </div>
  80. </div>
  81. </a-col>
  82. </a-row>
  83. </div>
  84. <script>
  85. const { createApp } = Vue
  86. createApp({
  87. data() {
  88. return {
  89. actions: [],
  90. menuList: [],
  91. actionActiveGroup: null,
  92. rawRequestContent: '',
  93. logs: [],
  94. reports: [],
  95. wsUrl: "ws://" + window.location.hostname + ":19001",
  96. ws: null,
  97. wsMessageIndex: 0,
  98. requests: {},
  99. reportId: 0,
  100. map: new Map(),
  101. counter: 0
  102. }
  103. },
  104. computed: {
  105. actionMenuItems() {
  106. return this.menuList.map(i => ({ key: i.className, label: i.classDispName }));
  107. }
  108. },
  109. mounted() {
  110. },
  111. methods: {
  112. // connect
  113. getReportId(str) {
  114. // 如果字符串已存在,返回已存储的id
  115. if (this.map.has(str)) {
  116. return this.map.get(str);
  117. }
  118. // 否则,生成一个新的ID
  119. const id = this.counter++;
  120. this.map.set(str, id);
  121. return id;
  122. },
  123. actionConnect() {
  124. this.ws = new WebSocket(this.wsUrl);
  125. this.ws.onclose = () => this.ws = null;
  126. this.ws.onmessage = event => {
  127. let data = JSON.parse(event.data);
  128. let responseEntry = {};
  129. responseEntry.title = `${data.fromClass}.${data.fromFn}`;
  130. responseEntry.content = JSON.stringify(data, null, 2);
  131. if ('Ack' === data.messageType && 'FNScheduler' === data.fromClass && 'geFnList' === data.fromFn) {
  132. this.actionListReload(data);
  133. }
  134. if ('Ack' === data.messageType && 'FNScheduler' === data.fromClass && 'geMenuList' === data.fromFn) {
  135. this.menuListReload(data);
  136. }
  137. if ('Ack' === data.messageType) {
  138. this.logs.push(responseEntry);
  139. }
  140. if ('Report' === data.messageType) {
  141. let reportuuid = data.fromClass + '.' + data.fromFn;
  142. let reportId = this.getReportId(reportuuid);
  143. // this.reports.unshift(reportId,responseEntry);
  144. this.reports[reportId] = responseEntry;
  145. }
  146. };
  147. this.ws.onopen = () => {
  148. {
  149. this.wsMessageIndex++;
  150. let request = {};
  151. request.messageId = this.wsMessageIndex;
  152. request.timeStamp = Math.floor(Date.now() / 1000);
  153. request.messageType = 'Command';
  154. request.className = 'FNScheduler';
  155. request.fnName = 'geFnList';
  156. request.params = {};
  157. this.wsCall(request);
  158. }
  159. {
  160. this.wsMessageIndex++;
  161. let request = {};
  162. request.messageId = this.wsMessageIndex;
  163. request.timeStamp = Math.floor(Date.now() / 1000);
  164. request.messageType = 'Command';
  165. request.className = 'FNScheduler';
  166. request.fnName = 'geMenuList';
  167. request.params = {};
  168. this.wsCall(request);
  169. }
  170. }
  171. },
  172. // disconnect
  173. actionDisconnect() {
  174. this.ws.close();
  175. },
  176. // clear logs
  177. actionClearLogs() {
  178. this.logs = [];
  179. },
  180. showKeyboard(values, param) {
  181. // const inputElement = document.querySelector(`input[placeholder="${param}"]`);
  182. // if (inputElement) {
  183. // VirtualKeyboard.show(inputElement);
  184. // this.updateDisplayContainer(inputElement);
  185. // }
  186. },
  187. updateDisplayContainer(inputElement) {
  188. const displayContainer = document.querySelector('.virtual-keyboard-display');
  189. if (displayContainer) {
  190. inputElement.addEventListener('input', () => {
  191. displayContainer.textContent = inputElement.value;
  192. });
  193. }
  194. },
  195. menuListReload(response) {
  196. let data = response.rely;
  197. if (undefined === data) {
  198. return;
  199. }
  200. this.menuList = data;
  201. },
  202. // action list reload
  203. actionListReload(response) {
  204. let data = response.rely;
  205. if (undefined === data) {
  206. return;
  207. }
  208. this.actions = [];
  209. for (let action of data.fnlist) {
  210. let group = this.actions.find(i => i.key === action.className);
  211. if (undefined === group) {
  212. group = { key: action.className, items: [] };
  213. this.actions.push(group);
  214. }
  215. item = JSON.parse(JSON.stringify(action)); // Replace structuredClone with JSON.parse(JSON.stringify())
  216. item.values = {};
  217. item.paramInfoMap = {};
  218. for (let i = 0; i < item.paramsTypeInfo.length; i++) {
  219. let typeName = item.paramsTypeInfo[i];
  220. let info = data.typeInfoList.find(p => p.typeName === typeName);
  221. let name = item.params[i];
  222. item.paramInfoMap[name] = info;
  223. }
  224. group.items.push(item);
  225. }
  226. },
  227. // action group menu item click
  228. actionGroupMenuItemClick(event) {
  229. this.actionActiveGroup = this.actions.find(i => i.key === event.key);
  230. },
  231. // action execute
  232. actionActionExecute(item) {
  233. this.wsMessageIndex++;
  234. let request = {};
  235. request.messageId = this.wsMessageIndex;
  236. request.timeStamp = Math.floor(Date.now() / 1000);
  237. request.messageType = 'Command';
  238. request.className = item.className;
  239. request.fnName = item.fnName;
  240. request.params = {};
  241. for (let i = 0; i < item.params.length; i++) {
  242. let param = item.params[i];
  243. let type = item.paramsTypeInfo[i];
  244. let value = item.values[param];
  245. switch (type) {
  246. case 'json':
  247. case 'vector<bool>':
  248. case 'vector<json>':
  249. case 'vector<double>':
  250. case 'vector<int32_t>':
  251. case 'vector<string>': value = JSON.parse(value); break;
  252. case 'bool': value = '1' === value ? true : false; break;
  253. case 'float':
  254. case 'double':
  255. case 'int': value *= 1; break;
  256. case 'string': /* nothing to do here */ break;
  257. default: /* throw an exception is required. */
  258. }
  259. request.params[param] = value;
  260. }
  261. this.logs = [];
  262. this.wsCall(request);
  263. },
  264. // raw request send
  265. actionSendRawRequest() {
  266. let request = JSON.parse(this.rawRequestContent);
  267. this.wsCall(request);
  268. },
  269. // ws call
  270. wsCall(request) {
  271. if (null === this.ws) {
  272. return;
  273. }
  274. let requestEntry = {};
  275. requestEntry.title = `${request.messageType} : ${request.className}.${request.fnName}`;
  276. requestEntry.content = JSON.stringify(request, null, 2);
  277. this.logs.push(requestEntry);
  278. this.ws.send(JSON.stringify(request));
  279. },
  280. },
  281. })
  282. .use(antd)
  283. .mount('#app');
  284. </script>
  285. <style>
  286. .h-full {
  287. height: 100%;
  288. }
  289. .action {
  290. display: flex;
  291. flex-direction: row;
  292. }
  293. </style>
  294. </body>
  295. </html>