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.
78 lines
3.8 KiB
78 lines
3.8 KiB
|
2 days ago
|
/* ---- 数据加载(列表=旧端点 contacts 全字段;图谱=graph/detail;互不吞数据) ---- */
|
||
|
|
async function loadContacts() {
|
||
|
|
const d = await api('/api/customer/contacts?customerId=' + D.id);
|
||
|
|
C.list = (Array.isArray(d) ? d : ((d && d.content) || [])).map(c => Object.assign({}, c, { _jobCode: '', _catCode: '' }));
|
||
|
|
C.checked = {}; revealed = {}; C.dirtyRows = {}; C.revealAll = false;
|
||
|
|
$('btnRevealAll').textContent = '明文查看';
|
||
|
|
window._contacts = C.list; // dlgContact/dlgCheckPhone 旧入口兼容
|
||
|
|
C.list.forEach(c => { c._jobCode = jobCodeOfName(c.jobTitleName); });
|
||
|
|
}
|
||
|
|
function loadGraph() {
|
||
|
|
return api('/api/customer/contact/graph/detail?customerId=' + D.id).then(applyGraph);
|
||
|
|
}
|
||
|
|
function applyGraph(dto) {
|
||
|
|
G.version = Number(dto.version) || 0;
|
||
|
|
G.contacts = (dto.nodes || []).map(n => ({
|
||
|
|
id: String(n.contactId), name: n.name || '', cat: n.jobTitleCategory || '', job: n.jobTitleName || '',
|
||
|
|
level: n.level == null ? null : Number(n.level), levelSource: n.levelSource == null ? null : Number(n.levelSource),
|
||
|
|
phone: n.phoneMasked || '', key: Number(n.isKeyContact) || 0, internal: null
|
||
|
|
}));
|
||
|
|
G.edges = (dto.edges || []).map(e => ({ id: String(e.parentId) + '>' + String(e.childId), parent: String(e.parentId), child: String(e.childId) }));
|
||
|
|
G.cardPos = {}; G.pendingAdds = []; G.pendingDeletes = []; G.cycleHighlight = null; G.editing = false;
|
||
|
|
document.body.classList.remove('graph-edit');
|
||
|
|
paintGraphEditButtons();
|
||
|
|
}
|
||
|
|
/* 联系人子页签入口(switchSub('contacts') 调;双加载后首渲染) */
|
||
|
|
async function openContactsTab() {
|
||
|
|
await ensureDicts();
|
||
|
|
try {
|
||
|
|
await Promise.all([loadContacts(), loadGraph()]);
|
||
|
|
} catch (e) {
|
||
|
|
$('contactTbody').innerHTML = '<tr><td colspan="10"><div class="errbox">' + esc(e.message) + codeSuffix(e) + '</div></td></tr>';
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
layoutGraph();
|
||
|
|
renderContactsAll();
|
||
|
|
if (G.curView === 'graph') { if (!G.fitOnce) { fitView(); G.fitOnce = true; } applyTransform(); }
|
||
|
|
}
|
||
|
|
function renderContactsAll() { renderContactsList(); renderGraph(); renderGraphState(); }
|
||
|
|
/* ---- 脱敏明文(GET /reveal 服务端记埋点;双写列表行与图谱节点) ---- */
|
||
|
|
async function revealOne(id) {
|
||
|
|
if (revealed[id]) return;
|
||
|
|
try {
|
||
|
|
const plain = await api('/api/customer/contact/reveal?id=' + encodeURIComponent(id));
|
||
|
|
revealed[id] = true;
|
||
|
|
const lc = cById(id); if (lc) lc.phone = plain;
|
||
|
|
const gc = byId(id); if (gc) gc.phone = plain;
|
||
|
|
addLog('埋点', opName() + ' 于 ' + nowStr() + ' 查看明文号码:' + (gc ? gc.name : id) + '(' + maskPhone(plain) + ')');
|
||
|
|
} catch (err) {
|
||
|
|
toast('明文获取失败(' + err.code + '):' + err.message, 'err');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
async function toggleRevealAll() {
|
||
|
|
C.revealAll = !C.revealAll;
|
||
|
|
$('btnRevealAll').textContent = C.revealAll ? '隐藏明文' : '明文查看';
|
||
|
|
if (C.revealAll) {
|
||
|
|
addLog('埋点', opName() + ' 于 ' + nowStr() + ' 批量显示当前过滤结果完整号码(共 ' + filteredContacts().length + ' 位)');
|
||
|
|
for (const c of filteredContacts()) { if (!revealed[c.id]) await revealOne(c.id); }
|
||
|
|
}
|
||
|
|
renderContactsAll();
|
||
|
|
}
|
||
|
|
/* ---- 查询(页内过滤;勾选与临时明文重置) ---- */
|
||
|
|
function queryContacts() {
|
||
|
|
C.query = { keyword: $('qKeyword').value, internal: $('qInternal').value };
|
||
|
|
C.checked = {}; revealed = {}; C.revealAll = false;
|
||
|
|
$('btnRevealAll').textContent = '明文查看';
|
||
|
|
renderContactsList();
|
||
|
|
}
|
||
|
|
function resetContactsContact() {
|
||
|
|
$('qKeyword').value = ''; $('qInternal').value = '';
|
||
|
|
C.query = { keyword: '', internal: '' };
|
||
|
|
C.checked = {}; revealed = {}; C.revealAll = false;
|
||
|
|
$('btnRevealAll').textContent = '明文查看';
|
||
|
|
renderContactsList();
|
||
|
|
}
|
||
|
|
function chkAllChange(el) {
|
||
|
|
filteredContacts().forEach(c => { const k = String(c.id); if (el.checked) C.checked[k] = true; else delete C.checked[k]; });
|
||
|
|
renderContactsList();
|
||
|
|
}
|