/* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * @description 增量更新操作界面逻辑 */ // @ts-ignore service.ts 编译规则和 src 不一致 // eslint-disable-next-line prettier/prettier declare let jsondiffpatch: any; /** 差异 */ declare let delta: any; /** 当前 swagger 版本 */ declare let curVersion: any; /** 新 swagger 版本 */ declare let diffVersion: any; { /* eslint-disable no-undef */ const title = (document.title = 'swagger 增量同步工具'); const ChangedClassName = 'select-change'; const keySeparator = '@@__S__@@'; const canvas = document.querySelector('#canvas') as HTMLDivElement; const menu = document.querySelector('#menu') as HTMLDivElement; canvas.innerHTML = jsondiffpatch.formatters.html.format(delta, curVersion); /** 隐藏未修改 */ function hide() { jsondiffpatch.formatters.html.hideUnchanged(); } /** 显示未修改 */ function show() { jsondiffpatch.formatters.html.showUnchanged(); } // eslint-disable-next-line @typescript-eslint/no-unused-vars function toggleUnchanged(me: HTMLInputElement) { const checked = me.checked; if (checked) { show(); } else { hide(); } } function toggleSelectAll(me: HTMLInputElement) { const checked = me.checked; const allChangedInput = document.querySelectorAll(`.${ChangedClassName}`); const deletedExcluded = (document.getElementById('仅不选择删除') as HTMLInputElement)!.checked; const addedIncluded = (document.getElementById('仅选择新增') as HTMLInputElement)!.checked; if (allChangedInput) { [].forEach.call(allChangedInput, (node: HTMLInputElement) => { if ( (deletedExcluded && (node.parentNode as HTMLDivElement)!.className.indexOf('-deleted') !== -1) || (addedIncluded && (node.parentNode as HTMLDivElement)!.className.indexOf('-added') === -1) ) { // 排除 node.checked = false; } else { node.checked = checked; } }); } setCount(); } /** 仅不选择删除 */ // eslint-disable-next-line @typescript-eslint/no-unused-vars function excludeDelete(me: HTMLInputElement) { setTimeout(function() { const all = document.getElementById('全选/取消全选') as HTMLInputElement; all.checked = true; toggleSelectAll(all); }); } /** 仅选择新增 */ // eslint-disable-next-line @typescript-eslint/no-unused-vars function onlyAdd(me: HTMLInputElement) { setTimeout(function() { const all = document.getElementById('全选/取消全选') as HTMLInputElement; all.checked = true; toggleSelectAll(all); }); } /** 显示选中修改状态 */ // eslint-disable-next-line @typescript-eslint/no-unused-vars function showStatus(me: HTMLInputElement) { const addedEle = document.getElementById('仅显示新增') as HTMLInputElement; const deletedEle = document.getElementById('仅显示删除') as HTMLInputElement; const modifiedEle = document.getElementById('仅显示修改') as HTMLInputElement; const propertyNameEle = document.getElementById('仅显示属性名') as HTMLInputElement; if (me !== propertyNameEle) { if (me === modifiedEle) { addedEle.checked = false; deletedEle.checked = false; } else { modifiedEle.checked = false; } } const added = addedEle.checked; const deleted = deletedEle.checked; const modified = modifiedEle.checked; const addedAndDeleted = added && deleted; const propertyNameOnly = propertyNameEle.checked; (document.getElementById('canvas') as HTMLDivElement).className = `${ modified ? 'show-modified-only canvas' : addedAndDeleted ? 'show-added-deleted-only canvas' : added ? 'show-added-only canvas' : deleted ? 'show-add-deleted canvas' : 'canvas' }${propertyNameOnly ? ' show-only-property-name' : ''}`; } const help = ``; // eslint-disable-next-line @typescript-eslint/no-unused-vars function toggleHelp(e: MouseEvent) { e.stopImmediatePropagation(); const helpInfo = document.getElementById('help-info'); if (helpInfo) { helpInfo.style.display = helpInfo.style.display === 'none' ? 'block' : 'none'; helpInfo.onclick = e => { e.stopImmediatePropagation(); }; } } document.body.onclick = () => { const helpInfo = document.getElementById('help-info'); if (helpInfo) { helpInfo.style.display = 'none'; } }; menu.innerHTML = [ [ '仅显示新增', 'showStatus', '', '', `(${document.querySelectorAll('.jsondiffpatch-added').length}处)` ], [ '仅显示删除', 'showStatus', '', '', `(${document.querySelectorAll('.jsondiffpatch-deleted').length}处)` ], [ '仅显示修改', 'showStatus', '', '', `(${document.querySelectorAll('.jsondiffpatch-modified').length}处)` ], ['显示未变更', 'toggleUnchanged'], ['仅显示属性名', 'showStatus'], ['全选/取消全选', 'toggleSelectAll'], ['仅不选择删除', 'excludeDelete'], ['仅选择新增', 'onlyAdd'], ['同步已选择更新', 'patch', '', 'button'] ].reduce((html, item) => { const [zero, callback, three, tagName, extra] = item; const name = zero || three; html += tagName ? ` ` : ` `; return html; }, '') + `?${help}`; const counter = document.createElement('div'); counter.className = 'select-count'; menu.appendChild(counter); function setCount() { counter.innerHTML = `已选:${getAllSelect().length} / ${getAllChanged().length} 处`; } hide(); function getKeys(node: HTMLElement) { let par = node.parentNode; let key = node.getAttribute('data-key'); const keys = []; if (key) { // IMP: 数组的 key 需要特殊处理,符合 json diff 协议 if ( node.className.indexOf('jsondiffpatch-deleted') !== -1 && (par as HTMLElement).className.indexOf('jsondiffpatch-node-type-array') !== -1 ) { key = '_' + key; } keys.unshift(key); while (par && par !== canvas) { key = (par as HTMLElement).getAttribute('data-key'); if (key) { keys.unshift(key); } par = par.parentNode; } } return keys; } /** 所有选中的 key */ let allSelectedIndexes: string[][] = []; /** 所有被排除的 key */ let allExcludedIndexes: string[][] = []; function getAllSelect() { allSelectedIndexes = []; allExcludedIndexes = []; return [].filter.call( document.querySelectorAll(`.${ChangedClassName}`) || [], (item: HTMLInputElement) => { if (item.checked) { allSelectedIndexes.push(item.value.split(keySeparator)); } else { allExcludedIndexes.push(item.value.split(keySeparator)); } return item.checked; } ); } function getAllChanged() { return ( document.querySelectorAll( 'li[data-key]:not(.jsondiffpatch-unchanged):not(.jsondiffpatch-node)' ) || [] ); } const allChanged = getAllChanged(); [].forEach.call(allChanged, (node: HTMLElement) => { const input = document.createElement('input'); input.className = ChangedClassName; input.type = 'checkbox'; input.value = getKeys(node).join(keySeparator); input.onchange = () => { setCount(); }; node.insertBefore(input, node.firstChild); const handleClick = () => { input.checked = !input.checked; setCount(); }; (node.querySelector('.jsondiffpatch-value') as HTMLButtonElement).onclick = handleClick; const key = node.querySelector('.jsondiffpatch-property-name') as HTMLButtonElement; if (key) { key.onclick = handleClick; } }); setCount(); /** 让 server 端应用被选中的更新 */ // eslint-disable-next-line @typescript-eslint/no-unused-vars function patch() { if (!allSelectedIndexes.length) { if (!confirm('忽略所有远程变动?')) { return; } } const xhr = new XMLHttpRequest(); xhr.open('POST', '/patch'); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send( JSON.stringify({ version: diffVersion, keys: allSelectedIndexes, unkeys: allExcludedIndexes }) ); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { try { const res = JSON.parse(xhr.response); if (res.code) { throw res.message; } else { if (confirm('同步成功,可以重新生成 service 了——关闭当前窗口?')) { // @IMP: f**k 2 ok window.close(); window.close(); } } } catch (e) { alert('失败:' + (e.message || e)); } } }; xhr.onload = function() { if (xhr.status !== 200) { alert('同步失败'); } }; xhr.onerror = function(e) { alert('同步失败:' + e && e['message']); }; } }