chore: track version files, docs, web app split, scripts (missed commits from March work)

This commit is contained in:
2026-09-13 08:41:35 +08:00
parent 84c709bbcc
commit edf76db56b
33 changed files with 3082 additions and 504 deletions
+211
View File
@@ -0,0 +1,211 @@
console.log("[INP2P] boot", typeof Vue, Vue && Vue.version);
const { createApp, onMounted, onBeforeUnmount, watch } = Vue;
createApp({
setup(){
const state = window.INP2P.createState(Vue);
const { api, loginByPassword } = window.INP2P.createApi(state);
const { actions, refs, setSwitchTab } = window.INP2P.createActions(state, { api, loginByPassword, Vue });
const switchTab = async (next) => {
state.tab.value = next;
if (!state.loggedIn.value) return;
try {
if (next === 'tenants') await actions.loadTenants();
else if (next === 'apikeys') await actions.loadKeys();
else if (next === 'users') await actions.loadUsers();
else if (next === 'enroll') await actions.loadEnrolls();
else if (next === 'settings' && state.isAdmin.value) {
state.beginTab('settings');
try { state.settings.value = await api('/api/v1/admin/settings'); state.endTabOk('settings'); }
catch(_) { state.endTabErr('settings'); }
} else if (next === 'audit' && state.isAdmin.value) {
await actions.loadAudit();
} else if (next === 'sdwan') {
state.beginTab('sdwan');
try {
state.sd.value = await api('/api/v1/sdwans');
state.endTabOk('sdwan', !(state.sd.value?.nodes||[]).length);
} catch (e) { state.toast('SDWAN 加载失败: ' + (e.message || ''), 'error'); state.endTabErr('sdwan'); }
}
} catch (e) {
state.toast(e.message || '切换页面失败', 'error');
}
};
setSwitchTab(switchTab);
watch(state.refreshSec, actions.startTimer);
watch(state.loggedIn, (v) => {
if (v) actions.startTimer();
else actions.stopTimer();
});
watch(state.tenantKeyword, (v) => localStorage.setItem('inp2p_kw_tenant', String(v || '')));
watch(state.keyKeyword, (v) => localStorage.setItem('inp2p_kw_key', String(v || '')));
watch(state.userKeyword, (v) => localStorage.setItem('inp2p_kw_user', String(v || '')));
watch(state.enrollKeyword, (v) => localStorage.setItem('inp2p_kw_enroll', String(v || '')));
watch(state.keepFailedPool, (v) => localStorage.setItem('inp2p_keep_failed_pool', v ? '1' : '0'));
onMounted(() => {
state.applyTheme && state.applyTheme();
// 全局兜底:前端异常时保留可见提示,避免“瞬间空白”
window.addEventListener('error', (ev) => {
const m = (ev && ev.message) ? ev.message : 'unknown';
state.toast('前端异常:' + m, 'error');
state.logEvent && state.logEvent('error', { tab:'global', action:'window_error', message:m });
});
window.addEventListener('unhandledrejection', (ev) => {
const m = ev && ev.reason && ev.reason.message ? ev.reason.message : String(ev && ev.reason ? ev.reason : 'unknown');
state.toast('请求异常:' + m, 'error');
state.logEvent && state.logEvent('error', { tab:'global', action:'promise_rejection', message:m });
});
if (localStorage.getItem('t')) {
state.loggedIn.value = true;
actions.refreshAll();
switchTab(state.tab.value);
}
});
onBeforeUnmount(() => {
});
return {
buildVersion: state.buildVersion,
tab: state.tab,
filteredTabs: state.filteredTabs,
loggedIn: state.loggedIn,
loginBusy: state.loginBusy,
globalBusy: state.globalBusy,
tabBusy: state.tabBusy,
tabState: state.tabState,
debugMode: state.debugMode,
debugEvents: state.debugEvents,
clearDebugEvents: state.clearDebugEvents,
role: state.role,
roleLabel: state.roleLabel,
status: state.status,
tokenType: state.tokenType,
tenantId: state.tenantId,
loginUser: state.loginUser,
loginPass: state.loginPass,
loginErr: state.loginErr,
opSummary: state.opSummary,
refreshSec: state.refreshSec,
theme: state.theme,
health: state.health,
stats: state.stats,
nodes: state.nodes,
nodeKeyword: state.nodeKeyword,
filteredNodes: state.filteredNodes,
sd: state.sd,
connectForm: state.connectForm,
nodeEditVisible: state.nodeEditVisible,
nodeEditMode: state.nodeEditMode,
nodeEditTitle: state.nodeEditTitle,
nodeEditNode: state.nodeEditNode,
nodeEditValue: state.nodeEditValue,
tenants: state.tenants,
activeTenant: state.activeTenant,
keys: state.keys,
users: state.users,
enrolls: state.enrolls,
selectedKeyIds: state.selectedKeyIds,
selectedUserIds: state.selectedUserIds,
selectedEnrollIds: state.selectedEnrollIds,
bulkFailedKeyIds: state.bulkFailedKeyIds,
bulkFailedUserIds: state.bulkFailedUserIds,
bulkFailedEnrollIds: state.bulkFailedEnrollIds,
keepFailedPool: state.keepFailedPool,
auditPreset: state.auditPreset,
tenantKeyword: state.tenantKeyword,
keyKeyword: state.keyKeyword,
userKeyword: state.userKeyword,
enrollKeyword: state.enrollKeyword,
filteredTenants: state.filteredTenants,
filteredKeys: state.filteredKeys,
filteredUsers: state.filteredUsers,
filteredEnrolls: state.filteredEnrolls,
tenantForm: state.tenantForm,
keyForm: state.keyForm,
userForm: state.userForm,
settings: state.settings,
tenantFormErr: state.tenantFormErr,
keyFormErr: state.keyFormErr,
userFormErr: state.userFormErr,
sdwanFormErr: state.sdwanFormErr,
audit: state.audit,
auditTenant: state.auditTenant,
auditFilters: state.auditFilters,
auditActionOptions: state.auditActionOptions,
onlineMap: state.onlineMap,
nodeStatus: state.nodeStatus,
isOnline: state.isOnline,
nodeOnline: state.nodeOnline,
nodeStatusTextOf: state.nodeStatusTextOf,
nodeStatusClassOf: state.nodeStatusClassOf,
natText: state.natText,
uptime: state.uptime,
fmtTime: state.fmtTime,
appPushNode: refs.appPushNode,
appPushRaw: refs.appPushRaw,
login: actions.login,
logout: actions.logout,
refreshAll: actions.refreshAll,
switchTab,
toggleTheme: state.toggleTheme,
saveSDWAN: actions.saveSDWAN,
addSDWANNode: actions.addSDWANNode,
removeSDWANNode: actions.removeSDWANNode,
addSubnetProxy: actions.addSubnetProxy,
removeSubnetProxy: actions.removeSubnetProxy,
autoAssignIPs: actions.autoAssignIPs,
kickNode: actions.kickNode,
renameNode: actions.renameNode,
changeNodeIP: actions.changeNodeIP,
closeNodeEdit: actions.closeNodeEdit,
submitNodeEdit: actions.submitNodeEdit,
openAppManager: actions.openAppManager,
pushAppConfigs: actions.pushAppConfigs,
openConnect: actions.openConnect,
doConnect: actions.doConnect,
createTenant: actions.createTenant,
loadTenants: actions.loadTenants,
setTenantStatus: actions.setTenantStatus,
reassignTenantSubnet: actions.reassignTenantSubnet,
createKey: actions.createKey,
loadKeys: actions.loadKeys,
setKeyStatus: actions.setKeyStatus,
createUser: actions.createUser,
loadUsers: actions.loadUsers,
setUserStatus: actions.setUserStatus,
resetUserPassword: actions.resetUserPassword,
deleteUser: actions.deleteUser,
createEnroll: actions.createEnroll,
loadEnrolls: actions.loadEnrolls,
setEnrollStatus: actions.setEnrollStatus,
consumeEnroll: actions.consumeEnroll,
saveSettings: actions.saveSettings,
loadAudit: actions.loadAudit,
clearAuditFilters: actions.clearAuditFilters,
applyAuditPreset: actions.applyAuditPreset,
exportAuditCsv: actions.exportAuditCsv,
exportAuditFailuresCsv: actions.exportAuditFailuresCsv,
toggleAllKeys: actions.toggleAllKeys,
toggleAllUsers: actions.toggleAllUsers,
toggleAllEnrolls: actions.toggleAllEnrolls,
bulkSetKeyStatus: actions.bulkSetKeyStatus,
bulkSetUserStatus: actions.bulkSetUserStatus,
bulkSetEnrollStatus: actions.bulkSetEnrollStatus,
retryFailedKeyOps: actions.retryFailedKeyOps,
retryFailedUserOps: actions.retryFailedUserOps,
retryFailedEnrollOps: actions.retryFailedEnrollOps,
clearFailedPool: actions.clearFailedPool,
updateCharts: actions.updateCharts
};
}
}).mount('#app');