1
This commit is contained in:
8
electron-vue-template/scripts/copy-assets.js
Normal file
8
electron-vue-template/scripts/copy-assets.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const Path = require('path');
|
||||
const FileSystem = require('fs-extra');
|
||||
|
||||
async function copyAssets() {
|
||||
console.log('Static assets are now handled by Vite from src/renderer/public');
|
||||
}
|
||||
|
||||
module.exports = copyAssets;
|
||||
@@ -111,12 +111,10 @@ function getSplashPath(): string {
|
||||
|
||||
return join(__dirname, '../../public/splash.html');
|
||||
}
|
||||
|
||||
function getIconPath(): string {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return join(__dirname, '../../public/icon/icon.png');
|
||||
}
|
||||
|
||||
const bundledIconPath = join(process.resourcesPath, 'app.asar.unpacked/public/icon/icon.png');
|
||||
if (existsSync(bundledIconPath)) {
|
||||
return bundledIconPath;
|
||||
@@ -230,7 +228,7 @@ function startSpringBoot() {
|
||||
}
|
||||
}
|
||||
|
||||
startSpringBoot();
|
||||
// startSpringBoot();
|
||||
|
||||
function stopSpringBoot() {
|
||||
if (!springProcess) return;
|
||||
@@ -268,7 +266,7 @@ function createWindow() {
|
||||
|
||||
Menu.setApplicationMenu(null);
|
||||
mainWindow.setMenuBarVisibility(false);
|
||||
|
||||
|
||||
// 打开开发者工具
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
mainWindow.webContents.openDevTools();
|
||||
@@ -315,7 +313,6 @@ app.whenReady().then(() => {
|
||||
splashWindow.loadFile(splashPath);
|
||||
}
|
||||
|
||||
//11111
|
||||
// setTimeout(() => {
|
||||
// openAppIfNotOpened();
|
||||
// }, 2000);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="version-info" @click="autoCheck">v{{ version || '-' }}</div>
|
||||
|
||||
<el-dialog v-model="show" width="522px" :close-on-click-modal="false" align-center class="update-dialog"
|
||||
:title="stage === 'downloading' ? `正在更新 ${appName}` : '软件更新'">
|
||||
<div v-if="stage === 'check'" class="update-content">
|
||||
@@ -14,7 +13,6 @@
|
||||
<p class="desc">{{ appName }} {{ info.latestVersion }} 可供安装,您现在的版本是 {{
|
||||
version
|
||||
}},要现在安装吗?</p>
|
||||
|
||||
<div class="update-details form">
|
||||
<h4>更新信息</h4>
|
||||
<el-input
|
||||
@@ -25,14 +23,13 @@
|
||||
readonly
|
||||
resize="none"/>
|
||||
</div>
|
||||
|
||||
<div class="update-actions row">
|
||||
<div class="update-buttons">
|
||||
<div class="left-actions">
|
||||
<el-button size="small" @click="show=false">跳过这个版本</el-button>
|
||||
<el-button size="small" @click="skipVersion">跳过这个版本</el-button>
|
||||
</div>
|
||||
<div class="right-actions">
|
||||
<el-button size="small" @click="show=false">稍后提醒</el-button>
|
||||
<el-button size="small" @click="remindLater">稍后提醒</el-button>
|
||||
<el-button size="small" type="primary" @click="start">下载更新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,7 +61,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="stage === 'completed'" class="update-content">
|
||||
<div class="update-header text-center">
|
||||
<img src="/icon/icon.png" class="app-icon" alt="App Icon"/>
|
||||
@@ -118,6 +114,9 @@ const info = ref({
|
||||
hasUpdate: false
|
||||
})
|
||||
|
||||
const SKIP_VERSION_KEY = 'skipped_version'
|
||||
const REMIND_LATER_KEY = 'remind_later_time'
|
||||
|
||||
async function autoCheck() {
|
||||
try {
|
||||
version.value = await (window as any).electronAPI.getJarVersion()
|
||||
@@ -129,6 +128,18 @@ async function autoCheck() {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否跳过此版本
|
||||
const skippedVersion = localStorage.getItem(SKIP_VERSION_KEY)
|
||||
if (skippedVersion === result.latestVersion) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否在稍后提醒时间内
|
||||
const remindLater = localStorage.getItem(REMIND_LATER_KEY)
|
||||
if (remindLater && Date.now() < parseInt(remindLater)) {
|
||||
return
|
||||
}
|
||||
|
||||
info.value = {
|
||||
currentVersion: result.currentVersion,
|
||||
latestVersion: result.latestVersion,
|
||||
@@ -145,6 +156,17 @@ async function autoCheck() {
|
||||
}
|
||||
}
|
||||
|
||||
function skipVersion() {
|
||||
localStorage.setItem(SKIP_VERSION_KEY, info.value.latestVersion)
|
||||
show.value = false
|
||||
}
|
||||
|
||||
function remindLater() {
|
||||
// 24小时后再提醒
|
||||
localStorage.setItem(REMIND_LATER_KEY, (Date.now() + 24 * 60 * 60 * 1000).toString())
|
||||
show.value = false
|
||||
}
|
||||
|
||||
async function start() {
|
||||
if (!info.value.downloadUrl) {
|
||||
ElMessage.error('下载链接不可用')
|
||||
@@ -222,6 +244,8 @@ onMounted(async () => {
|
||||
onUnmounted(() => {
|
||||
(window as any).electronAPI.removeDownloadProgressListener()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -396,10 +420,6 @@ onUnmounted(() => {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.download-header {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.download-header h3 {
|
||||
font-size: 14px;
|
||||
|
||||
6
electron-vue-template/src/renderer/typings/element-plus-shim.d.ts
vendored
Normal file
6
electron-vue-template/src/renderer/typings/element-plus-shim.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
declare module 'element-plus' {
|
||||
export const ElMessage: (options: { message: string; type?: 'success' | 'warning' | 'error' | 'info' }) => void
|
||||
export const ElMessageBox: { confirm: (message: string, title?: string, options?: any) => Promise<void> }
|
||||
}
|
||||
|
||||
|
||||
78
electron-vue-template/src/renderer/utils/imageProxy.ts
Normal file
78
electron-vue-template/src/renderer/utils/imageProxy.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
/**
|
||||
* 通过后端代理获取图片并转换为Base64
|
||||
* @param imageUrl 原始图片URL
|
||||
* @param maxSize 最大尺寸,默认80px
|
||||
* @returns Promise<string | null> Base64字符串或null
|
||||
*/
|
||||
export async function convertImageToBase64ViaProxy(imageUrl: string, maxSize: number = 80): Promise<string | null> {
|
||||
if (!imageUrl) return null
|
||||
try {
|
||||
const proxyUrl = `http://127.0.0.1:8081/api/proxy/image-url?url=${encodeURIComponent(imageUrl)}`
|
||||
const response = await fetch(proxyUrl)
|
||||
if (!response.ok) return null
|
||||
|
||||
const contentType = response.headers.get('Content-Type')
|
||||
const arrayBuffer = await response.arrayBuffer()
|
||||
if (!arrayBuffer || arrayBuffer.byteLength === 0) return null
|
||||
if (arrayBuffer.byteLength < 1000) return null
|
||||
|
||||
const mimeType = contentType && contentType.startsWith('image/') ? contentType : 'image/jpeg'
|
||||
const imageBlob = new Blob([arrayBuffer], { type: mimeType })
|
||||
const objectUrl = URL.createObjectURL(imageBlob)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const img = new Image()
|
||||
|
||||
img.onload = () => {
|
||||
try {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ratio = Math.min(maxSize / img.width, maxSize / img.height)
|
||||
canvas.width = img.width * ratio
|
||||
canvas.height = img.height * ratio
|
||||
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx) {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
resolve(null)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
|
||||
const base64 = canvas.toDataURL('image/jpeg', 0.8)
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
resolve(base64)
|
||||
} catch (error) {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
resolve(null)
|
||||
}
|
||||
}
|
||||
|
||||
img.onerror = () => {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
img.src = objectUrl
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量处理图片转换
|
||||
* @param imageUrls 图片URL数组
|
||||
* @param maxSize 最大尺寸
|
||||
* @returns Promise<(string | null)[]> Base64数组
|
||||
*/
|
||||
export async function batchConvertImages(imageUrls: string[], maxSize: number = 80): Promise<(string | null)[]> {
|
||||
const promises = imageUrls.map(async (url) => {
|
||||
if (!url) return null
|
||||
return await convertImageToBase64ViaProxy(url, maxSize)
|
||||
})
|
||||
|
||||
return await Promise.all(promises)
|
||||
}
|
||||
123
electron-vue-template/src/renderer/utils/settings.ts
Normal file
123
electron-vue-template/src/renderer/utils/settings.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
// 应用设置管理工具
|
||||
|
||||
export type Platform = 'amazon' | 'rakuten' | 'zebra'
|
||||
|
||||
export interface PlatformExportSettings {
|
||||
exportPath: string
|
||||
}
|
||||
|
||||
export interface AppSettings {
|
||||
// 全局设置
|
||||
global: PlatformExportSettings
|
||||
// 平台特定设置
|
||||
platforms: {
|
||||
amazon: PlatformExportSettings
|
||||
rakuten: PlatformExportSettings
|
||||
zebra: PlatformExportSettings
|
||||
}
|
||||
}
|
||||
|
||||
const SETTINGS_KEY = 'app-settings'
|
||||
|
||||
// 默认平台设置
|
||||
const defaultPlatformSettings: PlatformExportSettings = {
|
||||
exportPath: ''
|
||||
}
|
||||
|
||||
// 默认设置
|
||||
const defaultSettings: AppSettings = {
|
||||
global: { ...defaultPlatformSettings },
|
||||
platforms: {
|
||||
amazon: { ...defaultPlatformSettings },
|
||||
rakuten: { ...defaultPlatformSettings },
|
||||
zebra: { ...defaultPlatformSettings }
|
||||
}
|
||||
}
|
||||
|
||||
// 获取设置
|
||||
export function getSettings(): AppSettings {
|
||||
const saved = localStorage.getItem(SETTINGS_KEY)
|
||||
if (saved) {
|
||||
const settings = JSON.parse(saved)
|
||||
return {
|
||||
global: { ...defaultSettings.global, ...settings.global },
|
||||
platforms: {
|
||||
amazon: { ...defaultSettings.platforms.amazon, ...settings.platforms?.amazon },
|
||||
rakuten: { ...defaultSettings.platforms.rakuten, ...settings.platforms?.rakuten },
|
||||
zebra: { ...defaultSettings.platforms.zebra, ...settings.platforms?.zebra }
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultSettings
|
||||
}
|
||||
|
||||
// 保存设置
|
||||
export function saveSettings(settings: Partial<AppSettings>): void {
|
||||
const current = getSettings()
|
||||
const updated = {
|
||||
global: { ...current.global, ...settings.global },
|
||||
platforms: {
|
||||
amazon: { ...current.platforms.amazon, ...settings.platforms?.amazon },
|
||||
rakuten: { ...current.platforms.rakuten, ...settings.platforms?.rakuten },
|
||||
zebra: { ...current.platforms.zebra, ...settings.platforms?.zebra }
|
||||
}
|
||||
}
|
||||
localStorage.setItem(SETTINGS_KEY, JSON.stringify(updated))
|
||||
}
|
||||
|
||||
// 保存平台特定设置
|
||||
export function savePlatformSettings(platform: Platform, settings: Partial<PlatformExportSettings>): void {
|
||||
const current = getSettings()
|
||||
const updated = {
|
||||
...current,
|
||||
platforms: {
|
||||
...current.platforms,
|
||||
[platform]: { ...current.platforms[platform], ...settings }
|
||||
}
|
||||
}
|
||||
localStorage.setItem(SETTINGS_KEY, JSON.stringify(updated))
|
||||
}
|
||||
|
||||
// 获取平台导出配置
|
||||
export function getPlatformExportConfig(platform: Platform): PlatformExportSettings {
|
||||
const settings = getSettings()
|
||||
return settings.platforms[platform]
|
||||
}
|
||||
|
||||
|
||||
// 处理平台特定文件导出
|
||||
export async function handlePlatformFileExport(
|
||||
platform: Platform,
|
||||
blob: Blob,
|
||||
defaultFileName: string
|
||||
): Promise<void> {
|
||||
const config = getPlatformExportConfig(platform)
|
||||
|
||||
if (!config.exportPath) {
|
||||
const result = await (window as any).electronAPI.showSaveDialog({
|
||||
title: '保存文件',
|
||||
defaultPath: defaultFileName,
|
||||
filters: [
|
||||
{ name: 'Excel 文件', extensions: ['xlsx', 'xls'] },
|
||||
{ name: '所有文件', extensions: ['*'] }
|
||||
]
|
||||
})
|
||||
|
||||
if (!result.canceled && result.filePath) {
|
||||
await writeFileToPath(blob, result.filePath)
|
||||
}
|
||||
} else {
|
||||
const filePath = `${config.exportPath}/${defaultFileName}`
|
||||
await writeFileToPath(blob, filePath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 写入文件到指定路径
|
||||
async function writeFileToPath(blob: Blob, filePath: string): Promise<void> {
|
||||
const arrayBuffer = await blob.arrayBuffer()
|
||||
const buffer = new Uint8Array(arrayBuffer)
|
||||
const result = await (window as any).electronAPI.writeFile(filePath, buffer)
|
||||
if (!result.success) throw new Error(result.error)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<!-- 已移除 JavaFX/FxWeaver 相关依赖,保留为纯 Spring Boot -->
|
||||
<dependency>
|
||||
<groupId>com.qiniu</groupId>
|
||||
<artifactId>qiniu-java-sdk</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user