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.
 
 
 
 
 

345 lines
11 KiB

<!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">
<script src="./virtual-keyboard.js"></script>
</head>
<body>
<div id="app" class="h-full">
<a-row class="h-full">
<a-col :span="3">
<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="15" 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; ">
<!-- 按键 -->
<a-button ghost type="primary"
style="margin-right: 5px; min-width:230px ;font-weight: bold; text-align: left;"
@click="actionActionExecute(item)">
{{item.fnDispName}}</a-button>
<!-- 参数 -->
<div v-for="param in item.params" style="margin-right: 10px; width:150px ">
<a-select v-if="item.paramInfoMap[param].isEnum" style=" width:150px" 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"
@click="showKeyboard(item.values, param)"></a-input>
</div>
</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>
<div style="padding:10px;">
<div style="margin-bottom: 5px;height: 600px; overflow-y: auto;">
<a-collapse>
<a-collapse-panel v-for="(entry,index) in reports" :key="index" :header="entry.title">
<div style="white-space: pre-wrap;">
{{entry.content}}
</div>
</a-collapse-panel>
</a-collapse>
</div>
</div>
</a-col>
</a-row>
</div>
<script>
const { createApp } = Vue
createApp({
data() {
return {
actions: [],
menuList: [],
actionActiveGroup: null,
rawRequestContent: '',
logs: [],
reports: [],
wsUrl: "ws://" + window.location.hostname + ":19001",
ws: null,
wsMessageIndex: 0,
requests: {},
reportId: 0,
map: new Map(),
counter: 0
}
},
computed: {
actionMenuItems() {
return this.menuList.map(i => ({ key: i.className, label: i.classDispName }));
}
},
mounted() {
},
methods: {
// connect
getReportId(str) {
// 如果字符串已存在,返回已存储的id
if (this.map.has(str)) {
return this.map.get(str);
}
// 否则,生成一个新的ID
const id = this.counter++;
this.map.set(str, id);
return id;
},
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.fromClass}.${data.fromFn}`;
responseEntry.content = JSON.stringify(data, null, 2);
if ('Ack' === data.messageType && 'FNScheduler' === data.fromClass && 'geFnList' === data.fromFn) {
this.actionListReload(data);
}
if ('Ack' === data.messageType && 'FNScheduler' === data.fromClass && 'geMenuList' === data.fromFn) {
this.menuListReload(data);
}
if ('Ack' === data.messageType) {
this.logs.push(responseEntry);
}
if ('Report' === data.messageType) {
let reportuuid = data.fromClass + '.' + data.fromFn;
let reportId = this.getReportId(reportuuid);
// this.reports.unshift(reportId,responseEntry);
this.reports[reportId] = responseEntry;
}
};
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);
}
{
this.wsMessageIndex++;
let request = {};
request.messageId = this.wsMessageIndex;
request.timeStamp = Math.floor(Date.now() / 1000);
request.messageType = 'Command';
request.className = 'FNScheduler';
request.fnName = 'geMenuList';
request.params = {};
this.wsCall(request);
}
}
},
// disconnect
actionDisconnect() {
this.ws.close();
},
// clear logs
actionClearLogs() {
this.logs = [];
},
showKeyboard(values, param) {
// const inputElement = document.querySelector(`input[placeholder="${param}"]`);
// if (inputElement) {
// VirtualKeyboard.show(inputElement);
// this.updateDisplayContainer(inputElement);
// }
},
updateDisplayContainer(inputElement) {
const displayContainer = document.querySelector('.virtual-keyboard-display');
if (displayContainer) {
inputElement.addEventListener('input', () => {
displayContainer.textContent = inputElement.value;
});
}
},
menuListReload(response) {
let data = response.rely;
if (undefined === data) {
return;
}
this.menuList = data;
},
// 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 = JSON.parse(JSON.stringify(action)); // Replace structuredClone with JSON.parse(JSON.stringify())
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>