This commit is contained in:
Zengtudor 2025-05-11 01:40:19 +08:00
parent 51c5428a61
commit 37cc168d96
3 changed files with 167 additions and 89 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.10)
project(eew CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(webview REQUIRED)
find_package(Threads REQUIRED)

View File

@ -1,104 +1,159 @@
<!DOCTYPE html>
<html lang="zh-cn">
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Environment Variables Table</title>
<title>Environment Variables Viewer</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
body { font-family: system-ui, -apple-system, sans-serif; margin: 0; background: #f5f7fa; }
.container { max-width: 1200px; margin: 0 auto; padding: 0 16px; }
header { background: white; padding: 20px 0; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
h1 { color: #165DFF; margin: 0; }
main { padding: 24px 0; }
.card { background: white; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); padding: 16px; }
table { width: 100%; border-collapse: collapse; }
th { text-align: left; padding: 12px 16px; background: #f9fafb; color: #6b7280; font-size: 12px; text-transform: uppercase; }
td { padding: 12px 16px; border-bottom: 1px solid #e5e7eb; }
tr:last-child td { border-bottom: none; }
tr:nth-child(even) { background: #f9fafb; }
tr:hover { background: #f3f4f6; }
footer { background: #1d2129; color: white; text-align: center; padding: 20px 0; }
.loading { text-align: center; color: #9ca3af; padding: 20px 0; }
.error { text-align: center; color: #ef4444; padding: 20px 0; }
a { color: #165DFF; text-decoration: none; }
a:hover { text-decoration: underline; }
.btn {
background-color: #165DFF;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
margin-bottom: 16px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
font-size: 18px;
text-align: left;
.btn:hover {
background-color: #0E42CC;
}
th, td {
padding: 12px;
border: 1px solid #ddd;
.btn:active {
background-color: #0A3199;
}
th {
background-color: #f4f4f4;
.scrollable {
max-height: 80px;
overflow-y: auto;
max-width: 300px;
border: 1px solid #e5e7eb;
padding: 4px;
border-radius: 2px;
background-color: #f9fafb;
}
tr:nth-child(even) {
background-color: #f9f9f9;
/* 自定义滚动条样式 */
.scrollable::-webkit-scrollbar {
width: 6px;
}
tr:hover {
background-color: #f1f1f1;
.scrollable::-webkit-scrollbar-track {
background: #f1f1f1;
}
@media (max-width: 600px) {
table, thead, tbody, th, td, tr {
display: block;
}
th, td {
text-align: right;
padding: 10px;
}
th {
background-color: #f4f4f4;
position: sticky;
top: 0;
}
td {
border: none;
border-bottom: 1px solid #ddd;
}
td::before {
content: attr(data-label);
float: left;
font-weight: bold;
}
.scrollable::-webkit-scrollbar-thumb {
background: #c5c5c5;
border-radius: 3px;
}
.scrollable::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
</style>
</head>
<body>
<h1>Environment Variables</h1>
<table id="envTable">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<!-- Rows will be dynamically inserted here -->
</tbody>
</table>
<header>
<div class="container">
<h1>Environment Variables Viewer</h1>
<p>Real-time system environment configuration</p>
</div>
</header>
<script script type="module">
// TODO: async getEnvString() will be implemented elsewhere
<main class="container">
<button id="refreshBtn" class="btn">
<i class="fa fa-refresh mr-1"></i> Refresh
</button>
<div class="card">
<table id="envTable">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody id="envTableBody">
<tr>
<td colspan="2" class="loading">Loading environment variables...</td>
</tr>
</tbody>
</table>
</div>
</main>
async function refreshEnvTable() {
try {
// 调用 getEnvString 函数并解析返回值
const env = await window.getEnvString();
console.log("Environment String:", env);
<footer>
<div class="container">
<p>© 2025 Environment Variables Viewer | Author: Tudor 曾子愚</p>
<p>
<a href="https://blog.zziyu.cn" target="_blank">Blog</a> |
<a href="https://gitcode.com/Zengtudor" target="_blank">GitCode</a> |
<a href="mailto:Zengtudor@outlook.com" target="_blank">Email</a>
</p>
</div>
</footer>
// 清空表格内容
const tableBody = document.querySelector("#envTable tbody");
tableBody.innerHTML = "";
<script>
async function refreshEnvTable() {
const tableBody = document.getElementById('envTableBody');
tableBody.innerHTML = '<tr><td colspan="2" class="loading">Refreshing environment variables...</td></tr>';
try {
const env = await window.getEnvString();
tableBody.innerHTML = '';
// 填充表格
for (const [key, value] of Object.entries(env)) {
const row = document.createElement("tr");
row.innerHTML = `
<td data-label="Key">${key}</td>
<td data-label="Value">${value}</td>
if (!env || Object.keys(env).length === 0) {
tableBody.innerHTML = '<tr><td colspan="2" class="loading">No environment variables found</td></tr>';
return;
}
Object.entries(env).forEach(([key, value]) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${key}</td>
<td><div class="scrollable" title="${value}">${value}</div></td>
`;
tableBody.appendChild(row);
});
} catch (error) {
tableBody.innerHTML = `
<tr>
<td colspan="2" class="error">Failed to load: ${error.message}</td>
</tr>
`;
tableBody.appendChild(row);
}
} catch (error) {
console.error("Failed to refresh environment table:", error);
}
}
document.addEventListener('DOMContentLoaded', async () => {
await refreshEnvTable();
});
// 页面加载时刷新表格
// document.addEventListener("DOMContentLoaded", refreshEnvTable);
</script>
document.addEventListener('DOMContentLoaded', refreshEnvTable);
document.getElementById('refreshBtn').addEventListener('click', refreshEnvTable);
// Mock data for demonstration
if (!window.getEnvString) {
window.getEnvString = async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
return {
NODE_ENV: 'development',
PORT: '3000',
DB_HOST: 'localhost',
DB_USER: 'root',
DB_PASSWORD: '********',
API_KEY: 'sk-********************************',
DEBUG_MODE: 'true',
LONG_TEXT_VARIABLE: 'This is a very long text value that exceeds the normal display area. It should be scrollable within the container so users can view the entire content without truncation. This provides a better user experience when dealing with large environment variable values.'
};
};
}
</script>
</body>
</html>
</html>

View File

@ -8,6 +8,8 @@
#include <sstream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <unordered_set>
#include <utility>
#include <vector>
#include <webview/backends.hh>
@ -49,20 +51,41 @@ std::ostream&operator<<(std::ostream &os,const std::vector<T> &v){
return os;
}
std::string envKvToJsonString(const vpss_t &v){
std::stringstream ss;
const auto toJsonString = [](const std::string_view &str)->std::string{
std::stringstream ss;
for(size_t i=0;i<str.size();i++){
const std::unordered_set<char> set={'\\','\"'};
if(set.find(str[i])!=set.end()){
ss<<"\\";
}
ss<<str[i];
}
return ss.str();
};
if(v.size()==0)return "{}";
ss<<"{";
if(v.size()==1){
ss<<"\""<<toJsonString(v[0].first)<<"\":\""<<toJsonString(v[0].second)<<"\"}";
return ss.str();
}
for(size_t i = 0;i<v.size()-1;i++){
ss<<"\""<<toJsonString(v[i].first)<<"\":\""<<toJsonString(v[i].second)<<"\",";
}
ss<<"\""<<toJsonString(v[v.size()-1].first)<<"\":\""<<toJsonString(v[v.size()-1].second)<<"\"}";
return ss.str();
}
int main(const int argc,char *argv[],char *env[]){
try {
std::cout<<getEnvKv()<<'\n';
webview::webview wv(true,nullptr);
wv.set_html(html);
wv.bind("getEnvString",
[](const std::string &req)->std::string {
std::stringstream oss;
oss<<getEnvKv();
std::cout<<std::format("{{env:\"{}\"}}",getEnvKv()[0].first)<<'\n';
return std::format("{{\"env\":\"{}\"}}",getEnvKv()[0].first);
std::cout<<envKvToJsonString(getEnvKv())<<'\n';
return envKvToJsonString(getEnvKv());
});
wv.set_html(html);
wv.run();
} catch (const std::exception &e) {
std::cerr<<e.what()<<'\n';