|
|
<!DOCTYPE html> <html>
<head> <title>消毒API测试页面</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="./vue.global.js"></script> <script src="./dayjs/dayjs.min.js"></script> <script src="./dayjs/plugin/customParseFormat.js"></script> <script src="./dayjs/plugin/weekday.js"></script> <script src="./dayjs/plugin/localeData.js"></script> <script src="./dayjs/plugin/weekOfYear.js"></script> <script src="./dayjs/plugin/weekYear.js"></script> <script src="./dayjs/plugin/advancedFormat.js"></script> <script src="./dayjs/plugin/quarterOfYear.js"></script> <script src="./ant-design-vue/antd.min.js"></script> <link href="./ant-design-vue/reset.min.css" rel="stylesheet"> </head> </head>
<body> <div id="app" class="h-full"> <a-row class="h-full"> <a-col :span="6"> <div style="display:flex;padding:5px;"> <a-input v-model:value="wsUrl" style="margin-right:5px;"></a-input> <a-button v-if="null === ws" @click="actionConnect">连接</a-button> <a-button v-else @click="actionDisconnect">断开</a-button> </div> <a-menu mode="inline" :items="actionMenuItems" @click="actionGroupMenuItemClick"></a-menu> </a-col> <a-col :span="12" style="background-color: #f1f1f1;display:flex;flex-direction: column;"> <div v-if="null !== actionActiveGroup" style="height:0;flex-grow: 1;overflow-y: auto;margin-bottom: 10px;padding: 10px;"> <div v-for="item in actionActiveGroup.items" class="action" style="margin-bottom: 5px;background:white;padding:5px;border-radius: 5px;"> <div style="margin-right:5px;padding: 8px;"> {{item.fnName}} </div> <div v-for="param in item.params"> <a-select v-if="item.paramInfoMap[param].isEnum" v-model:value="item.values[param]" :placeholder="param" :dropdownMatchSelectWidth="false"> <a-select-option v-for="enumValue in item.paramInfoMap[param].enumValues" :key="enumValue" :value="enumValue">{{enumValue}}</a-select-option> </a-select> <a-input v-else v-model:value="item.values[param]" :placeholder="param" /> </div> <a-button style="margin-left:5px;" @click="actionActionExecute(item)">执行</a-button> </div> </div> <div style="padding:10px;"> <a-textarea v-model:value="rawRequestContent" style="margin-bottom: 5px;height: 300px;"></a-textarea> <div> <a-button @click="actionSendRawRequest">发送</a-button> </div> </div> </a-col> <a-col :span="6" style="height: 100%;display: flex;flex-direction: column;"> <div style="text-align: right; padding:10px;"> <a-button @click="actionClearLogs">清空日志</a-button> </div> <div style="height:0;flex-grow:1;overflow-y: auto;"> <a-collapse> <a-collapse-panel v-for="(entry,index) in logs" :key="index" :header="entry.title"> <div style="white-space: pre-wrap;"> {{entry.content}} </div> </a-collapse-panel> </a-collapse> </div> </a-col> </a-row> </div> <script> const { createApp } = Vue createApp({ data() { return { actions: [], actionActiveGroup: null, rawRequestContent: '', logs: [], wsUrl: "ws://" + window.location.hostname + ":19001", ws: null, wsMessageIndex: 0, requests: {}, } }, computed: { actionMenuItems() { return this.actions.map(i => ({ key: i.key, label: i.key })); } }, methods: { // connect actionConnect() { this.ws = new WebSocket(this.wsUrl); this.ws.onclose = () => this.ws = null; this.ws.onmessage = event => { let data = JSON.parse(event.data); let responseEntry = {}; responseEntry.title = `${data.messageType}`; responseEntry.content = JSON.stringify(data, null, 2); this.logs.push(responseEntry); if ('Ack' === data.messageType && 'FNScheduler' === data.fromClass && 'geFnList' === data.fromFn) { this.actionListReload(data); } }; this.ws.onopen = () => { this.wsMessageIndex++; let request = {}; request.messageId = this.wsMessageIndex; request.timeStamp = Math.floor(Date.now() / 1000); request.messageType = 'Command'; request.className = 'FNScheduler'; request.fnName = 'geFnList'; request.params = {}; this.wsCall(request); } },
// disconnect actionDisconnect() { this.ws.close(); },
// clear logs actionClearLogs() { this.logs = []; },
// action list reload actionListReload(response) { let data = response.rely; if (undefined === data) { return; }
this.actions = []; for (let action of data.fnlist) { let group = this.actions.find(i => i.key === action.className); if (undefined === group) { group = { key: action.className, items: [] }; this.actions.push(group); } item = structuredClone(action); item.values = {}; item.paramInfoMap = {}; for (let i = 0; i < item.paramsTypeInfo.length; i++) { let typeName = item.paramsTypeInfo[i]; let info = data.typeInfoList.find(p => p.typeName === typeName); let name = item.params[i]; item.paramInfoMap[name] = info; } group.items.push(item); } },
// action group menu item click actionGroupMenuItemClick(event) { this.actionActiveGroup = this.actions.find(i => i.key === event.key); },
// action execute actionActionExecute(item) { this.wsMessageIndex++;
let request = {}; request.messageId = this.wsMessageIndex; request.timeStamp = Math.floor(Date.now() / 1000); request.messageType = 'Command'; request.className = item.className; request.fnName = item.fnName; request.params = {}; for (let i = 0; i < item.params.length; i++) { let param = item.params[i]; let type = item.paramsTypeInfo[i]; let value = item.values[param]; switch (type) { case 'json': case 'vector<bool>': case 'vector<json>': case 'vector<double>': case 'vector<int32_t>': case 'vector<string>': value = JSON.parse(value); break; case 'bool': value = '1' === value ? true : false; break; case 'float': case 'double': case 'int': value *= 1; break; case 'string': /* nothing to do here */ break; default: /* throw an exception is required. */ } request.params[param] = value; } this.logs = []; this.wsCall(request); },
// raw request send actionSendRawRequest() { let request = JSON.parse(this.rawRequestContent); this.wsCall(request); },
// ws call wsCall(request) { if (null === this.ws) { return; } let requestEntry = {}; requestEntry.title = `${request.messageType} : ${request.className}.${request.fnName}`; requestEntry.content = JSON.stringify(request, null, 2); this.logs.push(requestEntry); this.ws.send(JSON.stringify(request)); }, }, }) .use(antd) .mount('#app'); </script> <style> .h-full { height: 100%; }
.action { display: flex; flex-direction: row; } </style> </body>
</html>
|