Files
department-api/routes/docs.js
huanglinhuan 01c7b2b673 修改路由
2025-12-08 18:26:55 +08:00

167 lines
6.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const express = require('express');
const router = express.Router();
const path = require('path');
const fs = require('fs');
const sanitizeSegment = (seg) => String(seg || '').replace(/[^a-zA-Z0-9_\-]/g, '');
router.get('/list', (req, res) => {
try {
const series = sanitizeSegment(req.query.series);
const sub = sanitizeSegment(req.query.sub);
if (!series || !sub) {
return res.status(400).json({ error: '缺少必要参数 series 或 sub' });
}
const modelsDocsDir = path.join(__dirname, '..', 'uploads', 'models', series, sub, 'docs');
const legacyDocsDir = path.join(__dirname, '..', 'uploads', 'docs', series, sub);
const docsDir = fs.existsSync(modelsDocsDir) ? modelsDocsDir : legacyDocsDir;
if (!fs.existsSync(docsDir)) {
return res.json({ success: true, data: [] });
}
const entries = fs.readdirSync(docsDir, { withFileTypes: true });
const files = entries
.filter((e) => e.isFile())
.filter((e) => /\.(pdf|doc|docx|xls|xlsx|ppt|pptx)$/i.test(e.name))
.map((e) => {
const fullPath = path.join(docsDir, e.name);
let size = 0;
try {
size = fs.statSync(fullPath).size;
} catch {}
const base = docsDir === modelsDocsDir ? `/uploads/models/${series}/${sub}/docs` : `/uploads/docs/${series}/${sub}`;
const url = `${base}/${e.name}`;
return { name: e.name, url, size };
});
res.json({ success: true, data: files });
} catch (error) {
console.error('获取资料列表错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 图片列表(支持每机型统一文件夹结构)
router.get('/images', (req, res) => {
try {
const series = sanitizeSegment(req.query.series);
const sub = sanitizeSegment(req.query.sub);
if (!series || !sub) {
return res.status(400).json({ error: '缺少必要参数 series 或 sub' });
}
const candidates = [
path.join(__dirname, '..', 'uploads', 'models', series, sub, 'image'),
path.join(__dirname, '..', 'uploads', 'models', series, sub, 'images'),
path.join(__dirname, '..', 'uploads', 'images', series, sub),
path.join(__dirname, '..', 'uploads', 'image', series, sub)
];
const imgDir = candidates.find((p) => fs.existsSync(p));
if (!fs.existsSync(imgDir)) {
return res.json({ success: true, data: [] });
}
const entries = fs.readdirSync(imgDir, { withFileTypes: true });
const files = entries
.filter((e) => e.isFile())
.filter((e) => /\.(png|jpg|jpeg|gif|webp|svg)$/i.test(e.name))
.map((e) => {
const fullPath = path.join(imgDir, e.name);
let size = 0;
try { size = fs.statSync(fullPath).size; } catch {}
let base = `/uploads/images/${series}/${sub}`;
if (imgDir.includes(path.join('uploads', 'models'))) {
if (imgDir.endsWith(path.join(series, sub, 'image'))) {
base = `/uploads/models/${series}/${sub}/image`;
} else if (imgDir.endsWith(path.join(series, sub, 'images'))) {
base = `/uploads/models/${series}/${sub}/images`;
}
} else if (imgDir.includes(path.join('uploads', 'image'))) {
base = `/uploads/image/${series}/${sub}`;
}
const url = `${base}/${e.name}`;
return { name: e.name, url, size };
});
res.json({ success: true, data: files });
} catch (error) {
console.error('获取图片列表错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
module.exports = router;
// 使用相同 router 添加规格读取接口
router.get('/specs', (req, res) => {
try {
const series = sanitizeSegment(req.query.series);
const sub = sanitizeSegment(req.query.sub);
if (!series || !sub) {
return res.status(400).json({ error: '缺少必要参数 series 或 sub' });
}
const dirCandidates = [
path.join(__dirname, '..', 'uploads', 'models', series, sub, 'specs'),
path.join(__dirname, '..', 'uploads', 'specs', series, sub)
];
const parseCsvFile = (filePath) => {
const raw = fs.readFileSync(filePath, 'utf8');
const lines = raw.replace(/^\uFEFF/, '').split(/\r?\n/).filter((l) => l.trim().length);
const normalize = (s) => String(s || '').trim().replace(/^"(.*)"$/, '$1').replace(/^'(.*)'$/, '$1');
const parseLine = (l) => {
const replaced = l.replace(//g, ';').replace(//g, ',').replace(/\uff0c/g, ',').replace(/\uff1b/g, ';');
let tokens = replaced.match(/"([^"]*)"|[^,;\t]+/g) || [];
if (tokens.length < 2) {
const parts = replaced.split(/:|/);
if (parts.length >= 2) {
tokens = [parts[0], parts.slice(1).join(':')];
}
}
const key = normalize(tokens[0] || '');
const val = normalize(tokens[1] || '');
return { key, value: val };
};
return lines.map(parseLine).filter((r) => r.key.length);
};
const dirPath = dirCandidates.find((p) => fs.existsSync(p) && fs.statSync(p).isDirectory());
if (dirPath) {
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
const csvFiles = entries.filter((e) => e.isFile() && /\.csv$/i.test(String(e.name).trim()));
if (csvFiles.length) {
const sections = csvFiles.map((e) => {
const fp = path.join(dirPath, e.name);
const title = e.name.replace(/\.csv$/i, '');
return { title, rows: parseCsvFile(fp) };
});
return res.json({ success: true, data: sections });
}
}
const fileCandidates = [
path.join(__dirname, '..', 'uploads', 'models', series, sub, 'specs', 'specs.csv'),
path.join(__dirname, '..', 'uploads', 'models', series, sub, 'specs.csv'),
path.join(__dirname, '..', 'uploads', 'specs', series, `${sub}.csv`),
path.join(__dirname, '..', 'uploads', 'specs', series, sub, 'specs.csv')
];
const filePath = fileCandidates.find((p) => fs.existsSync(p));
if (!filePath) {
return res.json({ success: true, data: [] });
}
const specs = parseCsvFile(filePath);
res.json({ success: true, data: specs });
} catch (error) {
console.error('读取规格CSV错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});