You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
5.1 KiB

1 day ago
/* ---- 联系人导入三段式(upload→confirm→result/failures 轮询;id 加 cimp 前缀避让客户导入 tab) ---- */
let cimpTaskId = null, cimpPollTimer = null;
function openCimp() {
cimpTaskId = null;
clearInterval(cimpPollTimer);
$('cimpStep1').style.display = ''; $('cimpStep2').style.display = 'none'; $('cimpStep3').style.display = 'none';
$('cimpFile').value = '';
$('cimpCustName').textContent = custName();
$('cimpOverlay').classList.add('show');
}
function cimpClose() { $('cimpOverlay').classList.remove('show'); clearInterval(cimpPollTimer); }
async function cimpTemplateDownload() {
try {
const blob = await apiDownload('/api/customer/contact/import/template', 'GET');
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = '联系人导入模板-V1.xlsx';
a.click();
URL.revokeObjectURL(a.href);
} catch (err) { toast('模板下载失败(' + err.code + '):' + err.message, 'err'); }
}
function cimpReupload() { $('cimpStep1').style.display = ''; $('cimpStep2').style.display = 'none'; }
async function cimpUpload() {
const file = $('cimpFile').files[0];
if (!file) { toast('请先选择 .xlsx 文件', 'err'); return; }
const fd = new FormData();
fd.append('customerId', D.id);
fd.append('file', file);
fd.append('importMode', $('cimpMode').value);
fd.append('duplicateStrategy', $('cimpStrategy').value);
$('cimpUploadBtn').disabled = true;
try {
const p = await api('/api/customer/contact/import/upload', { method: 'POST', body: fd });
cimpTaskId = p.taskId;
$('cimpPreviewHead').textContent = '预检完成(任务 ' + p.taskId + ' 待确认):共 ' + p.totalCount
+ ' 行,预计新增 ' + p.insertCount + '、更新 ' + p.updateCount + '、失败 ' + p.failCount + '、疑似重复 ' + p.suspectCount;
$('cimpPreviewTbody').innerHTML = (p.rows || []).map(r =>
'<tr><td>' + r.rowNum + '</td><td>' + esc(r.identity || '') + '</td><td>' + esc(r.verdict || '') + '</td><td>' + esc(r.reason || '--') + '</td></tr>').join('')
|| '<tr><td colspan="4" class="empty">无明细(全部可入库)</td></tr>';
$('cimpStep1').style.display = 'none'; $('cimpStep2').style.display = '';
} catch (err) {
toast('预检失败(' + err.code + '):' + err.message, 'err'); // 67023 守门/模板版本/行数超限
} finally {
$('cimpUploadBtn').disabled = false;
}
}
async function cimpConfirmTask() {
if (!cimpTaskId) return;
try {
await api('/api/customer/contact/import/confirm?taskId=' + encodeURIComponent(cimpTaskId), { method: 'POST' });
$('cimpStep2').style.display = 'none'; $('cimpStep3').style.display = '';
$('cimpResultHead').textContent = '导入执行中…';
$('cimpFailTbody').innerHTML = '';
pollCimpResult();
} catch (err) {
toast('确认失败(' + err.code + '):' + err.message, 'err'); // 67024 重复确认/状态不允许
}
}
function pollCimpResult() {
clearInterval(cimpPollTimer);
const tick = async () => {
try {
const r = await api('/api/customer/contact/import/result?taskId=' + encodeURIComponent(cimpTaskId));
if (r.status === 1) { $('cimpResultHead').textContent = '导入执行中…(总 ' + r.totalCount + ' 行)'; return; }
clearInterval(cimpPollTimer);
const statusTxt = r.status === 2 ? '已完成' : (r.status === 3 ? '已失败:' + (r.failReason || '--') : '状态 ' + r.status);
$('cimpResultHead').textContent = statusTxt + ':新增 ' + r.insertCount + '、更新 ' + r.updateCount
+ '、未变化 ' + r.unchangedCount + '、失败 ' + r.failCount + '、疑似重复 ' + r.suspectCount;
const fails = await api('/api/customer/contact/import/failures?taskId=' + encodeURIComponent(cimpTaskId)).catch(() => []);
$('cimpFailTbody').innerHTML = (fails || []).map(f =>
'<tr><td>' + f.rowNum + '</td><td>' + esc(f.name || '') + '</td><td>' + esc(f.phone || '--') + '</td><td>' + esc(f.failReason || '') + '</td></tr>').join('')
|| '<tr><td colspan="4" class="empty">无失败/疑似明细</td></tr>';
if (D.sub === 'contacts') {
await Promise.all([loadContacts(), loadGraph()]);
layoutGraph(); renderContactsAll();
}
} catch (err) {
clearInterval(cimpPollTimer);
toast('结果查询失败(' + err.code + '):' + err.message, 'err');
}
};
tick();
cimpPollTimer = setInterval(tick, 1000);
}
function cimpDone() { $('cimpOverlay').classList.remove('show'); clearInterval(cimpPollTimer); }
/* ---- 批量导出(POST /export 全量导出该客户 xlsx;电话列脱敏口径) ---- */
async function exportContacts() {
try {
const blob = await apiDownload('/api/customer/contact/export?customerId=' + D.id, 'POST');
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = '联系人导出.xlsx';
a.click();
URL.revokeObjectURL(a.href);
addLog('数据', opName() + ' 导出联系人(xlsx 全量,电话恒脱敏)');
toast('导出已提交(全量,电话恒脱敏)', 'ok');
} catch (err) {
toast('导出失败(' + err.code + '):' + err.message, 'err');
}
}