init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、 antdesign(管理后台)、landingpage(营销落地页)、 数据库 SQL 和配置文件。
This commit is contained in:
36
webapp/scripts/dev.sh
Executable file
36
webapp/scripts/dev.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 尝试的端口列表
|
||||
PORTS=(3000 3001 3007 3008 3009)
|
||||
|
||||
# 检查端口是否被占用
|
||||
check_port() {
|
||||
local port=$1
|
||||
if nc -z localhost $port 2>/dev/null || curl -s http://localhost:$port >/dev/null 2>&1; then
|
||||
return 1 # 端口被占用
|
||||
else
|
||||
return 0 # 端口可用
|
||||
fi
|
||||
}
|
||||
|
||||
# 查找可用端口
|
||||
find_available_port() {
|
||||
for port in "${PORTS[@]}"; do
|
||||
if check_port $port; then
|
||||
echo $port
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# 如果预定义端口都被占用,随机选择一个
|
||||
echo $((3000 + RANDOM % 1000))
|
||||
return 0
|
||||
}
|
||||
|
||||
# 查找可用端口
|
||||
AVAILABLE_PORT=$(find_available_port)
|
||||
|
||||
echo "🚀 Starting dev server on port $AVAILABLE_PORT..."
|
||||
|
||||
# 启动开发服务器
|
||||
npx next dev -H 0.0.0.0 -p $AVAILABLE_PORT
|
||||
103
webapp/scripts/optimize-svg.js
Normal file
103
webapp/scripts/optimize-svg.js
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { optimize } = require('svgo');
|
||||
|
||||
// SVG优化配置
|
||||
const svgoConfig = {
|
||||
multipass: true,
|
||||
plugins: [
|
||||
{
|
||||
name: 'preset-default',
|
||||
params: {
|
||||
overrides: {
|
||||
removeViewBox: false,
|
||||
cleanupIds: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
'removeDimensions',
|
||||
'removeStyleElement',
|
||||
'removeScriptElement',
|
||||
'removeComments',
|
||||
'removeMetadata',
|
||||
'removeEditorsNSData',
|
||||
'cleanupListOfValues',
|
||||
'convertStyleToAttrs',
|
||||
'removeEmptyContainers',
|
||||
'mergePaths',
|
||||
'convertShapeToPath',
|
||||
'sortAttrs',
|
||||
'removeDimensions',
|
||||
],
|
||||
};
|
||||
|
||||
// 递归遍历目录
|
||||
function walkDir(dir, callback) {
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
walkDir(filePath, callback);
|
||||
} else if (path.extname(file) === '.svg') {
|
||||
callback(filePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 优化单个SVG文件
|
||||
function optimizeSvg(filePath) {
|
||||
try {
|
||||
const svgContent = fs.readFileSync(filePath, 'utf8');
|
||||
const originalSize = Buffer.byteLength(svgContent, 'utf8');
|
||||
|
||||
const result = optimize(svgContent, {
|
||||
path: filePath,
|
||||
...svgoConfig,
|
||||
});
|
||||
|
||||
const optimizedSize = Buffer.byteLength(result.data, 'utf8');
|
||||
const savings = ((1 - optimizedSize / originalSize) * 100).toFixed(1);
|
||||
|
||||
fs.writeFileSync(filePath, result.data);
|
||||
|
||||
console.log(`✓ ${path.relative(process.cwd(), filePath)}: ${originalSize}B → ${optimizedSize}B (节省 ${savings}%)`);
|
||||
|
||||
return { originalSize, optimizedSize, savings: parseFloat(savings) };
|
||||
} catch (error) {
|
||||
console.error(`✗ 处理文件失败: ${filePath}`, error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 主函数
|
||||
function main() {
|
||||
const publicDir = path.join(process.cwd(), 'public');
|
||||
|
||||
console.log('开始优化SVG文件...\n');
|
||||
|
||||
let totalOriginal = 0;
|
||||
let totalOptimized = 0;
|
||||
let fileCount = 0;
|
||||
|
||||
walkDir(publicDir, (filePath) => {
|
||||
const result = optimizeSvg(filePath);
|
||||
if (result) {
|
||||
totalOriginal += result.originalSize;
|
||||
totalOptimized += result.optimizedSize;
|
||||
fileCount++;
|
||||
}
|
||||
});
|
||||
|
||||
const totalSavings = ((1 - totalOptimized / totalOriginal) * 100).toFixed(1);
|
||||
|
||||
console.log('\n优化完成!');
|
||||
console.log(`处理文件: ${fileCount} 个`);
|
||||
console.log(`原始大小: ${(totalOriginal / 1024).toFixed(2)} KB`);
|
||||
console.log(`优化后: ${(totalOptimized / 1024).toFixed(2)} KB`);
|
||||
console.log(`总共节省: ${totalSavings}% (${((totalOriginal - totalOptimized) / 1024).toFixed(2)} KB)`);
|
||||
}
|
||||
|
||||
main();
|
||||
84
webapp/scripts/start-with-port.js
Normal file
84
webapp/scripts/start-with-port.js
Normal file
@@ -0,0 +1,84 @@
|
||||
const { spawn } = require('child_process');
|
||||
const net = require('net');
|
||||
|
||||
const DEFAULT_PORT = 3000;
|
||||
const MAX_PORT = 3020;
|
||||
|
||||
function checkPort(port) {
|
||||
return new Promise((resolve) => {
|
||||
const server = net.createServer();
|
||||
|
||||
server.once('error', (err) => {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
resolve(false);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
|
||||
server.once('listening', () => {
|
||||
server.close();
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
server.listen(port, '0.0.0.0');
|
||||
});
|
||||
}
|
||||
|
||||
async function findAvailablePort(startPort = DEFAULT_PORT) {
|
||||
for (let port = startPort; port <= MAX_PORT; port++) {
|
||||
const isAvailable = await checkPort(port);
|
||||
if (isAvailable) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
throw new Error(`No available port found between ${startPort} and ${MAX_PORT}`);
|
||||
}
|
||||
|
||||
async function startServer() {
|
||||
try {
|
||||
const port = await findAvailablePort(DEFAULT_PORT);
|
||||
|
||||
if (port !== DEFAULT_PORT) {
|
||||
console.log(`Port ${DEFAULT_PORT} is in use, using port ${port} instead`);
|
||||
} else {
|
||||
console.log(`Starting server on port ${port}`);
|
||||
}
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const command = args[0] || 'next';
|
||||
const commandArgs = args.slice(1);
|
||||
|
||||
const child = spawn(command, [...commandArgs, '-p', String(port), '-H', '0.0.0.0'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
env: {
|
||||
...process.env,
|
||||
PORT: String(port)
|
||||
}
|
||||
});
|
||||
|
||||
child.on('error', (error) => {
|
||||
console.error('Failed to start server:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
child.on('exit', (code) => {
|
||||
process.exit(code || 0);
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
child.kill('SIGINT');
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
child.kill('SIGTERM');
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
startServer();
|
||||
Reference in New Issue
Block a user