mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 01:10:16 +08:00
feat: 添加 ESLint 配置并优化代码风格,移除未使用的功能
This commit is contained in:
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -9,5 +9,10 @@
|
||||
],
|
||||
"url": "https://json.schemastore.org/electron-builder"
|
||||
}
|
||||
],
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"vue"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import { ref } from 'vue';
|
||||
export let isLoaded = ref(false);
|
||||
export const isLoaded = ref(false);
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ipcMain, WebContents } from 'electron';
|
||||
import { spawn, ChildProcess, exec } from 'node:child_process';
|
||||
import readline from 'node:readline';
|
||||
import { promisify } from 'node:util';
|
||||
import pino from 'pino';
|
||||
|
||||
@@ -122,7 +121,7 @@ const parseUpgradableList = (output: string) => {
|
||||
// Listen for download requests from renderer process
|
||||
ipcMain.on('queue-install', async (event, download_json) => {
|
||||
const download = JSON.parse(download_json);
|
||||
const { id, pkgname, upgradeOnly } = download || {};
|
||||
const { id, pkgname } = download || {};
|
||||
|
||||
if (!id || !pkgname) {
|
||||
logger.warn('passed arguments missing id or pkgname');
|
||||
@@ -151,9 +150,9 @@ ipcMain.on('queue-install', async (event, download_json) => {
|
||||
const webContents = event.sender;
|
||||
|
||||
// 开始组装安装命令
|
||||
let superUserCmd = await checkSuperUserCommand();
|
||||
const superUserCmd = await checkSuperUserCommand();
|
||||
let execCommand = '';
|
||||
let execParams = [];
|
||||
const execParams = [];
|
||||
if (superUserCmd.length > 0) {
|
||||
execCommand = superUserCmd;
|
||||
execParams.push(SHELL_CALLER_PATH);
|
||||
@@ -258,7 +257,7 @@ ipcMain.handle('check-installed', async (_event, pkgname: string) => {
|
||||
|
||||
logger.info(`检查应用是否已安装: ${pkgname}`);
|
||||
|
||||
let child = spawn(SHELL_CALLER_PATH, ['apm', 'list', '--installed', pkgname], {
|
||||
const child = spawn(SHELL_CALLER_PATH, ['apm', 'list', '--installed', pkgname], {
|
||||
shell: true,
|
||||
env: process.env
|
||||
});
|
||||
@@ -291,16 +290,16 @@ ipcMain.on('remove-installed', async (_event, pkgname: string) => {
|
||||
}
|
||||
logger.info(`卸载已安装应用: ${pkgname}`);
|
||||
|
||||
let superUserCmd = await checkSuperUserCommand();
|
||||
const superUserCmd = await checkSuperUserCommand();
|
||||
let execCommand = '';
|
||||
let execParams = [];
|
||||
const execParams = [];
|
||||
if (superUserCmd.length > 0) {
|
||||
execCommand = superUserCmd;
|
||||
execParams.push(SHELL_CALLER_PATH);
|
||||
} else {
|
||||
execCommand = SHELL_CALLER_PATH;
|
||||
}
|
||||
let child = spawn(execCommand, [...execParams, 'apm', 'remove', '-y', pkgname], {
|
||||
const child = spawn(execCommand, [...execParams, 'apm', 'remove', '-y', pkgname], {
|
||||
shell: true,
|
||||
env: process.env
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import pino from "pino";
|
||||
|
||||
const logger = pino({ 'name': 'deeplink.ts' });
|
||||
type Query = Record<string, string>;
|
||||
export type Listener = (query: Query) => any;
|
||||
export type Listener = (query: Query) => void;
|
||||
|
||||
class ListenersMap {
|
||||
private map: Map<string, Set<Listener>> = new Map();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { app, BrowserWindow, ipcMain, Menu, shell, Tray } from 'electron'
|
||||
import { createRequire } from 'node:module'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'node:path'
|
||||
import os from 'node:os'
|
||||
@@ -19,7 +18,6 @@ import './backend/install-manager.js'
|
||||
import './handle-url-scheme.js'
|
||||
|
||||
const logger = pino({ 'name': 'index.ts' });
|
||||
const require = createRequire(import.meta.url)
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
// The built directory structure
|
||||
@@ -187,8 +185,13 @@ app.whenReady().then(() => {
|
||||
// 双击触发
|
||||
tray.on('click', () => {
|
||||
// 双击通知区图标实现应用的显示或隐藏
|
||||
win.isVisible() ? win.hide() : win.show()
|
||||
win.isVisible() ? win.setSkipTaskbar(false) : win.setSkipTaskbar(true);
|
||||
if (win.isVisible()) {
|
||||
win.hide();
|
||||
win.setSkipTaskbar(true);
|
||||
} else {
|
||||
win.show();
|
||||
win.setSkipTaskbar(false);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
@@ -123,7 +123,8 @@ const { appendLoading, removeLoading } = useLoading()
|
||||
domReady().then(appendLoading)
|
||||
|
||||
window.onmessage = (ev) => {
|
||||
ev.data.payload === 'removeLoading' && removeLoading()
|
||||
if (ev.data.payload === 'removeLoading')
|
||||
removeLoading()
|
||||
}
|
||||
|
||||
setTimeout(removeLoading, 4999)
|
||||
|
||||
17
eslint.config.ts
Normal file
17
eslint.config.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
import eslintConfigPrettier from "eslint-config-prettier/flat";
|
||||
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
|
||||
|
||||
export default defineConfig([
|
||||
globalIgnores(["**/3rdparty/**", "**/node_modules/**", "**/dist/**", "**/dist-electron/**"]),
|
||||
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts,vue}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||
tseslint.configs.recommended,
|
||||
pluginVue.configs["flat/essential"],
|
||||
{ files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser } } },
|
||||
eslintConfigPrettier,
|
||||
eslintPluginPrettierRecommended,
|
||||
]);
|
||||
13
package.json
13
package.json
@@ -26,15 +26,26 @@
|
||||
"build:vite": "vue-tsc --noEmit && vite build --mode production",
|
||||
"build:rpm": "vue-tsc --noEmit && vite build --mode production && electron-builder --config electron-builder.yml --linux rpm",
|
||||
"build:deb": "vue-tsc --noEmit && vite build --mode production && electron-builder --config electron-builder.yml --linux deb",
|
||||
"preview": "vite preview --mode debug"
|
||||
"preview": "vite preview --mode debug",
|
||||
"lint": "eslint --ext .ts,.vue src electron"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dotenvx/dotenvx": "^1.51.4",
|
||||
"@eslint/create-config": "^1.11.0",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@loongdotjs/electron-builder": "^26.0.12-1",
|
||||
"@vitejs/plugin-vue": "^6.0.3",
|
||||
"electron": "^40.0.0",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
"eslint-plugin-vue": "^10.7.0",
|
||||
"globals": "^17.3.0",
|
||||
"jiti": "^2.6.1",
|
||||
"pino-pretty": "^13.1.3",
|
||||
"prettier": "3.8.1",
|
||||
"typescript": "^5.4.2",
|
||||
"typescript-eslint": "^8.55.0",
|
||||
"vite": "^6.4.1",
|
||||
"vite-plugin-electron": "^0.29.0",
|
||||
"vite-plugin-electron-renderer": "^0.14.5",
|
||||
|
||||
81
src/App.vue
81
src/App.vue
@@ -59,8 +59,9 @@ import UninstallConfirmModal from './components/UninstallConfirmModal.vue';
|
||||
import { APM_STORE_BASE_URL, currentApp, currentAppIsInstalled } from './global/storeConfig';
|
||||
import { downloads, removeDownloadItem, watchDownloadsChange } from './global/downloadStatus';
|
||||
import { handleInstall, handleRetry, handleUpgrade } from './modeuls/processInstall';
|
||||
import type { App, AppJson, DownloadItem, UpdateAppItem, InstalledAppInfo, ChannelPayload } from './global/typedefinition';
|
||||
import type { App, AppJson, DownloadItem, UpdateAppItem, ChannelPayload } from './global/typedefinition';
|
||||
import type { Ref } from 'vue';
|
||||
import type { IpcRendererEvent } from 'electron';
|
||||
const logger = pino();
|
||||
|
||||
// Axios 全局配置
|
||||
@@ -250,9 +251,9 @@ const refreshUpgradableApps = async () => {
|
||||
selected: false,
|
||||
upgrading: false
|
||||
}));
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
upgradableApps.value = [];
|
||||
updateError.value = error?.message || '检查更新失败';
|
||||
updateError.value = (error as Error)?.message || '检查更新失败';
|
||||
} finally {
|
||||
updateLoading.value = false;
|
||||
}
|
||||
@@ -322,7 +323,7 @@ const refreshInstalledApps = async () => {
|
||||
installedError.value = result?.message || '读取已安装应用失败';
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
installedApps.value = []
|
||||
for (const app of result.apps) {
|
||||
let appInfo = apps.value.find(a => a.pkgname === app.pkgname);
|
||||
@@ -355,9 +356,9 @@ const refreshInstalledApps = async () => {
|
||||
}
|
||||
installedApps.value.push(appInfo);
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
installedApps.value = [];
|
||||
installedError.value = error?.message || '读取已安装应用失败';
|
||||
installedError.value = (error as Error)?.message || '读取已安装应用失败';
|
||||
} finally {
|
||||
installedLoading.value = false;
|
||||
}
|
||||
@@ -409,70 +410,6 @@ const uninstallInstalledApp = (app: App) => {
|
||||
requestUninstall(app);
|
||||
};
|
||||
|
||||
const openApmStoreUrl = (url: string, { fallbackText }: { fallbackText: string }) => {
|
||||
try {
|
||||
window.location.href = url;
|
||||
} catch (e) {
|
||||
showProtocolFallback(fallbackText);
|
||||
}
|
||||
};
|
||||
|
||||
const showProtocolFallback = (cmd: string) => {
|
||||
const existing = document.getElementById('protocolFallbackBox');
|
||||
if (existing) existing.remove();
|
||||
|
||||
const box = document.createElement('div');
|
||||
box.id = 'protocolFallbackBox';
|
||||
box.style.position = 'fixed';
|
||||
box.style.right = '18px';
|
||||
box.style.bottom = '18px';
|
||||
box.style.zIndex = '2000';
|
||||
box.style.boxShadow = 'var(--shadow)';
|
||||
box.style.background = 'var(--card)';
|
||||
box.style.borderRadius = '12px';
|
||||
box.style.padding = '12px';
|
||||
box.style.maxWidth = '420px';
|
||||
box.style.fontSize = '13px';
|
||||
box.innerHTML = `
|
||||
<div style="font-weight:600;margin-bottom:6px;">无法直接启动本地应用?</div>
|
||||
<div style="color:var(--muted);margin-bottom:8px;">请在终端执行下列命令,或检查系统是否已将 <code>apmstore://</code> 协议关联到 APM 处理程序。</div>
|
||||
<div style="display:flex;gap:8px;align-items:center;">
|
||||
<code style="padding:6px 8px;border-radius:8px;background:var(--glass);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${escapeHtml(cmd)}</code>
|
||||
<button id="copyApmCmd" class="action-btn secondary" title="复制命令">复制</button>
|
||||
<button id="dismissApmCmd" class="action-btn" title="关闭">关闭</button>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(box);
|
||||
|
||||
document.getElementById('copyApmCmd')?.addEventListener('click', () => {
|
||||
navigator.clipboard?.writeText(cmd).then(() => {
|
||||
alert('命令已复制到剪贴板');
|
||||
}).catch(() => {
|
||||
prompt('请手动复制命令:', cmd);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('dismissApmCmd')?.addEventListener('click', () => {
|
||||
box.remove();
|
||||
});
|
||||
|
||||
// 自动消失
|
||||
setTimeout(() => {
|
||||
try { box.remove(); } catch (e) { }
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
const escapeHtml = (s: string) => {
|
||||
if (!s) return '';
|
||||
return s.replace(/[&<>"']/g, (c) => ({
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
})[c as '&' | '<' | '>' | '"' | "'"]);
|
||||
};
|
||||
|
||||
// 目前 APM 商店不能暂停下载(因为 APM 本身不支持),但保留这些方法以备将来使用
|
||||
const pauseDownload = (id: DownloadItem) => {
|
||||
const download = downloads.value.find(d => d.id === id.id);
|
||||
@@ -660,7 +597,7 @@ onMounted(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
window.ipcRenderer.on('deep-link-install', (_event: Electron.IpcRendererEvent, pkgname: string) => {
|
||||
window.ipcRenderer.on('deep-link-install', (_event: IpcRendererEvent, pkgname: string) => {
|
||||
const tryOpen = () => {
|
||||
const target = apps.value.find(a => a.pkgname === pkgname);
|
||||
if (target) {
|
||||
@@ -682,7 +619,7 @@ onMounted(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
window.ipcRenderer.on('remove-complete', (_event: Electron.IpcRendererEvent, payload: ChannelPayload) => {
|
||||
window.ipcRenderer.on('remove-complete', (_event: IpcRendererEvent, payload: ChannelPayload) => {
|
||||
const pkgname = currentApp.value?.pkgname
|
||||
if(payload.success && pkgname){
|
||||
removeDownloadItem(pkgname);
|
||||
|
||||
@@ -146,18 +146,6 @@ const handleOverlayClick = () => {
|
||||
close();
|
||||
};
|
||||
|
||||
const pause = () => {
|
||||
// emit('pause', props.download.id);
|
||||
};
|
||||
|
||||
const resume = () => {
|
||||
// emit('resume', props.download.id);
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
//emit('cancel', props.download.id);
|
||||
};
|
||||
|
||||
const retry = () => {
|
||||
if (props.download) {
|
||||
emit('retry', props.download);
|
||||
|
||||
@@ -100,18 +100,6 @@ const toggleExpand = () => {
|
||||
isExpanded.value = !isExpanded.value;
|
||||
};
|
||||
|
||||
const pauseDownload = (id: string) => {
|
||||
// emit('pause', id);
|
||||
};
|
||||
|
||||
const resumeDownload = (id: string) => {
|
||||
// emit('resume', id);
|
||||
};
|
||||
|
||||
const cancelDownload = (id: string) => {
|
||||
// emit('cancel', id);
|
||||
};
|
||||
|
||||
const retryDownload = (download: DownloadItem) => {
|
||||
emit('retry', download);
|
||||
};
|
||||
|
||||
@@ -90,6 +90,7 @@ defineProps<{
|
||||
hasSelected: boolean;
|
||||
}>();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const emit = defineEmits<{
|
||||
(e: 'close'): void;
|
||||
(e: 'refresh'): void;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { currentApp, currentAppIsInstalled } from "../global/storeConfig";
|
||||
import { APM_STORE_BASE_URL } from "../global/storeConfig";
|
||||
import { downloads } from "../global/downloadStatus";
|
||||
|
||||
import { InstallLog, DownloadItem, DownloadResult, App } from '../global/typedefinition';
|
||||
import { InstallLog, DownloadItem, DownloadResult, App, DownloadItemStatus } from '../global/typedefinition';
|
||||
|
||||
let downloadIdCounter = 0;
|
||||
const logger = pino({ name: 'processInstall.ts' });
|
||||
@@ -110,7 +110,7 @@ window.ipcRenderer.on('remove-complete', (_event, log: DownloadResult) => {
|
||||
|
||||
window.ipcRenderer.on('install-status', (_event, log: InstallLog) => {
|
||||
const downloadObj = downloads.value.find(d => d.id === log.id);
|
||||
if(downloadObj) downloadObj.status = log.message as any;
|
||||
if(downloadObj) downloadObj.status = log.message as DownloadItemStatus;
|
||||
});
|
||||
window.ipcRenderer.on('install-log', (_event, log: InstallLog) => {
|
||||
const downloadObj = downloads.value.find(d => d.id === log.id);
|
||||
|
||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
|
||||
Reference in New Issue
Block a user