This commit is contained in:
Eason010212
2025-09-27 23:19:12 +08:00
parent eaf56a63d0
commit 939aad7581
4 changed files with 373 additions and 5 deletions

View File

@@ -146,7 +146,7 @@
<div class="row" >
<div class="col-xl-6">
<div class="col-xl-4">
<div class="card shadow mb-4" style="border-radius:10px;min-height:660px">
<div style="position: absolute;right:20px;top:20px" class="d-none d-md-block">
<span>主题&nbsp;</span><input id="topicFilter" class="form-control form-control-sm" style="display:inline;width:100px;min-width:100px"></input>
@@ -172,7 +172,7 @@
</div>
</div>
</div>
<div class="col-xl-6">
<div class="col-xl-4">
<div class="card shadow mb-4" style="border-radius:10px">
<div class="card-body" style="overflow:auto;height:660px">
@@ -182,6 +182,27 @@
</div>
</div>
</div>
<div class="col-xl-4">
<div class="card shadow mb-4" style="border-radius:10px;min-height:660px">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">TinyDB</h6>
</div>
<div class="card-body" style="overflow:auto;">
<table id="special_table" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>键</th>
<th>值</th>
<th>更新时间</th>
</tr>
</thead>
<tbody id="special_data">
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,3 +1,49 @@
function init_special_table(rows) {
var tableBody = $('#special_data');
tableBody.empty();
rows.forEach(function(row) {
var tr = $('<tr></tr>');
tr.append('<td>' + (row.topic || '') + '</td>');
tr.append('<td>' + (row.message || '') + '</td>');
tr.append('<td>' + (row.time || '') + '</td>');
tableBody.append(tr);
});
// 初始化DataTable如果已初始化则销毁重新初始化
if ($.fn.DataTable.isDataTable('#special_table')) {
$('#special_table').DataTable().destroy();
}
$('#special_table').DataTable({
"pageLength": 10,
"order": [[2, "desc"]],
language: {
"sProcessing": "处理中...",
"sLengthMenu": "每页 _MENU_ 项",
"sZeroRecords": "没有匹配结果",
"sInfo": "显示第 _START_ 项至 第 _END_ 项结果,共 _TOTAL_ 项",
"sInfoEmpty": "显示第 0 项至 0 项结果,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
}
},
});
}
function get_data() {
$.get('queryHook', function(res) {
if (res == 1) {
@@ -6,16 +52,26 @@ function get_data() {
$("#stop").remove()
}
$.getJSON('getData', {
}, function(res) {
var max = res["max"]
$("#prj_num").html(res['count'] + " / " + max)
$("#prj_num_bar").attr("aria-valuenow", res['count'])
$("#prj_num_bar").attr("aria-valuemax", max)
$("#prj_num_bar").css("width", (res['count'] * 100 / max) + "%")
globalRows = res["rows"]
init_table(res["rows"])
// 筛选数据topic不以$开头的存入globalRows以$开头的存入globalRows2并去掉$
globalRows = res["rows"].filter(row => !row.topic || !row.topic.startsWith('$'));
globalRows2 = res["rows"]
.filter(row => row.topic && row.topic.startsWith('$'))
.map(row => ({
...row,
topic: row.topic.substring(1) // 去掉开头的$
}));
init_table(globalRows) // 初始化表格使用非$开头的数据
sync_chart()
init_special_table(globalRows2)
})
})

203
mixio.js
View File

@@ -1290,6 +1290,209 @@ var mixioServer = async function() {
})
})
// tinyWebDB Implementation
function validateRequiredParams(req, res) {
return new Promise((resolve) => {
const { user, secret, action } = req.body;
db.get("SELECT * FROM `user` WHERE username = ?", [user], function(err, row) {
if (err) {
return res.json({ status: 'error', message: '数据库查询错误' });
}
if (row) {
if (row.password === secret) {
if (!action) {
res.json({ status: 'error', message: '缺少操作类型参数' });
return resolve(true); // 表示已处理响应
}
const validActions = ['update', 'get', 'delete', 'count', 'search'];
if (!validActions.includes(action)) {
res.json({ status: 'error', message: '无效的操作类型' });
return resolve(true);
}
return resolve(false); // 验证通过,未处理响应
} else {
res.json({ status: 'error', message: '用户名或密钥错误' });
return resolve(true);
}
} else {
res.json({ status: 'error', message: '用户名或密钥错误' });
return resolve(true);
}
});
});
}
app.post('/tinydb', async (req, res) => {
const hasError = await validateRequiredParams(req, res);
// 如果 validateRequiredParams 已经发送了响应,直接返回
if (hasError) {
return;
}
const { user, action, tag, value } = req.body;
var hash = 0,
i, chr;
for (i = 0; i < user.length; i++) {
chr = user.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0;
}
hash = Math.abs(hash) % 8
switch (action) {
case 'update':
handleUpdate(req, res, hash);
break;
case 'get':
handleGet(req, res, hash);
break;
case 'delete':
handleDelete(req, res, hash);
break;
case 'count':
handleCount(req, res, hash);
break;
case 'search':
handleSearch(req, res, hash);
break;
default:
res.json({ status: 'error', message: '未知操作类型' });
}
});
// 更新操作
function handleUpdate(req, res, hash) {
const { user, tag, value } = req.body;
if (!tag || value === undefined) {
return res.json({ status: 'error', message: '更新操作需要 tag 和 value 参数' });
}
reserveDBs[hash].get("SELECT * FROM reserve WHERE topic = ? AND userName = ?", ['$' + tag, user], (err, row) => {
if (err) {
return res.json({ status: 'error', message: '数据库查询错误' });
}
if (row) {
reserveDBs[hash].run("UPDATE reserve SET message = ?, time = CURRENT_TIMESTAMP WHERE topic = ? AND userName = ?",
[value, '$' + tag, user], function(err) {
if (err) {
return res.json({ status: 'error', message: '更新失败' });
}
res.json({ status: 'success', message: '更新成功' });
});
} else {
// 插入新记录
reserveDBs[hash].run("INSERT INTO reserve (userName, topic, message) VALUES (?, ?, ?)",
[user, '$' + tag, value], function(err) {
if (err) {
return res.json({ status: 'error', message: '插入失败' });
}
res.json({ status: 'success', message: '更新成功' });
});
}
});
}
// 读取操作
function handleGet(req, res, hash) {
const { user, tag } = req.body;
if (!tag) {
return res.json({ status: 'error', message: '读取操作需要 tag 参数' });
}
reserveDBs[hash].get("SELECT * FROM reserve WHERE topic = ? AND userName = ?", ['$' + tag, user], (err, row) => {
if (err) {
return res.json({ status: 'error', message: '数据库查询错误' });
}
if (row) {
res.json({ status: 'success', value: row.message });
} else {
res.json({ status: 'error', message: '变量不存在' });
}
});
}
// 删除操作
function handleDelete(req, res, hash) {
const { user, tag } = req.body;
if (!tag) {
return res.json({ status: 'error', message: '删除操作需要 tag 参数' });
}
reserveDBs[hash].run("DELETE FROM reserve WHERE topic = ? AND userName = ?", ['$' + tag, user], function(err) {
if (err) {
return res.json({ status: 'error', message: '删除失败' });
}
if (this.changes > 0) {
res.json({ status: 'success', message: '删除成功' });
} else {
res.json({ status: 'error', message: '变量不存在' });
}
});
}
// 计数操作
function handleCount(req, res, hash) {
const { user } = req.body;
reserveDBs[hash].get("SELECT COUNT(*) as count FROM reserve WHERE userName = ?", [user], (err, row) => {
if (err) {
return res.json({ status: 'error', message: '数据库查询错误' });
}
res.json({ status: 'success', count: row.count });
});
}
// 查询操作
function handleSearch(req, res, hash) {
const { no = 1, count = 1, tag = '', type = 'both', user} = req.body;
const startIndex = Math.max(0, parseInt(no) - 1);
const limitCount = Math.min(100, parseInt(count)); // 最多返回100条
let sql = "SELECT * FROM reserve WHERE userName = ?";
let params = [user];
if (tag) {
sql += " AND topic LIKE ?";
params.push(`%${tag}%`);
}
sql += " ORDER BY time DESC LIMIT ? OFFSET ?";
params.push(limitCount, startIndex);
reserveDBs[hash].all(sql, params, (err, rows) => {
if (err) {
console.log(err)
return res.json({ status: 'error', message: '数据库查询错误' });
}
// 筛选以$开头的tag并在返回时去掉$
const formattedResult = rows
.filter(row => row.topic && row.topic.startsWith('$')) // 筛选$开头的tag
.map(row => {
const cleanTopic = row.topic.substring(1); // 去掉开头的$
if (type === 'tag') {
return { tag: cleanTopic };
} else if (type === 'value') {
return { value: row.message };
} else {
return { tag: cleanTopic, value: row.message };
}
});
res.json({
status: 'success',
data: formattedResult
});
});
}
app.get('/api/v1/getData', function(req, res) {
try {
if (!(req.query.user && req.query.password && req.query.project && req.query.topic)) {

88
test.sh Normal file
View File

@@ -0,0 +1,88 @@
#!/bin/bash
# 设置 API 地址
API_URL="http://localhost:8081/tinydb"
echo "=== TinyWebDB API 测试 ==="
echo "服务器地址: $API_URL"
echo
# 1. 测试更新操作
echo "1. 测试更新操作:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=update&tag=test_key&value=Hello World"
echo
echo
# 2. 测试读取操作
echo "2. 测试读取操作:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=get&tag=test_key"
echo
echo
# 3. 测试计数操作
echo "3. 测试计数操作:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=count"
echo
echo
# 4. 测试查询操作
echo "4. 测试查询操作:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=search&count=5"
echo
echo
# 5. 测试删除操作
echo "5. 测试删除操作:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=delete&tag=test_key"
echo
echo
# 6. 测试批量操作
echo "6. 测试批量操作 - 插入多条数据:"
for i in {1..5}; do
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=update&tag=key_$i&value=Value $i" > /dev/null 2>&1
echo "插入 key_$i"
done
echo
# 7. 测试条件查询
echo "7. 测试条件查询 (tag包含'key'):"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=search&tag=key&count=10"
echo
echo
# 8. 测试错误情况 - 认证失败
echo "8. 测试错误情况 - 认证失败:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=wrong&secret=wrong&action=get&tag=test_key"
echo
echo
# 9. 测试错误情况 - 缺少参数
echo "9. 测试错误情况 - 缺少参数:"
curl -X POST $API_URL \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user=1371033826@qq.com&secret=20b7b5eff3bd414ad42d7870feee4f45&action=update&tag=test_key"
echo
echo
echo "=== 测试完成 ==="
# 按任意键退出功能
echo "按任意键退出..."
read -n 1 -s -r