modex/index.vue 分割
This commit is contained in:
@@ -13,6 +13,7 @@ const { authMiddleware } = require('../middleware/auth');
|
||||
const { fetchAndValidateCurve } = require('../services/curveClient');
|
||||
const { uploadMeasurementToS3, getMeasurementFromS3 } = require('../services/measurementStorage');
|
||||
const { getEqCacheKeys, getEqCacheField } = require('../services/eqCacheStorage');
|
||||
const { fetchFromSquigLink, downloadTxtFile } = require('../services/squiglink');
|
||||
|
||||
/**
|
||||
* 将 TXT 频响文件内容转换为 CSV 格式
|
||||
@@ -303,6 +304,70 @@ router.get('/api/models/:model_id', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/models/squiglink-fetch — 从 squig.link share URL 抓取频响数据
|
||||
router.post('/api/models/squiglink-fetch', async (req, res) => {
|
||||
try {
|
||||
const { share_url, selected_file } = req.body;
|
||||
if (!share_url) {
|
||||
return res.json(ApiResponse.error('缺少 share_url 参数'));
|
||||
}
|
||||
|
||||
logger.info(`SquigLink fetch: ${share_url}${selected_file ? ' (selected=' + selected_file + ')' : ''}`);
|
||||
|
||||
// 如果用户从候选列表中选择了特定文件,直接下载
|
||||
if (selected_file) {
|
||||
const { parseShareUrl, detectFormFromUrl } = require('../services/squiglink');
|
||||
const { baseUrl } = parseShareUrl(share_url);
|
||||
const [downloadResult, detectedForm] = await Promise.all([
|
||||
downloadTxtFile(baseUrl, selected_file),
|
||||
detectFormFromUrl(baseUrl),
|
||||
]);
|
||||
const csvContent = convertTxtToCsv(downloadResult.buffer);
|
||||
// 从 file 名解析品牌和型号
|
||||
const parts = selected_file.split(' ');
|
||||
const brandName = parts.length > 1 ? parts[0] : '';
|
||||
const modelName = parts.length > 1 ? parts.slice(1).join(' ') : selected_file;
|
||||
return res.json(ApiResponse.success({
|
||||
brand_name: brandName,
|
||||
model_name: modelName,
|
||||
form: detectedForm || null,
|
||||
csv_content: csvContent,
|
||||
data_url: downloadResult.url,
|
||||
matches: [],
|
||||
}));
|
||||
}
|
||||
|
||||
// 自动抓取
|
||||
const result = await fetchFromSquigLink(share_url);
|
||||
|
||||
// 多个候选,返回给前端选择
|
||||
if (result.matches.length > 1) {
|
||||
return res.json(ApiResponse.success({
|
||||
brand_name: '',
|
||||
model_name: '',
|
||||
form: result.form || null,
|
||||
csv_content: null,
|
||||
data_url: null,
|
||||
matches: result.matches,
|
||||
}));
|
||||
}
|
||||
|
||||
// 单个匹配,返回 CSV 内容
|
||||
const csvContent = convertTxtToCsv(result.buffer);
|
||||
return res.json(ApiResponse.success({
|
||||
brand_name: result.brandName,
|
||||
model_name: result.modelName,
|
||||
form: result.form || null,
|
||||
csv_content: csvContent,
|
||||
data_url: result.dataUrl,
|
||||
matches: [],
|
||||
}));
|
||||
} catch (e) {
|
||||
logger.error(`SquigLink fetch error: ${e.message}`);
|
||||
return res.json(ApiResponse.error(e.message || '抓取失败'));
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/models/ (multipart/form-data)
|
||||
router.post('/api/models/', upload.single('measurement_file'), async (req, res) => {
|
||||
try {
|
||||
@@ -316,8 +381,19 @@ router.post('/api/models/', upload.single('measurement_file'), async (req, res)
|
||||
return res.json(ApiResponse.error('该品牌下型号名称已存在'));
|
||||
}
|
||||
|
||||
// 处理文件上传
|
||||
if (req.file && req.file.originalname) {
|
||||
// 处理文件上传(优先 squiglink_csv,其次文件上传)
|
||||
const { squiglink_csv } = req.body;
|
||||
if (squiglink_csv) {
|
||||
// 从 squig.link 抓取的 CSV 内容直接上传 S3
|
||||
const csvBuffer = Buffer.from(squiglink_csv, 'utf-8');
|
||||
const s3Key = await uploadMeasurementToS3(csvBuffer, {
|
||||
source: source || 'Eafonyoung',
|
||||
form: form || 'in-ear',
|
||||
brandName: brand_name,
|
||||
modelName: name,
|
||||
});
|
||||
logger.info(`SquigLink CSV uploaded to S3: ${s3Key}`);
|
||||
} else if (req.file && req.file.originalname) {
|
||||
const fileExt = path.extname(req.file.originalname).toLowerCase();
|
||||
if (!ALLOWED_EXTENSIONS.includes(fileExt)) {
|
||||
logger.error(`Unsupported file format: ${fileExt}`);
|
||||
@@ -390,7 +466,21 @@ router.put('/api/models/:model_id', upload.single('measurement_file'), async (re
|
||||
const effSource = source === undefined || source === 'null' ? dbModel.source : source;
|
||||
const effForm = form === undefined || form === 'null' ? dbModel.form : form;
|
||||
|
||||
if (req.file && req.file.originalname) {
|
||||
// 处理频响文件(优先 squiglink_csv,其次文件上传)
|
||||
const { squiglink_csv } = req.body;
|
||||
if (squiglink_csv) {
|
||||
if (!effSource || !effForm) {
|
||||
return res.json(ApiResponse.error('上传频响文件需要来源与形式字段'));
|
||||
}
|
||||
const csvBuffer = Buffer.from(squiglink_csv, 'utf-8');
|
||||
const s3Key = await uploadMeasurementToS3(csvBuffer, {
|
||||
source: effSource,
|
||||
form: effForm,
|
||||
brandName: newBrandName,
|
||||
modelName: newName,
|
||||
});
|
||||
logger.info(`SquigLink CSV uploaded to S3: ${s3Key}`);
|
||||
} else if (req.file && req.file.originalname) {
|
||||
const fileExt = path.extname(req.file.originalname).toLowerCase();
|
||||
if (!ALLOWED_EXTENSIONS.includes(fileExt)) {
|
||||
logger.error(`Unsupported file format: ${fileExt}`);
|
||||
|
||||
Reference in New Issue
Block a user