From fe8cfd1c55ab8425bf1192ca2114a53c294f7e50 Mon Sep 17 00:00:00 2001 From: zguiy <1415466602@qq.com> Date: Sat, 28 Jun 2025 17:11:30 +0800 Subject: [PATCH 1/4] 1 --- src/App.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.vue b/src/App.vue index 58b0f21..17239c5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -11,7 +11,7 @@ import HelloWorld from './components/HelloWorld.vue' - + + + + +
+

Chrome Bookmarks Recovery Tool

+
+ +
+ + + + + +
+
+ + + +
+ +
+

Other ways to recover bookmarks

+
+ + +
+
+ + +
+
+ + +
+

Disclaimer: this is not an official Google product.

+
+ + + + + + + + + + + + + diff --git a/server/index.js b/server/index.js new file mode 100644 index 0000000..0362ef1 --- /dev/null +++ b/server/index.js @@ -0,0 +1,32 @@ +const express = require('express') +const cors = require('cors') +const path = require('path') + +const app = express() +const PORT = process.env.PORT || 3001 + +// 中间件 +app.use(cors()) +app.use(express.json()) +app.use(express.urlencoded({ extended: true })) + +// 静态文件服务 +app.use(express.static(path.join(__dirname, '../dist'))) + +// API路由 +app.use('/api', require('./routes/api')) + +// 健康检查 +app.get('/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString() }) +}) + +// 处理Vue Router的历史模式 +app.get('*', (req, res) => { + res.sendFile(path.join(__dirname, '../dist/index.html')) +}) + +// 启动服务器 +app.listen(PORT, () => { + console.log(`服务器运行在 http://localhost:${PORT}`) +}) \ No newline at end of file diff --git a/server/routes/api.js b/server/routes/api.js new file mode 100644 index 0000000..c0e4e98 --- /dev/null +++ b/server/routes/api.js @@ -0,0 +1,216 @@ +const express = require('express') +const router = express.Router() +const { promisify } = require('util') +const { exec } = require('child_process') +const execAsync = promisify(exec) + +// IP查询API +router.get('/ip/:ip?', async (req, res) => { + try { + const ip = req.params.ip || req.ip || req.connection.remoteAddress + + // 如果是IPv6的IPv4映射地址,提取IPv4部分 + const cleanIp = ip.replace(/^::ffff:/, '') + + // 使用免费的IP查询服务 + const fetch = require('node-fetch') + const response = await fetch(`http://ip-api.com/json/${cleanIp}?lang=zh-CN`) + const data = await response.json() + + if (data.status === 'success') { + res.json({ + success: true, + data: { + ip: cleanIp, + country: data.country, + region: data.regionName, + city: data.city, + isp: data.isp, + timezone: data.timezone, + lat: data.lat, + lon: data.lon + } + }) + } else { + res.json({ + success: false, + message: '无法查询该IP地址信息' + }) + } + } catch (error) { + console.error('IP查询错误:', error) + res.status(500).json({ + success: false, + message: '服务器内部错误' + }) + } +}) + +// 获取当前IP +router.get('/myip', (req, res) => { + const ip = req.ip || req.connection.remoteAddress + const cleanIp = ip.replace(/^::ffff:/, '') + + res.json({ + success: true, + data: { + ip: cleanIp + } + }) +}) + +// 代理请求API(用于HTTP测试工具) +router.post('/proxy', async (req, res) => { + try { + const { url, method = 'GET', headers = {}, body } = req.body + + if (!url) { + return res.status(400).json({ + success: false, + message: 'URL参数不能为空' + }) + } + + const fetch = require('node-fetch') + + const options = { + method: method.toUpperCase(), + headers: { + 'User-Agent': 'Vue-Tools-Kit/1.0.0', + ...headers + } + } + + if (body && ['POST', 'PUT', 'PATCH'].includes(options.method)) { + options.body = body + } + + const startTime = Date.now() + const response = await fetch(url, options) + const endTime = Date.now() + + const responseHeaders = {} + for (const [key, value] of response.headers.entries()) { + responseHeaders[key] = value + } + + const responseBody = await response.text() + + res.json({ + success: true, + data: { + status: response.status, + statusText: response.statusText, + headers: responseHeaders, + body: responseBody, + responseTime: endTime - startTime, + url: response.url + } + }) + + } catch (error) { + console.error('代理请求错误:', error) + res.status(500).json({ + success: false, + message: error.message || '请求失败' + }) + } +}) + +// Markdown转换API +router.post('/markdown/convert', (req, res) => { + try { + const { content, type } = req.body + + if (!content) { + return res.status(400).json({ + success: false, + message: '内容不能为空' + }) + } + + if (type === 'html-to-md') { + // HTML转Markdown + const TurndownService = require('turndown') + const turndownService = new TurndownService() + const markdown = turndownService.turndown(content) + + res.json({ + success: true, + data: { result: markdown } + }) + } else if (type === 'md-to-html') { + // Markdown转HTML + const { marked } = require('marked') + const html = marked(content) + + res.json({ + success: true, + data: { result: html } + }) + } else { + res.status(400).json({ + success: false, + message: '不支持的转换类型' + }) + } + + } catch (error) { + console.error('Markdown转换错误:', error) + res.status(500).json({ + success: false, + message: '转换失败: ' + error.message + }) + } +}) + +// 文件格式化API +router.post('/format/code', (req, res) => { + try { + const { content, type } = req.body + + if (!content) { + return res.status(400).json({ + success: false, + message: '内容不能为空' + }) + } + + let formatted = content + + switch (type) { + case 'json': + try { + const parsed = JSON.parse(content) + formatted = JSON.stringify(parsed, null, 2) + } catch (e) { + throw new Error('JSON格式错误') + } + break + + case 'xml': + // 简单的XML格式化 + formatted = content + .replace(/>\n<') + .replace(/^\s*\n/gm, '') + break + + default: + throw new Error('不支持的格式化类型') + } + + res.json({ + success: true, + data: { result: formatted } + }) + + } catch (error) { + console.error('代码格式化错误:', error) + res.status(500).json({ + success: false, + message: error.message || '格式化失败' + }) + } +}) + +module.exports = router \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 3e63bec..7a5b620 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,30 +1,26 @@ - - + + diff --git a/src/components/BackToTop.vue b/src/components/BackToTop.vue new file mode 100644 index 0000000..4a4a11a --- /dev/null +++ b/src/components/BackToTop.vue @@ -0,0 +1,49 @@ + + + + + \ No newline at end of file diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue deleted file mode 100644 index b58e52b..0000000 --- a/src/components/HelloWorld.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - diff --git a/src/components/LanguageToggle.vue b/src/components/LanguageToggle.vue new file mode 100644 index 0000000..d3c5edd --- /dev/null +++ b/src/components/LanguageToggle.vue @@ -0,0 +1,72 @@ + + + \ No newline at end of file diff --git a/src/components/ThemeToggle.vue b/src/components/ThemeToggle.vue new file mode 100644 index 0000000..cdd6f0f --- /dev/null +++ b/src/components/ThemeToggle.vue @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/src/components/ToolHeader.vue b/src/components/ToolHeader.vue new file mode 100644 index 0000000..c1e0b71 --- /dev/null +++ b/src/components/ToolHeader.vue @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/src/components/tools/Base64ToImage.vue b/src/components/tools/Base64ToImage.vue new file mode 100644 index 0000000..2855009 --- /dev/null +++ b/src/components/tools/Base64ToImage.vue @@ -0,0 +1,402 @@ + + + + + \ No newline at end of file diff --git a/src/components/tools/DateCalculator.vue b/src/components/tools/DateCalculator.vue new file mode 100644 index 0000000..e952f58 --- /dev/null +++ b/src/components/tools/DateCalculator.vue @@ -0,0 +1,550 @@ + + + \ No newline at end of file diff --git a/src/components/tools/EncodingConverter.vue b/src/components/tools/EncodingConverter.vue new file mode 100644 index 0000000..4b1c4d1 --- /dev/null +++ b/src/components/tools/EncodingConverter.vue @@ -0,0 +1,306 @@ +