const http = require ( 'http' ) ;
const fs = require ( 'fs' ) ;
const path = require ( 'path' ) ;
const mysql = require ( 'mysql2/promise' ) ;
const OssUploader = require ( './oss-uploader' ) ;
const port = 3008 ;
// 数据库配置
const dbConfig = {
host : process . env . DB_HOST || '1.95.162.61' ,
user : process . env . DB_USER || 'root' ,
password : process . env . DB_PASSWORD || 'schl@2025' ,
database : process . env . DB_NAME || 'wechat_app' ,
waitForConnections : true ,
connectionLimit : 20 ,
queueLimit : 0 ,
connectTimeout : 10000 ,
timezone : '+08:00'
} ;
// 创建数据库连接池
const pool = mysql . createPool ( dbConfig ) ;
// 测试数据库连接
async function testDbConnection ( ) {
try {
const connection = await pool . getConnection ( ) ;
console . log ( '数据库连接成功' ) ;
connection . release ( ) ;
} catch ( error ) {
console . error ( '数据库连接失败:' , error . message ) ;
}
}
testDbConnection ( ) ;
const server = http . createServer ( async ( req , res ) => {
// 处理GET请求,获取最新的合格证信息
if ( req . method === 'GET' && req . url === '/getLatestCertificate' ) {
try {
// 从数据库获取最新的合格证信息
const [ rows ] = await pool . execute (
'SELECT company as subjectName, phoneNumber as contact, productName, grossWeight as weight, commitBasis as basis, origin, DATE_FORMAT(issueDate, "%Y-%m-%d") as date, signature FROM certificate ORDER BY id DESC LIMIT 1'
) ;
const certificate = rows . length > 0 ? rows [ 0 ] : null ;
// 返回成功响应
res . writeHead ( 200 , {
'Content-Type' : 'application/json' ,
'Access-Control-Allow-Origin' : '*' ,
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS' ,
'Access-Control-Allow-Headers' : 'Content-Type'
} ) ;
res . end ( JSON . stringify ( { success : true , certificate } ) ) ;
} catch ( error ) {
console . error ( '获取合格证信息失败:' , error . message ) ;
res . writeHead ( 500 , {
'Content-Type' : 'application/json' ,
'Access-Control-Allow-Origin' : '*' ,
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS' ,
'Access-Control-Allow-Headers' : 'Content-Type'
} ) ;
res . end ( JSON . stringify ( { success : false , error : '获取失败,请重试' } ) ) ;
}
return ;
}
// 处理POST请求
if ( req . method === 'POST' && req . url === '/submit' ) {
try {
let body = '' ;
req . on ( 'data' , chunk => {
body += chunk . toString ( ) ;
} ) ;
req . on ( 'end' , async ( ) => {
// 解析表单数据
const formData = new URLSearchParams ( body ) ;
const certificate = {
subjectName : formData . get ( 'subjectName' ) ,
contact : formData . get ( 'contact' ) ,
productName : formData . get ( 'productName' ) ,
weight : formData . get ( 'weight' ) ,
basis : formData . get ( 'basis' ) ,
origin : formData . get ( 'origin' ) ,
date : formData . get ( 'date' ) ,
signature : formData . get ( 'signature' )
} ;
// 处理手写签名,上传到OSS
let signatureUrl = null ;
if ( certificate . signature ) {
try {
// 从base64字符串中提取图片数据
const base64Data = certificate . signature . replace ( /^data:image\/png;base64,/ , '' ) ;
const buffer = Buffer . from ( base64Data , 'base64' ) ;
// 生成唯一的文件名,包含合格证信息的标识
const timestamp = Date . now ( ) ;
const filename = ` certificate_signature_ ${ timestamp } .png ` ;
// 上传到OSS,指定文件夹为certificate/signatures
signatureUrl = await OssUploader . uploadBuffer ( buffer , filename , 'certificate/signatures' , 'image' ) ;
console . log ( '手写签名上传到OSS成功:' , signatureUrl ) ;
} catch ( error ) {
console . error ( '上传手写签名到OSS失败:' , error . message ) ;
// 即使上传失败,也继续处理,将签名数据存储为base64
signatureUrl = certificate . signature ;
}
}
// 插入数据到数据库
await pool . execute (
'INSERT INTO certificate (company, phoneNumber, productName, grossWeight, commitBasis, origin, issueDate, signature) VALUES (?, ?, ?, ?, ?, ?, ?, ?)' ,
[ certificate . subjectName , certificate . contact , certificate . productName , certificate . weight , certificate . basis , certificate . origin , certificate . date , signatureUrl ]
) ;
// 返回成功响应,确保返回的signature是OSS URL
const responseCertificate = {
... certificate ,
signature : signatureUrl
} ;
res . writeHead ( 200 , {
'Content-Type' : 'application/json' ,
'Access-Control-Allow-Origin' : '*' ,
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS' ,
'Access-Control-Allow-Headers' : 'Content-Type'
} ) ;
res . end ( JSON . stringify ( { success : true , certificate : responseCertificate } ) ) ;
} ) ;
} catch ( error ) {
console . error ( '保存合格证信息失败:' , error . message ) ;
res . writeHead ( 500 , {
'Content-Type' : 'application/json' ,
'Access-Control-Allow-Origin' : '*' ,
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS' ,
'Access-Control-Allow-Headers' : 'Content-Type'
} ) ;
res . end ( JSON . stringify ( { success : false , error : '保存失败,请重试' } ) ) ;
}
return ;
}
// 处理GET请求
// 解析请求路径
let filePath = '.' + req . url ;
if ( filePath === './' ) {
filePath = './certificate.html' ;
}
// 获取文件扩展名
const extname = String ( path . extname ( filePath ) ) . toLowerCase ( ) ;
// 定义MIME类型
const mimeTypes = {
'.html' : 'text/html' ,
'.js' : 'text/javascript' ,
'.css' : 'text/css' ,
'.json' : 'application/json' ,
'.png' : 'image/png' ,
'.jpg' : 'image/jpg' ,
'.gif' : 'image/gif' ,
'.svg' : 'image/svg+xml' ,
'.wav' : 'audio/wav' ,
'.mp4' : 'video/mp4' ,
'.woff' : 'application/font-woff' ,
'.ttf' : 'application/font-ttf' ,
'.eot' : 'application/vnd.ms-fontobject' ,
'.otf' : 'application/font-otf' ,
'.wasm' : 'application/wasm'
} ;
// 获取对应的MIME类型
const contentType = mimeTypes [ extname ] || 'application/octet-stream' ;
// 读取文件
fs . readFile ( filePath , ( error , content ) => {
if ( error ) {
if ( error . code == 'ENOENT' ) {
// 文件不存在
fs . readFile ( './404.html' , ( error , content ) => {
res . writeHead ( 404 , { 'Content-Type' : 'text/html' } ) ;
res . end ( content , 'utf-8' ) ;
} ) ;
} else {
// 服务器错误
res . writeHead ( 500 ) ;
res . end ( 'Sorry, check with the site admin for error: ' + error . code + ' ..\n' ) ;
res . end ( ) ;
}
} else {
// 成功读取文件
res . writeHead ( 200 , { 'Content-Type' : contentType } ) ;
res . end ( content , 'utf-8' ) ;
}
} ) ;
} ) ;
// 启动服务器
server . listen ( port , ( ) => {
console . log ( ` Server running at http://localhost: ${ port } / ` ) ;
} ) ;
console . log ( ` Server starting on port ${ port } ... ` ) ;