mirror of
https://github.com/ZeroCatDev/ClassworksKV.git
synced 2025-09-03 16:19:24 +00:00
Compare commits
4 Commits
f1dba22f75
...
aea47eba7d
Author | SHA1 | Date | |
---|---|---|---|
![]() |
aea47eba7d | ||
![]() |
f250deb2bb | ||
![]() |
15691b7333 | ||
![]() |
22838ee71a |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ClassworksKV",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node ./bin/www",
|
||||
|
54
routes/kv.js
54
routes/kv.js
@ -234,6 +234,60 @@ router.delete(
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* GET /:namespace/_keys
|
||||
* 获取指定命名空间下的键名列表(分页,不包括内容)
|
||||
*/
|
||||
router.get(
|
||||
"/:namespace/_keys",
|
||||
checkRestrictedUUID,
|
||||
readAuthMiddleware,
|
||||
errors.catchAsync(async (req, res, next) => {
|
||||
const { namespace } = req.params;
|
||||
const { sortBy, sortDir, limit, skip } = req.query;
|
||||
|
||||
// 构建选项
|
||||
const options = {
|
||||
sortBy: sortBy || "key",
|
||||
sortDir: sortDir || "asc",
|
||||
limit: limit ? parseInt(limit) : 100,
|
||||
skip: skip ? parseInt(skip) : 0,
|
||||
};
|
||||
|
||||
const keys = await kvStore.listKeysOnly(namespace, options);
|
||||
|
||||
// 获取总记录数
|
||||
const totalRows = await kvStore.count(namespace);
|
||||
|
||||
// 构建响应对象
|
||||
const response = {
|
||||
keys: keys,
|
||||
total_rows: totalRows,
|
||||
current_page: {
|
||||
limit: options.limit,
|
||||
skip: options.skip,
|
||||
count: keys.length,
|
||||
},
|
||||
};
|
||||
|
||||
// 如果还有更多数据,添加load_more字段
|
||||
const nextSkip = options.skip + options.limit;
|
||||
if (nextSkip < totalRows) {
|
||||
const baseUrl = `${req.baseUrl}/${namespace}/_keys`;
|
||||
const queryParams = new URLSearchParams({
|
||||
sortBy: options.sortBy,
|
||||
sortDir: options.sortDir,
|
||||
limit: options.limit,
|
||||
skip: nextSkip,
|
||||
}).toString();
|
||||
|
||||
response.load_more = `${baseUrl}?${queryParams}`;
|
||||
}
|
||||
|
||||
return res.json(response);
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* GET /:namespace
|
||||
* 获取指定命名空间下的所有键名及元数据列表
|
||||
|
@ -160,6 +160,36 @@ class KVStore {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定命名空间下的键名列表(不包括内容)
|
||||
* @param {string} namespace - 命名空间
|
||||
* @param {object} options - 查询选项
|
||||
* @returns {Array} 键名列表
|
||||
*/
|
||||
async listKeysOnly(namespace, options = {}) {
|
||||
const { sortBy = "key", sortDir = "asc", limit = 100, skip = 0 } = options;
|
||||
|
||||
// 构建排序条件
|
||||
const orderBy = {};
|
||||
orderBy[sortBy] = sortDir.toLowerCase();
|
||||
|
||||
// 查询以命名空间开头的所有键,只选择键名
|
||||
const items = await prisma.kVStore.findMany({
|
||||
where: {
|
||||
namespace: namespace,
|
||||
},
|
||||
select: {
|
||||
key: true,
|
||||
},
|
||||
orderBy,
|
||||
take: limit,
|
||||
skip: skip,
|
||||
});
|
||||
|
||||
// 只返回键名数组
|
||||
return items.map((item) => item.key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计指定命名空间下的键值对数量
|
||||
* @param {string} namespace - 命名空间
|
||||
|
@ -20,37 +20,6 @@
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.form-section {
|
||||
background-color: #f0f8ff;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
margin-bottom: 10px;
|
||||
font-family: monospace;
|
||||
}
|
||||
button {
|
||||
padding: 10px 15px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
#response {
|
||||
white-space: pre-wrap;
|
||||
background-color: #f5f5f5;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
margin-top: 20px;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@ -62,70 +31,6 @@
|
||||
<div class="readme-content">
|
||||
<pre><%= readmeValue.readme %></pre>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h2>批量数据导入测试</h2>
|
||||
<form id="batchImportForm">
|
||||
<div>
|
||||
<label for="namespace">命名空间:</label>
|
||||
<input type="text" id="namespace" name="namespace" placeholder="输入命名空间" required>
|
||||
<button type="button" id="generateUUID">生成UUID</button>
|
||||
</div>
|
||||
<div>
|
||||
<label for="data">JSON数据 (格式: {"key":{}, "key2":{}})</label>
|
||||
<textarea id="data" name="data" placeholder='{"key1": {"value": "test1"}, "key2": {"value": "test2"}}' required></textarea>
|
||||
</div>
|
||||
<button type="submit">导入数据</button>
|
||||
</form>
|
||||
<div>
|
||||
<h3>响应结果:</h3>
|
||||
<pre id="response"></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('generateUUID').addEventListener('click', async function() {
|
||||
try {
|
||||
const response = await fetch('/_uuid', {
|
||||
method: 'GET'
|
||||
});
|
||||
const data = await response.json();
|
||||
document.getElementById('namespace').value = data.namespace;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
document.getElementById('response').textContent = '获取UUID失败: ' + error.message;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('batchImportForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
const namespace = document.getElementById('namespace').value;
|
||||
let jsonData;
|
||||
|
||||
try {
|
||||
jsonData = JSON.parse(document.getElementById('data').value);
|
||||
} catch (error) {
|
||||
document.getElementById('response').textContent = 'JSON解析错误: ' + error.message;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/${namespace}/_batchimport`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(jsonData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
document.getElementById('response').textContent = JSON.stringify(result, null, 2);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
document.getElementById('response').textContent = '请求失败: ' + error.message;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user