diff --git a/controllers/goods.js b/controllers/goods.js index fa5b6b7..c213d06 100644 --- a/controllers/goods.js +++ b/controllers/goods.js @@ -1,4 +1,5 @@ const { query } = require('../config/database') +const { toRelativeUrl } = require('../utils/image-url') async function getGoods(ctx) { let sql = 'SELECT * FROM goods WHERE 1=1' @@ -52,7 +53,7 @@ async function getGoods(ctx) { async function getGoodsById(ctx) { const goodsId = parseInt(ctx.params.id) const goods = await query('SELECT * FROM goods WHERE id = ?', [goodsId]) - + if (goods.length > 0) { ctx.body = { code: 200, @@ -77,6 +78,9 @@ async function createGoods(ctx) { return } + // 将图片URL转换为相对路径存储 + const relativeImages = (images || []).map(img => toRelativeUrl(img)) + const sql = `INSERT INTO goods (name, price, cost_price, unit, category_id, images, stock, pricing_type, is_hot, is_new, remark, goods_no, barcode) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` @@ -87,7 +91,7 @@ async function createGoods(ctx) { parseFloat(ctx.request.body.costPrice || 0), unit, categoryId || null, - JSON.stringify(images || []), + JSON.stringify(relativeImages), parseInt(stock) || 0, parseInt(pricingType) || 1, parseInt(isHot) || 0, @@ -125,6 +129,9 @@ async function updateGoods(ctx) { return } + // 将图片URL转换为相对路径存储 + const relativeImages = (images || []).map(img => toRelativeUrl(img)) + const sql = `UPDATE goods SET name = ?, price = ?, original_price = ?, unit = ?, category_id = ?, images = ?, stock = ?, pricing_type = ?, is_hot = ?, is_new = ?, description = ? @@ -136,7 +143,7 @@ async function updateGoods(ctx) { parseFloat(ctx.request.body.originalPrice || 0), unit, categoryId || null, - JSON.stringify(images || []), + JSON.stringify(relativeImages), parseInt(stock) || 0, parseInt(pricingType) || 1, parseInt(isHot) || 0, diff --git a/routes/ai.js b/routes/ai.js index d9ec8bb..243d5d3 100644 --- a/routes/ai.js +++ b/routes/ai.js @@ -47,7 +47,7 @@ router.post('/generate-product', async (ctx) => { 'Content-Type': 'application/json' }, body: JSON.stringify({ - model: 'deepseek-ai/deepseek-v4-pro', + model: 'deepseek-v4-flash', messages: [ { role: 'user', diff --git a/routes/upload.js b/routes/upload.js index 1d3eedc..b19320a 100644 --- a/routes/upload.js +++ b/routes/upload.js @@ -2,7 +2,6 @@ const Router = require('koa-router') const multer = require('@koa/multer') const path = require('path') const fs = require('fs') -const { IMG_BASE_URL } = require('../config/domain') const router = new Router() @@ -37,7 +36,8 @@ router.post('/', upload.single('file'), async (ctx) => { return } - const fileUrl = `${IMG_BASE_URL}/${ctx.file.filename}` + // 存储相对路径,前端使用时拼接域名 + const fileUrl = `/img/${ctx.file.filename}` ctx.body = { code: 200, message: '上传成功', diff --git a/utils/image-url.js b/utils/image-url.js new file mode 100644 index 0000000..0706962 --- /dev/null +++ b/utils/image-url.js @@ -0,0 +1,71 @@ +// 图片URL处理工具 +const DOMAIN_CONFIG = require('./domain').DOMAIN_CONFIG; + +// 将完整URL转换为相对路径(用于存储到数据库) +function toRelativeUrl(url) { + if (!url) return ''; + // 移除域名前缀,保留相对路径 + const baseUrl = DOMAIN_CONFIG.BASE_URL; + if (url.startsWith(baseUrl)) { + return url.replace(baseUrl, ''); + } + // 移除其他可能的前缀 + const patterns = [ + /^https?:\/\/donghy\.top/, + /^https?:\/\/110\.42\.255\.239(:\d+)?/, + /^https?:\/\/localhost(:\d+)?/ + ]; + for (const pattern of patterns) { + if (pattern.test(url)) { + return url.replace(pattern, ''); + } + } + return url; +} + +// 将相对路径转换为完整URL(用于返回给前端) +function toFullUrl(url) { + if (!url) return ''; + // 如果已经是完整URL,直接返回 + if (url.startsWith('http://') || url.startsWith('https://')) { + return url; + } + // 如果是相对路径,拼接当前域名 + const baseUrl = DOMAIN_CONFIG.BASE_URL; + if (url.startsWith('/')) { + return baseUrl + url; + } + if (url.startsWith('img/')) { + return baseUrl + '/' + url; + } + return url; +} + +// 处理商品图片字段 +function processGoodsImages(goods) { + if (!goods) return goods; + + const processItem = (item) => { + if (item.images) { + try { + const images = JSON.parse(item.images); + const fullUrls = images.map(img => toFullUrl(img)); + item.images = JSON.stringify(fullUrls); + } catch (e) { + // 如果不是JSON格式,保持原样 + } + } + return item; + }; + + if (Array.isArray(goods)) { + return goods.map(processItem); + } + return processItem(goods); +} + +module.exports = { + toRelativeUrl, + toFullUrl, + processGoodsImages +};