import request from '@/utils/request' /** 查询产品列表 */ export function listProduct(query) { return request({ url: '/price/product/list', method: 'get', params: query }) } /** 查询产品详情 */ export function getProduct(productId) { return request({ url: '/price/product/' + productId, method: 'get' }) } /** 查询产品国家明细(优先 productId,绑定到具体产品版本行) */ export function listProductCountries(productCode, effectiveDate, productId) { const params = {} if (effectiveDate) params.effectiveDate = effectiveDate if (productId) params.productId = productId return request({ url: '/price/product/' + productCode + '/countries', method: 'get', params }) } /** 修改产品国家明细行(重量段/运费/挂号费/尺寸/尾程/时效/生效失效日期) */ export function updateProductCountry(data) { return request({ url: '/price/product/country', method: 'put', data: data }) } /** 新增产品 */ export function addProduct(data) { return request({ url: '/price/product', method: 'post', data: data }) } /** 修改产品 */ export function updateProduct(data) { return request({ url: '/price/product', method: 'put', data: data }) } /** 删除产品 */ export function delProduct(productIds) { return request({ url: '/price/product/' + productIds, method: 'delete' }) } export function getProductImportTask(taskId) { return request({ url: '/price/product/import/task/' + taskId, method: 'get' }) } function pickImportTaskId(res) { if (!res) return null const d = res.data if (d && typeof d === 'object' && d.taskId) return String(d.taskId) if (typeof d === 'string' && d.trim()) return d.trim() if (typeof res.msg === 'string') { const m = res.msg.trim() if (/^[a-f0-9]{32}$/i.test(m)) return m if (/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(m)) { return m.replace(/-/g, '') } } return null } async function pollProductImportTask(taskId, onProgress) { const started = Date.now() const maxMs = 30 * 60 * 1000 while (Date.now() - started < maxMs) { const res = await getProductImportTask(taskId) const task = res.data || {} if (typeof onProgress === 'function') { onProgress(task) } if (task.status === 'SUCCESS') { return { task } } if (task.status === 'FAIL') { const err = new Error(task.error || task.message || 'import failed') err.task = task throw err } await new Promise(resolve => setTimeout(resolve, 800)) } throw new Error('import timeout') } /** * Async all-country product import; poll until done. * @param {File|Blob} file * @param {(task: object) => void} [onProgress] */ export async function importProductExcelAsync(file, onProgress) { const formData = new FormData() formData.append('file', file) const submitRes = await request({ url: '/price/product/importData?updateSupport=0', method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data' } }) const taskId = pickImportTaskId(submitRes) if (!taskId) { throw new Error('missing import taskId') } return pollProductImportTask(taskId, onProgress) } /** * Async single-country product import; poll until done. * @param {File|Blob} file * @param {string} countryCode * @param {(task: object) => void} [onProgress] */ export async function importProductCountryExcelAsync(file, countryCode, onProgress) { const formData = new FormData() formData.append('file', file) const params = new URLSearchParams() params.set('countryCode', countryCode) const submitRes = await request({ url: '/price/product/importCountryData?' + params.toString(), method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data' } }) const taskId = pickImportTaskId(submitRes) if (!taskId) { throw new Error('missing import taskId') } return pollProductImportTask(taskId, onProgress) }