feat: convert pasted Mintegral click links
This commit is contained in:
+79
-87
@@ -2,36 +2,26 @@
|
||||
const templates = window.LINK_TEMPLATES;
|
||||
if (!templates?.length) return;
|
||||
|
||||
const { convertTrackingLink } = window.TrackingLinkConverter;
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const platformSelect = $('platformSelect');
|
||||
const linkTypeSelect = $('linkTypeSelect');
|
||||
const mappingBody = $('mappingTableBody');
|
||||
const macroBody = $('macroTableBody');
|
||||
const output = $('urlOutput');
|
||||
const businessIds = ['advid','campid','pkg','platformCode','sanCampid','adsetId','countryCode'];
|
||||
let state = { platformIndex:0, type:'click', mappings:{} };
|
||||
let activeResult = null;
|
||||
let inputTimer;
|
||||
|
||||
$('templateCount').textContent = `${templates.length} 个平台模板`;
|
||||
templates.forEach((template, index) => platformSelect.add(new Option(template.name, index)));
|
||||
|
||||
const activeTemplate = () => templates[state.platformIndex];
|
||||
const activeLink = () => activeTemplate().links[state.type];
|
||||
const activeTemplate = () => templates[Number(platformSelect.value || 0)];
|
||||
|
||||
function loadPlatform() {
|
||||
function renderPlatform() {
|
||||
const template = activeTemplate();
|
||||
linkTypeSelect.innerHTML = '';
|
||||
Object.keys(template.links).forEach((type) => linkTypeSelect.add(new Option(type === 'click' ? 'Click Link' : 'Impression Link', type)));
|
||||
state.type = Object.keys(template.links)[0];
|
||||
$('platformCode').value = template.platformCode;
|
||||
$('platformStatus').innerHTML = `<span class="template-status ${template.status.includes('待') ? 'review' : ''}">${template.status}</span>`;
|
||||
const review = template.status.includes('待');
|
||||
$('platformStatus').innerHTML = `<span class="template-status ${review ? 'review' : ''}">${escapeHtml(template.status)}</span>`;
|
||||
renderMacros();
|
||||
loadLink();
|
||||
}
|
||||
|
||||
function loadLink() {
|
||||
state.mappings = { ...activeLink().mappings };
|
||||
renderMappings();
|
||||
buildUrl();
|
||||
if ($('originalLink').value.trim()) convertFromInput(false);
|
||||
}
|
||||
|
||||
function renderMacros() {
|
||||
@@ -42,76 +32,72 @@
|
||||
: '<tr><td colspan="2" class="table-empty">没有匹配的媒体宏</td></tr>';
|
||||
}
|
||||
|
||||
function renderMappings() {
|
||||
mappingBody.innerHTML = Object.entries(state.mappings).map(([key, value]) => `<tr><td><code>${escapeHtml(key)}</code></td><td><input data-key="${escapeHtml(key)}" value="${escapeHtml(value)}" aria-label="${escapeHtml(key)} value"></td></tr>`).join('');
|
||||
mappingBody.querySelectorAll('input').forEach((input) => input.addEventListener('input', () => {
|
||||
state.mappings[input.dataset.key] = input.value;
|
||||
buildUrl();
|
||||
}));
|
||||
function renderChanges(changes) {
|
||||
const rows = changes.length ? changes : [{ key:'—', from:'原链接参数无需变化', to:'—' }];
|
||||
$('mappingTableBody').innerHTML = rows.map((change) => `<tr>
|
||||
<td><code>${escapeHtml(change.key)}</code></td>
|
||||
<td><span class="old-param">${escapeHtml(change.from || '(空值)')}</span></td>
|
||||
<td>${change.to ? `<code>${escapeHtml(change.to)}</code>` : '<span class="empty-param">留空</span>'}</td>
|
||||
</tr>`).join('');
|
||||
}
|
||||
|
||||
function buildUrl() {
|
||||
const link = activeLink();
|
||||
const campid = $('campid').value.trim();
|
||||
const pkg = $('pkg').value.trim();
|
||||
const type = state.type;
|
||||
const params = [];
|
||||
const addBusiness = (key, value) => params.push(`${key}=${encodeURIComponent(value)}`);
|
||||
const addRaw = (key, value) => params.push(`${key}=${value}`);
|
||||
|
||||
if (type === 'click') {
|
||||
addBusiness('advid', $('advid').value.trim());
|
||||
addBusiness('campid', campid);
|
||||
addBusiness('platform', $('platformCode').value.trim());
|
||||
addBusiness('pkg', pkg);
|
||||
} else {
|
||||
addBusiness('campid', campid);
|
||||
addBusiness('pkg', pkg);
|
||||
}
|
||||
|
||||
Object.entries(state.mappings).forEach(([key, value]) => {
|
||||
const finalValue = key === 'country_code' && $('countryCode').value.trim()
|
||||
? $('countryCode').value.trim().toUpperCase()
|
||||
: value;
|
||||
addRaw(key, finalValue);
|
||||
});
|
||||
|
||||
if (type === 'click') {
|
||||
if ($('sanCampid').value.trim()) addBusiness('san_campid', $('sanCampid').value.trim());
|
||||
if ($('adsetId').value.trim()) addBusiness('adset_id', $('adsetId').value.trim());
|
||||
addRaw('c_cto', '0');
|
||||
} else {
|
||||
addRaw('at_tag', '2');
|
||||
}
|
||||
|
||||
const url = `${link.endpoint}?${params.join('&')}`;
|
||||
output.textContent = url;
|
||||
$('urlLength').textContent = `${url.length} chars`;
|
||||
|
||||
const missing = [];
|
||||
if (!campid) missing.push('Campaign ID');
|
||||
if (!pkg) missing.push('Package Name');
|
||||
$('generatorMessage').textContent = missing.length ? `待填写:${missing.join('、')}` : '';
|
||||
function showEmpty() {
|
||||
activeResult = null;
|
||||
$('conversionEmpty').classList.remove('hidden');
|
||||
$('conversionResult').classList.add('hidden');
|
||||
$('detectedType').textContent = '等待链接';
|
||||
$('generatorMessage').textContent = '';
|
||||
$('copyStatus').textContent = '';
|
||||
$('copyLink').disabled = true;
|
||||
}
|
||||
|
||||
function resetGenerator() {
|
||||
$('advid').value = '30';
|
||||
$('campid').value = '';
|
||||
$('pkg').value = '';
|
||||
$('platformCode').value = activeTemplate().platformCode;
|
||||
$('sanCampid').value = '';
|
||||
$('adsetId').value = '-1';
|
||||
$('countryCode').value = '';
|
||||
loadLink();
|
||||
function showError(message) {
|
||||
activeResult = null;
|
||||
$('generatorMessage').textContent = message;
|
||||
$('conversionEmpty').classList.remove('hidden');
|
||||
$('conversionResult').classList.add('hidden');
|
||||
$('detectedType').textContent = '无法识别';
|
||||
$('copyLink').disabled = true;
|
||||
}
|
||||
|
||||
function convertFromInput(showRequiredMessage = true) {
|
||||
const original = $('originalLink').value.trim();
|
||||
$('copyStatus').textContent = '';
|
||||
if (!original) {
|
||||
showEmpty();
|
||||
if (showRequiredMessage) $('generatorMessage').textContent = '请先粘贴一条完整的 Tracking Link';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = convertTrackingLink(original, activeTemplate());
|
||||
activeResult = result;
|
||||
const typeLabel = result.type === 'imp' ? 'Impression' : 'Click';
|
||||
$('detectedType').innerHTML = `<span class="type-chip">${typeLabel}</span>`;
|
||||
$('summaryType').textContent = typeLabel;
|
||||
$('replacementCount').textContent = result.changes.length;
|
||||
$('preservedCount').textContent = result.preservedCount;
|
||||
$('urlLength').textContent = `${result.url.length} chars`;
|
||||
output.textContent = result.url;
|
||||
renderChanges(result.changes);
|
||||
$('generatorMessage').textContent = result.changes.length ? '' : '链接有效,但没有发现需要替换的参数';
|
||||
$('conversionEmpty').classList.add('hidden');
|
||||
$('conversionResult').classList.remove('hidden');
|
||||
$('copyLink').disabled = false;
|
||||
} catch (error) {
|
||||
showError(error.message === 'Invalid URL' ? '链接格式不正确,请粘贴包含 http:// 或 https:// 的完整链接' : error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function loadSample() {
|
||||
$('originalLink').value = 'https://trident.bigpinggo.com/l/click?advid=30&campid=91566789&platform=M_API_Self_Mintegral&pkg=com.salaryse.android&clickid={click_id}&offer_name={offer_name}&creative_id={creative_id}&creative_name={creative_name}&affiliate_id={affiliate_id}&idfa={idfa}&gaid={gaid}&imei={imei}&android_id={android_id}&mac={mac}&oaid={oaid}&uagent={ua}&os_platform={os_platform}&os_version={os_version}&device_model={device_model}&ip={ip}&country_code={country_code}&ext={ext}&rta_token={rta_token}&san_campid=91566789&adset_id=-1&c_cto=0';
|
||||
convertFromInput(false);
|
||||
}
|
||||
|
||||
async function copyUrl() {
|
||||
if (!$('campid').value.trim() || !$('pkg').value.trim()) {
|
||||
$('copyStatus').textContent = '请先补全必填参数';
|
||||
return;
|
||||
}
|
||||
if (!activeResult) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(output.textContent);
|
||||
await navigator.clipboard.writeText(activeResult.url);
|
||||
} catch (_) {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(output);
|
||||
@@ -123,7 +109,7 @@
|
||||
}
|
||||
$('copyStatus').textContent = '已复制';
|
||||
const toast = $('toast');
|
||||
toast.textContent = '最终链接已复制到剪贴板';
|
||||
toast.textContent = '转换后的平台链接已复制';
|
||||
toast.classList.add('show');
|
||||
setTimeout(() => toast.classList.remove('show'), 1800);
|
||||
}
|
||||
@@ -132,11 +118,17 @@
|
||||
return String(value).replace(/[&<>"']/g, (char) => ({ '&':'&', '<':'<', '>':'>', '"':'"', "'":''' })[char]);
|
||||
}
|
||||
|
||||
platformSelect.addEventListener('change', () => { state.platformIndex = Number(platformSelect.value); loadPlatform(); });
|
||||
linkTypeSelect.addEventListener('change', () => { state.type = linkTypeSelect.value; loadLink(); });
|
||||
platformSelect.addEventListener('change', renderPlatform);
|
||||
$('macroSearch').addEventListener('input', renderMacros);
|
||||
businessIds.forEach((id) => $(id).addEventListener('input', buildUrl));
|
||||
$('resetGenerator').addEventListener('click', resetGenerator);
|
||||
$('convertLink').addEventListener('click', () => convertFromInput(true));
|
||||
$('sampleLink').addEventListener('click', loadSample);
|
||||
$('copyLink').addEventListener('click', copyUrl);
|
||||
loadPlatform();
|
||||
$('clearConverter').addEventListener('click', () => { $('originalLink').value = ''; showEmpty(); $('originalLink').focus(); });
|
||||
$('originalLink').addEventListener('input', () => {
|
||||
clearTimeout(inputTimer);
|
||||
inputTimer = setTimeout(() => convertFromInput(false), 220);
|
||||
});
|
||||
|
||||
renderPlatform();
|
||||
showEmpty();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user