工具完成
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
2025-06-28 22:38:49 +08:00
parent 2c668fedd0
commit 8400dbfab9
60 changed files with 23197 additions and 144 deletions

32
server/index.js Normal file
View File

@ -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}`)
})

216
server/routes/api.js Normal file
View File

@ -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(/></g, '>\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