import request from '@/utils/request' /** 查询红线价列表 */ export function listRedline(query) { return request({ url: '/price/redline/list', method: 'get', params: query }) } /** 产品下拉选项(非分页,不要求 price:redline:list 权限) */ export function listRedlineOptions(query) { return request({ url: '/price/redline/optionselect', method: 'get', params: query }) } /** 查询产品国家明细(优先 productId,绑定到具体产品版本行) */ export function listRedlineCountries(productCode, effectiveDate, productId) { const params = {} if (effectiveDate) params.effectiveDate = effectiveDate if (productId) params.productId = productId return request({ url: '/price/redline/' + productCode + '/countries', method: 'get', params }) } /** 修改产品国家明细行(重量段/运费/挂号费/尺寸/尾程/时效/生效失效日期) */ export function updateRedlineCountry(data) { return request({ url: '/price/redline/country', method: 'put', data: data }) } export function listRedlineVersions(query) { return request({ url: '/price/redline/versions', method: 'get', params: query }) } export function activateRedlineVersion(psvId, data) { return request({ url: '/price/redline/version/activate/' + psvId, method: 'put', data: data || {} }) } export function deleteRedlineVersion(psvId) { return request({ url: '/price/redline/version/' + psvId, method: 'delete' }) } export function getRedlineDraftVersion() { return request({ url: '/price/redline/version/draft', method: 'get' }) } export function prepareRedlineVersion(copyFromLatest) { return request({ url: '/price/redline/version/prepare', method: 'post', params: { copyFromLatest: !!copyFromLatest } }) } /** Persist create-page preview into draft (no effectiveDate required). Polls until saved. */ export async function applyRedlineCatalogPreview(data, onProgress) { const submitRes = await request({ url: '/price/redline/version/applyPreviewAsync', method: 'post', data, headers: { repeatSubmit: false }, timeout: 10 * 60 * 1000 }) const taskId = pickImportTaskId(submitRes) if (!taskId) { throw new Error('missing import taskId') } const { task } = await pollProductImportTask(taskId, onProgress) return { data: task } } /** Excel attachments of a redline version. */ export function listRedlineVersionExcelFiles(psvId) { return request({ url: '/price/redline/version/' + psvId + '/excelFiles', method: 'get' }) } /** Save import Excel onto draft/pending version (prc_price_excel_file). */ export function attachRedlineVersionExcel(psvId, file) { const formData = new FormData() formData.append('file', file) return request({ url: '/price/redline/version/' + psvId + '/excel', method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false }, timeout: 10 * 60 * 1000 }) } /** 删除产品 */ export function delRedline(productIds) { return request({ url: '/price/redline/' + productIds, method: 'delete' }) } export function getRedlineImportTask(taskId) { return request({ url: '/price/redline/import/task/' + taskId, method: 'get', timeout: 10 * 60 * 1000 }) } 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 getRedlineImportTask(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 {string} effectiveDate yyyy-MM-dd (required) * @param {(task: object) => void} [onProgress] */ /** Async parse multi-country Excel only (no DB write); poll until done. */ function appendUploadFiles(formData, file) { const list = Array.isArray(file) ? file : [file] for (const item of list) { const raw = item && (item.raw || item) if (raw) formData.append('files', raw) } } export async function previewRedlineImport(file, onProgress) { const formData = new FormData() appendUploadFiles(formData, file) const submitRes = await request({ url: '/price/redline/previewImport', method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false }, timeout: 10 * 60 * 1000 }) const taskId = pickImportTaskId(submitRes) if (!taskId) { throw new Error('missing import taskId') } const { task } = await pollProductImportTask(taskId, onProgress) return { data: (task && task.result) || {} } } /** Async parse single-country Excel only (no DB write); poll until done. */ export async function previewRedlineCountryImport(file, countryCode, onProgress) { const formData = new FormData() appendUploadFiles(formData, file) const params = new URLSearchParams() params.set('countryCode', countryCode) const submitRes = await request({ url: '/price/redline/previewImportCountry?' + params.toString(), method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false }, timeout: 10 * 60 * 1000 }) const taskId = pickImportTaskId(submitRes) if (!taskId) { throw new Error('missing import taskId') } const { task } = await pollProductImportTask(taskId, onProgress) return { data: (task && task.result) || {} } } export async function importRedlineExcelAsync(file, effectiveDate, onProgress) { const formData = new FormData() formData.append('file', file) const params = new URLSearchParams() params.set('updateSupport', '0') if (effectiveDate) params.set('effectiveDate', effectiveDate) const submitRes = await request({ url: '/price/redline/importData?' + params.toString(), method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false }, timeout: 10 * 60 * 1000 }) 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 {string} effectiveDate yyyy-MM-dd * @param {(task: object) => void} [onProgress] */ export async function importRedlineCountryExcelAsync(file, countryCode, effectiveDate, onProgress) { const formData = new FormData() formData.append('file', file) const params = new URLSearchParams() params.set('countryCode', countryCode) if (effectiveDate) params.set('effectiveDate', effectiveDate) const submitRes = await request({ url: '/price/redline/importCountryData?' + params.toString(), method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false }, timeout: 10 * 60 * 1000 }) const taskId = pickImportTaskId(submitRes) if (!taskId) { throw new Error('missing import taskId') } return pollProductImportTask(taskId, onProgress) }