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 @@
-
+
主题  @@ -172,7 +172,7 @@
-
+
@@ -182,6 +182,27 @@
+
+
+
+
TinyDB
+
+
+ + + + + + + + + + + +
更新时间
+
+
+
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