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.

219 lines
7.4 KiB

12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>TMP</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. </head>
  19. <body>
  20. <div id="app" class="h-full">
  21. <a-row class="h-full">
  22. <a-col :span="6">
  23. <div style="display:flex;padding:5px;">
  24. <a-input v-model:value="wsUrl" style="margin-right:5px;"></a-input>
  25. <a-button v-if="null === ws" @click="actionConnect">Connect</a-button>
  26. <a-button v-else @click="actionDisconnect">Disconnect</a-button>
  27. </div>
  28. <a-menu mode="inline" :items="actionMenuItems" @click="actionGroupMenuItemClick"></a-menu>
  29. </a-col>
  30. <a-col :span="12" style="background-color: #f1f1f1;display:flex;flex-direction: column;">
  31. <div v-if="null !== actionActiveGroup"
  32. style="height:0;flex-grow: 1;overflow-y: auto;margin-bottom: 10px;padding: 10px;">
  33. <div v-for="item in actionActiveGroup.items" class="action"
  34. style="margin-bottom: 5px;background:white;padding:5px;border-radius: 5px;">
  35. <div style="margin-right:5px;padding: 8px;">
  36. {{item.fnName}}
  37. </div>
  38. <div v-for="param in item.params">
  39. <a-input v-model:value="item.values[param]" :placeholder="param" />
  40. </div>
  41. <a-button style="margin-left:5px;" @click="actionActionExecute(item)">执行</a-button>
  42. </div>
  43. </div>
  44. <div style="padding:10px;">
  45. <a-textarea v-model:value="rawRequestContent" style="margin-bottom: 5px;height: 300px;"></a-textarea>
  46. <div>
  47. <a-button @click="actionSendRawRequest">Send</a-button>
  48. </div>
  49. </div>
  50. </a-col>
  51. <a-col :span="6" style="height: 100%;display: flex;flex-direction: column;">
  52. <div style="text-align: right; padding:10px;">
  53. <a-button @click="actionClearLogs">Clear</a-button>
  54. </div>
  55. <div style="height:0;flex-grow:1;overflow-y: auto;">
  56. <a-collapse>
  57. <a-collapse-panel v-for="(entry,index) in logs" :key="index" :header="entry.title">
  58. <div style="white-space: pre-wrap;">
  59. {{entry.content}}
  60. </div>
  61. </a-collapse-panel>
  62. </a-collapse>
  63. </div>
  64. </a-col>
  65. </a-row>
  66. </div>
  67. <script>
  68. const { createApp } = Vue
  69. createApp({
  70. data() {
  71. return {
  72. actions: [],
  73. actionActiveGroup: null,
  74. rawRequestContent: '',
  75. logs: [],
  76. wsUrl: "ws://" + window.location.hostname + ":19001",
  77. ws: null,
  78. wsMessageIndex: 0,
  79. requests: {},
  80. }
  81. },
  82. computed: {
  83. actionMenuItems() {
  84. return this.actions.map(i => ({ key: i.key, label: i.key }));
  85. }
  86. },
  87. methods: {
  88. // connect
  89. actionConnect() {
  90. this.ws = new WebSocket(this.wsUrl);
  91. this.ws.onclose = () => this.ws = null;
  92. this.ws.onmessage = event => {
  93. let data = JSON.parse(event.data);
  94. let responseEntry = {};
  95. responseEntry.title = `${data.messageType}`;
  96. responseEntry.content = JSON.stringify(data, null, 2);
  97. this.logs.push(responseEntry);
  98. if ('Ack' === data.messageType && 'FNScheduler' === data.fromClass && 'geFnList' === data.fromFn) {
  99. this.actionListReload(data);
  100. }
  101. };
  102. this.ws.onopen = () => {
  103. this.wsMessageIndex++;
  104. let request = {};
  105. request.messageId = this.wsMessageIndex;
  106. request.timeStamp = Math.floor(Date.now() / 1000);
  107. request.messageType = 'Command';
  108. request.className = 'FNScheduler';
  109. request.fnName = 'geFnList';
  110. request.params = {};
  111. this.wsCall(request);
  112. }
  113. },
  114. // disconnect
  115. actionDisconnect() {
  116. this.ws.close();
  117. },
  118. // clear logs
  119. actionClearLogs() {
  120. this.logs = [];
  121. },
  122. // action list reload
  123. actionListReload(response) {
  124. let data = response.rely;
  125. if (undefined === data) {
  126. return;
  127. }
  128. this.actions = [];
  129. for (let action of data.fnlist) {
  130. let group = this.actions.find(i => i.key === action.className);
  131. if (undefined === group) {
  132. group = { key: action.className, items: [] };
  133. this.actions.push(group);
  134. }
  135. item = structuredClone(action);
  136. item.values = {};
  137. group.items.push(item);
  138. }
  139. },
  140. // action group menu item click
  141. actionGroupMenuItemClick(event) {
  142. this.actionActiveGroup = this.actions.find(i => i.key === event.key);
  143. },
  144. // action execute
  145. actionActionExecute(item) {
  146. this.wsMessageIndex++;
  147. let request = {};
  148. request.messageId = this.wsMessageIndex;
  149. request.timeStamp = Math.floor(Date.now() / 1000);
  150. request.messageType = 'Command';
  151. request.className = item.className;
  152. request.fnName = item.fnName;
  153. request.params = {};
  154. for (let i = 0; i < item.params.length; i++) {
  155. let param = item.params[i];
  156. let type = item.paramsTypeInfo[i];
  157. let value = item.values[param];
  158. switch (type) {
  159. case 'json':
  160. case 'vector<bool>':
  161. case 'vector<json>':
  162. case 'vector<double>':
  163. case 'vector<int32_t>':
  164. case 'vector<string>': value = JSON.parse(value); break;
  165. case 'bool': value = '1' === value ? true : false; break;
  166. case 'float':
  167. case 'double':
  168. case 'int': value *= 1; break;
  169. case 'string': /* nothing to do here */ break;
  170. default: /* throw an exception is required. */
  171. }
  172. request.params[param] = value;
  173. }
  174. this.wsCall(request);
  175. },
  176. // raw request send
  177. actionSendRawRequest() {
  178. let request = JSON.parse(this.rawRequestContent);
  179. this.wsCall(request);
  180. },
  181. // ws call
  182. wsCall(request) {
  183. if (null === this.ws) {
  184. return;
  185. }
  186. let requestEntry = {};
  187. requestEntry.title = `${request.messageType} : ${request.className}.${request.fnName}`;
  188. requestEntry.content = JSON.stringify(request, null, 2);
  189. this.logs.push(requestEntry);
  190. this.ws.send(JSON.stringify(request));
  191. },
  192. },
  193. })
  194. .use(antd)
  195. .mount('#app');
  196. </script>
  197. <style>
  198. .h-full {
  199. height: 100%;
  200. }
  201. .action {
  202. display: flex;
  203. flex-direction: row;
  204. }
  205. </style>
  206. </body>
  207. </html>