fix: 新增代理

This commit is contained in:
丹尼尔
2026-03-12 13:02:25 +08:00
parent bdba4ec071
commit 66362780a0
8 changed files with 3146 additions and 69 deletions

View File

@@ -146,11 +146,11 @@
<div class="field full">
<label>客户标签(从客户档案中选)</label>
<div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center;">
<select id="g-tag-select" style="max-width:160px"><option value="">请先登录后加载</option></select>
<select id="g-tag-select" style="max-width:200px"><option value="">选择标签…</option></select>
<button type="button" class="secondary" id="g-tag-add" style="padding:4px 10px;font-size:12px">添加标签</button>
<span id="g-tags-chips" class="tags-chips"></span>
</div>
<p class="small-label" style="margin-top:4px">在下方「客户档案」中维护的标签会出现在下拉列表;可多选,发送时仅推送给带这些标签的客户。</p>
<p class="small-label" style="margin-top:4px">在下方「客户档案」中维护的标签会出现在下拉列表;可多选,发送时仅推送给带这些标签的客户。支持获取联系人列表。</p>
</div>
<div class="field full"><label>问候语模板(可用 {{name}}</label><textarea id="g-template" rows="2" placeholder="早安,{{name}}!今日上新…"></textarea></div>
<div class="field"><label>&nbsp;</label><label><input type="checkbox" id="g-use-qwen" /> 使用千问生成个性化问候</label></div>
@@ -165,9 +165,10 @@
<label>选择接收人(从好友/客户列表)</label>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
<button type="button" class="secondary" id="btn-load-friends" style="padding:4px 10px;font-size:12px">加载联系人</button>
<button type="button" class="secondary" id="btn-load-customers-mass" style="padding:4px 10px;font-size:12px" title="从客户档案加载,与联系人合并去重">加载客户</button>
<span id="mass-selected-count" class="small-label">已选 0 人</span>
</div>
<div id="mass-friend-list" style="max-height:140px;overflow-y:auto;border:1px solid var(--border);border-radius:8px;padding:8px;margin-top:6px;background:rgba(15,23,42,0.6)"></div>
<div id="mass-friend-list" style="max-height:200px;overflow-y:auto;border:1px solid var(--border);border-radius:8px;padding:8px;margin-top:6px;background:rgba(15,23,42,0.6)"></div>
</div>
<div class="field full"><label>群发文案</label><textarea id="mass-content" rows="2" placeholder="输入要群发的文字…"></textarea></div>
<button type="button" class="primary" id="btn-mass-send">一键群发</button>
@@ -630,6 +631,28 @@
}
let massSelectedWxids = [];
/** 快速群发可选列表(好友+客户合并去重):{ wxid, name, source?: 'friend'|'customer' } */
let massContactList = [];
function renderMassContactList() {
const el = $('mass-friend-list');
if (!el) return;
if (!massContactList.length) {
el.innerHTML = '<span class="small-label">请点击「加载联系人」或「加载客户」获取列表。</span>';
return;
}
el.innerHTML = massContactList.map(f => {
const wxid = (f.wxid || '').toString();
const name = (f.name || wxid).toString();
const checked = massSelectedWxids.includes(wxid) ? ' checked' : '';
const badge = f.source === 'customer' ? ' <span class="small-label" style="color:var(--muted)">[客户]</span>' : '';
return '<label style="display:block;margin:4px 0"><input type="checkbox" class="mass-friend-cb" data-wxid="' + escapeHtml(wxid) + '"' + checked + ' /> ' + escapeHtml(name) + badge + ' <span class="small-label">(' + escapeHtml(wxid.slice(0, 16)) + (wxid.length > 16 ? '…' : '') + ')</span></label>';
}).join('');
el.querySelectorAll('.mass-friend-cb').forEach(cb => {
cb.addEventListener('change', updateMassSelected);
});
updateMassSelected();
}
async function loadFriendsForMass() {
const key = $('key').value.trim();
@@ -637,27 +660,55 @@
const el = $('mass-friend-list');
el.innerHTML = '<span class="small-label">加载中…</span>';
try {
const data = await callApi('/api/friends?key=' + encodeURIComponent(key), { cache: 'no-store' });
const data = await callApi('/api/contact-list?key=' + encodeURIComponent(key) + '&refresh=1', { cache: 'no-store' });
const list = data.items || [];
if (!list.length) {
el.innerHTML = '<span class="small-label">暂无联系人,请先在「客户档案」添加客户。</span>';
massContactList = list.map(f => {
const wxid = (f.wxid || f.Wxid || f.UserName || '').toString();
const name = (f.remark_name || f.RemarkName || f.nick_name || f.NickName || wxid).toString();
return { wxid, name, source: 'friend' };
}).filter(f => f.wxid);
if (!massContactList.length) {
el.innerHTML = '<span class="small-label">暂无联系人。可点击「加载客户」从客户档案选择。</span>';
return;
}
el.innerHTML = list.map(f => {
const wxid = (f.wxid || f.Wxid || f.UserName || '').toString();
const name = (f.remark_name || f.RemarkName || f.NickName || wxid).toString();
return '<label style="display:block;margin:4px 0"><input type="checkbox" class="mass-friend-cb" data-wxid="' + escapeHtml(wxid) + '" /> ' + escapeHtml(name) + ' <span class="small-label">(' + escapeHtml(wxid.slice(0, 16)) + '…)</span></label>';
}).join('');
el.querySelectorAll('.mass-friend-cb').forEach(cb => {
cb.addEventListener('change', updateMassSelected);
});
massSelectedWxids = [];
updateMassSelected();
renderMassContactList();
} catch (e) {
el.innerHTML = '<span class="small-label">加载失败: ' + escapeHtml(e.message) + '</span>';
}
}
async function loadCustomersForMass() {
const key = $('key').value.trim();
if (!key) { alert('请先登录'); return; }
const el = $('mass-friend-list');
const wasEmpty = !massContactList.length;
if (wasEmpty) el.innerHTML = '<span class="small-label">加载中…</span>';
try {
const data = await callApi('/api/customers?key=' + encodeURIComponent(key));
const list = data.items || [];
const existingWxids = new Set(massContactList.map(f => f.wxid));
list.forEach(c => {
const wxid = (c.wxid || '').toString();
if (!wxid) return;
if (existingWxids.has(wxid)) return;
existingWxids.add(wxid);
massContactList.push({
wxid,
name: (c.remark_name || c.wxid || wxid).toString(),
source: 'customer'
});
});
if (!massContactList.length) {
el.innerHTML = '<span class="small-label">暂无客户。请先在「客户档案」添加客户,或点击「加载联系人」获取好友列表。</span>';
return;
}
renderMassContactList();
} catch (e) {
if (wasEmpty) el.innerHTML = '<span class="small-label">加载失败: ' + escapeHtml(e.message) + '</span>';
else alert('加载客户失败: ' + e.message);
}
}
function updateMassSelected() {
const list = $('mass-friend-list');
if (!list) return;
@@ -832,6 +883,7 @@
if ($('g-time')) { $('g-time').addEventListener('change', onGreetingTimeChange); $('g-time').addEventListener('input', onGreetingTimeChange); }
})();
$('btn-load-friends').addEventListener('click', loadFriendsForMass);
$('btn-load-customers-mass') && $('btn-load-customers-mass').addEventListener('click', loadCustomersForMass);
$('btn-mass-send').addEventListener('click', doMassSend);
$('btn-send-image').addEventListener('click', doSendImage);
if ($('img-file') && $('img-file-name')) {