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
100 lines
5.1 KiB
/* ---- 联系人导入三段式(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');
|
|
}
|
|
}
|