V0.21.10.250611_alpha:数据监控单次注入功能已可用
This commit is contained in:
parent
3958965fbf
commit
1e2581a239
Binary file not shown.
@ -213,6 +213,9 @@ protected:
|
||||
while (std::getline(ss, item, ',')) {
|
||||
items.push_back(item);
|
||||
}
|
||||
if (items.size() != getArrayWholeSize<T>()) {
|
||||
return;
|
||||
}
|
||||
T temp;
|
||||
setStdArrayFromString(temp, items, 0);
|
||||
data = temp;
|
||||
|
@ -199,7 +199,7 @@ private:
|
||||
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, std::string>
|
||||
|| std::is_convertible_v<T, std::string> || std::is_same_v<T, char *>
|
||||
|| std::is_same_v<T, const char *>,
|
||||
"错误码:010211001,不支持的类型转换,详见XNLogger.cpp:line 199");
|
||||
"A01021001: 不支持的类型转换,详见XNLogger.cpp:line 199");
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ private:
|
||||
static std::string formatMessage(const std::string &message, Args &&...args)
|
||||
{
|
||||
static_assert(sizeof...(Args) <= 9,
|
||||
"错误码:010211002,单条日志参数数量超过限制,详见XNLogger.cpp:line 216");
|
||||
"A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216");
|
||||
|
||||
std::string result = message;
|
||||
// 使用初始化列表展开参数包
|
||||
|
@ -43,3 +43,14 @@ constexpr size_t getTypeSize()
|
||||
return sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t getArrayWholeSize()
|
||||
{
|
||||
if constexpr (is_std_array_v<T>) {
|
||||
// 对于std::array,计算所有元素的总大小
|
||||
return getArrayWholeSize<typename T::value_type>() * array_size_v<T>;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +213,9 @@ protected:
|
||||
while (std::getline(ss, item, ',')) {
|
||||
items.push_back(item);
|
||||
}
|
||||
if (items.size() != getArrayWholeSize<T>()) {
|
||||
return;
|
||||
}
|
||||
T temp;
|
||||
setStdArrayFromString(temp, items, 0);
|
||||
data = temp;
|
||||
|
@ -43,3 +43,14 @@ constexpr size_t getTypeSize()
|
||||
return sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t getArrayWholeSize()
|
||||
{
|
||||
if constexpr (is_std_array_v<T>) {
|
||||
// 对于std::array,计算所有元素的总大小
|
||||
return getArrayWholeSize<typename T::value_type>() * array_size_v<T>;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -196,23 +196,154 @@ class DataMonitor extends HTMLElement {
|
||||
<td title="${item.InterfaceName}">${item.InterfaceName}</td>
|
||||
<td title="${item.ModelStructName}">${item.ModelStructName}</td>
|
||||
<td class="data-cell" title="-">-</td>
|
||||
<td title="-">-</td>
|
||||
<td>
|
||||
<input type="text"
|
||||
class="inject-input"
|
||||
value=""
|
||||
placeholder="输入注入值"
|
||||
data-interface="${item.InterfaceName}"
|
||||
data-struct="${item.ModelStructName}">
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="action-button plot" data-interface="${item.InterfaceName}" data-struct="${item.ModelStructName}">绘图</button>
|
||||
<button class="action-button">注入一次</button>
|
||||
<button class="action-button">连续注入</button>
|
||||
<button class="action-button inject-once" data-interface="${item.InterfaceName}" data-struct="${item.ModelStructName}">注入一次</button>
|
||||
<button class="action-button inject-continuous" data-interface="${item.ModelStructName}" data-struct="${item.ModelStructName}">连续注入</button>
|
||||
<button class="action-button delete" data-interface="${item.InterfaceName}" data-struct="${item.ModelStructName}">删除</button>
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
|
||||
// 添加删除按钮事件
|
||||
// 为输入框绑定事件
|
||||
const input = tr.querySelector('.inject-input');
|
||||
input.addEventListener('input', (e) => {
|
||||
const value = e.target.value;
|
||||
const interfaceName = e.target.dataset.interface;
|
||||
const modelStructName = e.target.dataset.struct;
|
||||
|
||||
// 检查接口类型
|
||||
const isArray = this.isInterfaceArray(interfaceName, modelStructName);
|
||||
|
||||
// 只允许数字、小数点、负号和逗号
|
||||
const validValue = value.replace(/[^0-9.,-]/g, '');
|
||||
if (value !== validValue) {
|
||||
e.target.value = validValue;
|
||||
}
|
||||
|
||||
// 验证格式
|
||||
const isValid = this.validateInjectValue(validValue, isArray, interfaceName, modelStructName);
|
||||
e.target.classList.toggle('invalid', !isValid);
|
||||
|
||||
// 实时更新表格数据
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
if (row) {
|
||||
row.InjectValue = validValue;
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener('change', (e) => {
|
||||
const interfaceName = e.target.dataset.interface;
|
||||
const modelStructName = e.target.dataset.struct;
|
||||
const value = e.target.value;
|
||||
|
||||
// 检查接口类型
|
||||
const isArray = this.isInterfaceArray(interfaceName, modelStructName);
|
||||
|
||||
// 验证格式
|
||||
if (!this.validateInjectValue(value, isArray, interfaceName, modelStructName)) {
|
||||
e.target.value = '';
|
||||
// 清空表格数据中的注入值
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
if (row) {
|
||||
row.InjectValue = '';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新表格数据
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
if (row) {
|
||||
row.InjectValue = value;
|
||||
}
|
||||
});
|
||||
|
||||
// 为按钮绑定事件
|
||||
const deleteButton = tr.querySelector('.action-button.delete');
|
||||
deleteButton.addEventListener('click', () => {
|
||||
this.handleDelete(item.InterfaceName, item.ModelStructName);
|
||||
});
|
||||
|
||||
const plotButton = tr.querySelector('.action-button.plot');
|
||||
plotButton.addEventListener('click', () => {
|
||||
this.handlePlot(item.InterfaceName, item.ModelStructName);
|
||||
});
|
||||
|
||||
const injectButton = tr.querySelector('.action-button.inject-once');
|
||||
injectButton.addEventListener('click', async () => {
|
||||
// 检查监控状态
|
||||
const statusIndicator = this.shadowRoot.getElementById('statusIndicator');
|
||||
if (!statusIndicator || !statusIndicator.classList.contains('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === item.InterfaceName &&
|
||||
r.ModelStructName === item.ModelStructName
|
||||
);
|
||||
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!row.InjectValue || row.InjectValue.trim() === '') {
|
||||
alert('请先输入注入值');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查接口类型和注入值格式
|
||||
const isArray = this.isInterfaceArray(item.InterfaceName, item.ModelStructName);
|
||||
if (!this.validateInjectValue(row.InjectValue, isArray, item.InterfaceName, item.ModelStructName)) {
|
||||
alert(isArray ? '请输入正确格式的数组数据(用逗号分隔的数字)' : '请输入单个数字');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 构造接口数据
|
||||
const interfaceData = {
|
||||
[item.InterfaceName]: row.InjectValue
|
||||
};
|
||||
|
||||
// 调用注入接口
|
||||
const response = await fetch('/api/data-monitor/inject', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
structName: item.ModelStructName,
|
||||
interfaceNameAndData: JSON.stringify(interfaceData)
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
if (!result.success) {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注入失败:', error);
|
||||
alert(`注入失败: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
}
|
||||
@ -915,6 +1046,29 @@ class DataMonitor extends HTMLElement {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.inject-input {
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.inject-input:focus {
|
||||
border-color: #1890ff;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
|
||||
.inject-input.invalid {
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
|
||||
.inject-input.invalid:focus {
|
||||
box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.2);
|
||||
}
|
||||
|
||||
.floating-chart-window {
|
||||
position: fixed;
|
||||
width: 400px;
|
||||
@ -1034,22 +1188,31 @@ class DataMonitor extends HTMLElement {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${this.tableData.map(row => `
|
||||
${this.tableData.map(row => {
|
||||
return `
|
||||
<tr>
|
||||
<td title="${row.InterfaceName}">${row.InterfaceName}</td>
|
||||
<td title="${row.ModelStructName}">${row.ModelStructName}</td>
|
||||
<td class="data-cell" title="${this.formatMonitorData(row.monitorData)}">${this.formatMonitorData(row.monitorData)}</td>
|
||||
<td title="${row.InjectValue || '-'}">${row.InjectValue || '-'}</td>
|
||||
<td>
|
||||
<input type="text"
|
||||
class="inject-input"
|
||||
value="${row.InjectValue || ''}"
|
||||
placeholder="输入注入值"
|
||||
data-interface="${row.InterfaceName}"
|
||||
data-struct="${row.ModelStructName}">
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="action-button plot" data-interface="${row.InterfaceName}" data-struct="${row.ModelStructName}">绘图</button>
|
||||
<button class="action-button">注入一次</button>
|
||||
<button class="action-button">连续注入</button>
|
||||
<button class="action-button inject-once" data-interface="${row.InterfaceName}" data-struct="${row.ModelStructName}">注入一次</button>
|
||||
<button class="action-button inject-continuous" data-interface="${row.InterfaceName}" data-struct="${row.ModelStructName}">连续注入</button>
|
||||
<button class="action-button delete" data-interface="${row.InterfaceName}" data-struct="${row.ModelStructName}">删除</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
`;
|
||||
}).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -1057,6 +1220,8 @@ class DataMonitor extends HTMLElement {
|
||||
</div>
|
||||
`;
|
||||
|
||||
const injectInputs = this.shadowRoot.querySelectorAll('.inject-input');
|
||||
|
||||
// 搜索框事件
|
||||
const searchInput = this.shadowRoot.querySelector('.search-input');
|
||||
if (searchInput) {
|
||||
@ -1106,6 +1271,136 @@ class DataMonitor extends HTMLElement {
|
||||
});
|
||||
});
|
||||
|
||||
// 添加注入值输入框的事件处理
|
||||
injectInputs.forEach(input => {
|
||||
|
||||
// 添加输入验证
|
||||
input.addEventListener('input', (e) => {
|
||||
const value = e.target.value;
|
||||
const interfaceName = e.target.dataset.interface;
|
||||
const modelStructName = e.target.dataset.struct;
|
||||
|
||||
// 检查接口类型
|
||||
const isArray = this.isInterfaceArray(interfaceName, modelStructName);
|
||||
|
||||
// 只允许数字、小数点、负号和逗号
|
||||
const validValue = value.replace(/[^0-9.,-]/g, '');
|
||||
if (value !== validValue) {
|
||||
e.target.value = validValue;
|
||||
}
|
||||
|
||||
// 验证格式
|
||||
const isValid = this.validateInjectValue(validValue, isArray, interfaceName, modelStructName);
|
||||
e.target.classList.toggle('invalid', !isValid);
|
||||
|
||||
// 实时更新表格数据
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
if (row) {
|
||||
row.InjectValue = validValue;
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener('change', (e) => {
|
||||
const interfaceName = e.target.dataset.interface;
|
||||
const modelStructName = e.target.dataset.struct;
|
||||
const value = e.target.value;
|
||||
|
||||
// 检查接口类型
|
||||
const isArray = this.isInterfaceArray(interfaceName, modelStructName);
|
||||
|
||||
// 验证格式
|
||||
if (!this.validateInjectValue(value, isArray, interfaceName, modelStructName)) {
|
||||
e.target.value = '';
|
||||
// 清空表格数据中的注入值
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
if (row) {
|
||||
row.InjectValue = '';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新表格数据
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
if (row) {
|
||||
row.InjectValue = value;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 添加注入一次按钮的事件委托
|
||||
table.addEventListener('click', async (e) => {
|
||||
const injectButton = e.target.closest('.action-button.inject-once');
|
||||
if (injectButton) {
|
||||
// 检查监控状态
|
||||
const statusIndicator = this.shadowRoot.getElementById('statusIndicator');
|
||||
if (!statusIndicator || !statusIndicator.classList.contains('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const interfaceName = injectButton.dataset.interface;
|
||||
const modelStructName = injectButton.dataset.struct;
|
||||
|
||||
// 获取对应的注入值
|
||||
const row = this.tableData.find(r =>
|
||||
r.InterfaceName === interfaceName &&
|
||||
r.ModelStructName === modelStructName
|
||||
);
|
||||
|
||||
if (!row) {
|
||||
console.error('未找到对应的行数据');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!row.InjectValue || row.InjectValue.trim() === '') {
|
||||
alert('请先输入注入值');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查接口类型和注入值格式
|
||||
const isArray = this.isInterfaceArray(interfaceName, modelStructName);
|
||||
if (!this.validateInjectValue(row.InjectValue, isArray, interfaceName, modelStructName)) {
|
||||
alert(isArray ? '请输入正确格式的数组数据(用逗号分隔的数字)' : '请输入单个数字');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 构造接口数据
|
||||
const interfaceData = {
|
||||
[interfaceName]: row.InjectValue
|
||||
};
|
||||
|
||||
// 调用注入接口
|
||||
const response = await fetch('/api/data-monitor/inject', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
structName: modelStructName,
|
||||
interfaceNameAndData: JSON.stringify(interfaceData)
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
if (!result.success) {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注入失败:', error);
|
||||
alert(`注入失败: ${error.message}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 添加删除按钮的事件委托
|
||||
table.addEventListener('click', (e) => {
|
||||
const deleteButton = e.target.closest('.action-button.delete');
|
||||
@ -1127,6 +1422,69 @@ class DataMonitor extends HTMLElement {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 验证注入值的格式
|
||||
* @param {string} value - 要验证的值
|
||||
* @param {boolean} isArray - 是否为数组类型
|
||||
* @param {string} interfaceName - 接口名称
|
||||
* @param {string} modelStructName - 结构体名称
|
||||
* @returns {boolean} 是否有效
|
||||
*/
|
||||
validateInjectValue(value, isArray = false, interfaceName = '', modelStructName = '') {
|
||||
if (!value) return true; // 空值视为有效
|
||||
|
||||
// 检查是否包含非法字符
|
||||
if (/[^0-9.,-]/.test(value)) return false;
|
||||
|
||||
// 检查逗号分隔的数字
|
||||
const numbers = value.split(',');
|
||||
|
||||
// 如果不是数组类型,不应该有逗号
|
||||
if (!isArray && numbers.length > 1) return false;
|
||||
|
||||
// 验证每个数字的格式
|
||||
for (const num of numbers) {
|
||||
if (num && !/^-?\d*\.?\d*$/.test(num)) return false;
|
||||
}
|
||||
|
||||
// 如果是数组类型,验证数组大小
|
||||
if (isArray && interfaceName && modelStructName) {
|
||||
const interfaceInfo = this.interfaces.find(item =>
|
||||
item.InterfaceName === interfaceName &&
|
||||
item.ModelStructName === modelStructName
|
||||
);
|
||||
|
||||
if (interfaceInfo) {
|
||||
const size1 = interfaceInfo.InterfaceArraySize_1 || 0;
|
||||
const size2 = interfaceInfo.InterfaceArraySize_2 || 0;
|
||||
const expectedSize = size2 <= 1 ? size1 : size1 * size2;
|
||||
|
||||
if (numbers.length !== expectedSize) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 检查接口是否为数组类型
|
||||
* @param {string} interfaceName - 接口名称
|
||||
* @param {string} modelStructName - 结构体名称
|
||||
* @returns {boolean} 是否为数组类型
|
||||
*/
|
||||
isInterfaceArray(interfaceName, modelStructName) {
|
||||
// 从接口数据中查找对应的接口信息
|
||||
const interfaceInfo = this.interfaces.find(item =>
|
||||
item.InterfaceName === interfaceName &&
|
||||
item.ModelStructName === modelStructName
|
||||
);
|
||||
|
||||
// 如果找到接口信息,检查是否为数组类型
|
||||
return interfaceInfo ? interfaceInfo.InterfaceIsArray : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 处理删除按钮点击事件
|
||||
* @param {string} interfaceName - 接口名称
|
||||
|
Loading…
x
Reference in New Issue
Block a user