初步实现功能

This commit is contained in:
2025-08-06 14:15:15 +08:00
parent cbe3f72d1c
commit d57b5fb540
8 changed files with 3657 additions and 58 deletions

View File

@ -1,7 +1,7 @@
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");
let mainWindow
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
@ -9,22 +9,42 @@ function createWindow() {
height: 300,
transparent: true,
frame: false,
resizable: false, // 固定大小
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
}
})
preload: path.join(__dirname, "preload.js"),
contextIsolation: true,
},
});
// 开发模式加载Vite服务器
if (process.env.NODE_ENV === 'development') {
mainWindow.loadURL('http://localhost:5173')
if (process.env.NODE_ENV === "development") {
mainWindow.loadURL("http://localhost:5173");
} else {
mainWindow.loadFile(path.join(__dirname, '../renderer/dist/index.html'))
mainWindow.loadFile(path.join(__dirname, "../renderer/dist/index.html"));
}
mainWindow.setIgnoreMouseEvents(true, {
forward: true
})
// 窗口拖拽功能
let isDragging = false;
mainWindow.webContents.on("before-input-event", (_, input) => {
if (input.type === "mouseDown") {
isDragging = true;
mainWindow.webContents.executeJavaScript(`
window.dragOffset = { x: ${input.x}, y: ${input.y} }
`);
} else if (input.type === "mouseUp") {
isDragging = false;
}
});
mainWindow.on("moved", () => {
if (isDragging) {
mainWindow.webContents.executeJavaScript(`
window.electronAPI.updatePosition()
`);
}
const [x, y] = mainWindow.getPosition();
mainWindow.webContents.send("update-position", { x, y });
});
}
app.whenReady().then(createWindow)
app.whenReady().then(createWindow);

View File

@ -1,6 +1,9 @@
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
playSound: (file) => ipcRenderer.send('play-sound', file),
showTooltip: (text) => ipcRenderer.send('show-tooltip', text)
playSound: (soundFile) => ipcRenderer.send('play-sound', soundFile),
showTooltip: (text) => ipcRenderer.send('show-tooltip', text),
onUpdatePosition: (callback) => {
ipcRenderer.on('update-position', (_, position) => callback(position))
}
})

View File

@ -4,7 +4,9 @@
"description": "",
"main": "index.js",
"scripts": {
"dev": "concurrently \"cd renderer && npm run dev\" \"wait-on http://localhost:5173 && electron .\""
"dev": "concurrently \"cd renderer && npm run dev\" \"wait-on http://localhost:5173 && electron .\"",
"build": "cd renderer && npm run build && electron-builder",
"start": "electron ."
},
"repository": {
"type": "git",
@ -20,9 +22,14 @@
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"electron": "^37.2.5",
"vue": "^3.5.18"
"vue": "^3.5.18",
"concurrently": "^8.0.0",
"vite": "^4.0.0",
"wait-on": "^7.0.0"
},
"dependencies": {
"electron": "^37.2.5",
"vue": "^3.5.18",
"fs-extra": "^11.3.1",
"howler": "^2.2.4",
"path": "^0.12.7"

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@
"@vitejs/plugin-vue": "^6.0.0",
"@vue/tsconfig": "^0.7.0",
"concurrently": "^9.2.0",
"electron-builder": "^26.0.12",
"typescript": "~5.8.3",
"vite": "^7.0.4",
"vue-tsc": "^2.2.12",

View File

@ -1,39 +1,48 @@
<script setup>
import { ref, onMounted } from 'vue'
import petVideo from './assets/pet.mp4'
import { ref, onMounted } from "vue";
import petGif from "./assets/pet.gif";
// 配置数据
const tooltips = [
"说的道理",
]
const sounds = [
]
"说的道理~",
"尊尼获加",
"为什么不开大!!",
"(凤鸣)",
];
const soundFiles = ["example.mp3"];
const showTooltip = ref(false)
const currentTooltip = ref('')
// 状态管理
const showTooltip = ref(false);
const currentTooltip = ref("");
const position = ref({ x: 0, y: 0 });
// 点击事件处理
const handleClick = () => {
// 随机播放音效
const sound = sounds[Math.floor(Math.random() * sounds.length)]
window.electronAPI.playSound(sound)
// 随机显示提示
showTooltip.value = true
currentTooltip.value = tooltips[Math.floor(Math.random() * tooltips.length)]
setTimeout(() => showTooltip.value = false, 2000)
}
const randomSound = soundFiles[Math.floor(Math.random() * soundFiles.length)];
window.electronAPI?.playSound(randomSound);
currentTooltip.value = tooltips[Math.floor(Math.random() * tooltips.length)];
showTooltip.value = true;
setTimeout(() => (showTooltip.value = false), 2000);
};
// 初始化位置监听
onMounted(() => {
if (window.electronAPI) {
window.electronAPI.onUpdatePosition((pos) => {
position.value = pos;
});
}
});
</script>
<template>
<div class="container">
<!-- MP4素材播放 -->
<video
autoplay loop muted
:src="petVideo"
@click="handleClick"
/>
<!-- 文字提示框 -->
<div
class="pet-container"
:style="{ left: `${position.x}px`, top: `${position.y}px` }"
>
<img :src="petGif" class="pet-gif" @click="handleClick" draggable="false" />
<transition name="fade">
<div v-if="showTooltip" class="tooltip">
{{ currentTooltip }}
@ -43,22 +52,24 @@ const handleClick = () => {
</template>
<style scoped>
.container {
width: 100vw;
height: 100vh;
overflow: hidden;
.pet-container {
position: absolute;
width: 300px;
height: 300px;
-webkit-app-region: no-drag;
}
video {
.pet-gif {
width: 100%;
height: 100%;
object-fit: contain;
cursor: pointer;
user-select: none;
-webkit-user-drag: none;
}
.tooltip {
position: absolute;
bottom: 20px;
bottom: -40px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
@ -66,12 +77,15 @@ video {
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
white-space: nowrap;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter, .fade-leave-to {
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
</style>

BIN
renderer/src/assets/pet.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

@ -1,7 +1,11 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue()],
})
base: './',
build: {
assetsInlineLimit: 0
// 强制所有资源作为文件输出
}
})