From 939aad75819b4bbad165f0d53ecb10b1a5c9c407 Mon Sep 17 00:00:00 2001
From: Eason010212 <1371033826@qq.com>
Date: Sat, 27 Sep 2025 23:19:12 +0800
Subject: [PATCH] tinydb
---
ejs/data.ejs | 25 ++++++-
js/data.js | 62 +++++++++++++++-
mixio.js | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++
test.sh | 88 ++++++++++++++++++++++
4 files changed, 373 insertions(+), 5 deletions(-)
create mode 100644 test.sh
diff --git a/ejs/data.ejs b/ejs/data.ejs
index c78fa87..8a35b16 100644
--- a/ejs/data.ejs
+++ b/ejs/data.ejs
@@ -146,7 +146,7 @@
-
+
-
+
+
+
+
+
+
+
+
+ | 键 |
+ 值 |
+ 更新时间 |
+
+
+
+
+
+
+
+
+
diff --git a/js/data.js b/js/data.js
index 329594b..b292fbb 100644
--- a/js/data.js
+++ b/js/data.js
@@ -1,3 +1,49 @@
+function init_special_table(rows) {
+ var tableBody = $('#special_data');
+ tableBody.empty();
+
+ rows.forEach(function(row) {
+ var tr = $('
|
');
+ tr.append('
' + (row.topic || '') + ' | ');
+ tr.append('
' + (row.message || '') + ' | ');
+ tr.append('
' + (row.time || '') + ' | ');
+ 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)
})
})
diff --git a/mixio.js b/mixio.js
index 6b1ab74..92bbafb 100644
--- a/mixio.js
+++ b/mixio.js
@@ -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)) {
diff --git a/test.sh b/test.sh
new file mode 100644
index 0000000..ab28ab5
--- /dev/null
+++ b/test.sh
@@ -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
\ No newline at end of file