Merge remote-tracking branch 'origin/feature/refactor' into feature/refactor

# Conflicts:
#	frontend/src/views/MAAUserEdit.vue
This commit is contained in:
MoeSnowyFox
2025-09-14 23:34:12 +08:00
9 changed files with 1656 additions and 541 deletions

View File

@@ -590,12 +590,125 @@ ipcMain.handle('download-git', async () => {
ipcMain.handle('check-git-update', async () => {
try {
// 这里可以实现检查Git仓库更新的逻辑
// 暂时返回false表示没有更新
return { hasUpdate: false }
const appRoot = getAppRoot()
// 检查是否为Git仓库
const gitDir = path.join(appRoot, '.git')
if (!fs.existsSync(gitDir)) {
log.info('不是Git仓库跳过更新检查')
return { hasUpdate: false }
}
// 检查Git可执行文件是否存在
const gitPath = path.join(appRoot, 'environment', 'git', 'bin', 'git.exe')
if (!fs.existsSync(gitPath)) {
log.warn('Git可执行文件不存在无法检查更新')
return { hasUpdate: false, error: 'Git可执行文件不存在' }
}
// 获取Git环境变量
const gitEnv = {
...process.env,
PATH: `${path.join(appRoot, 'environment', 'git', 'bin')};${path.join(appRoot, 'environment', 'git', 'mingw64', 'bin')};${process.env.PATH}`,
GIT_EXEC_PATH: path.join(appRoot, 'environment', 'git', 'mingw64', 'libexec', 'git-core'),
HOME: process.env.USERPROFILE || process.env.HOME,
GIT_CONFIG_NOSYSTEM: '1',
GIT_TERMINAL_PROMPT: '0',
GIT_ASKPASS: '',
}
log.info('开始检查Git仓库更新...')
// 执行 git fetch 获取最新的远程信息
await new Promise<void>((resolve, reject) => {
const fetchProc = spawn(gitPath, ['fetch', 'origin'], {
stdio: 'pipe',
env: gitEnv,
cwd: appRoot,
})
fetchProc.stdout?.on('data', (data) => {
log.info('git fetch output:', data.toString())
})
fetchProc.stderr?.on('data', (data) => {
log.info('git fetch stderr:', data.toString())
})
fetchProc.on('close', (code) => {
if (code === 0) {
resolve()
} else {
reject(new Error(`git fetch失败退出码: ${code}`))
}
})
fetchProc.on('error', reject)
})
// 检查本地分支是否落后于远程分支
const hasUpdate = await new Promise<boolean>((resolve, reject) => {
const statusProc = spawn(gitPath, ['status', '-uno', '--porcelain=v1'], {
stdio: 'pipe',
env: gitEnv,
cwd: appRoot,
})
let output = ''
statusProc.stdout?.on('data', (data) => {
output += data.toString()
})
statusProc.stderr?.on('data', (data) => {
log.info('git status stderr:', data.toString())
})
statusProc.on('close', (code) => {
if (code === 0) {
// 检查是否有 "Your branch is behind" 的信息
// 使用 git rev-list 来比较本地和远程分支
const revListProc = spawn(gitPath, ['rev-list', '--count', 'HEAD..origin/feature/refactor'], {
stdio: 'pipe',
env: gitEnv,
cwd: appRoot,
})
let revOutput = ''
revListProc.stdout?.on('data', (data) => {
revOutput += data.toString()
})
revListProc.on('close', (revCode) => {
if (revCode === 0) {
const commitsBehind = parseInt(revOutput.trim())
const hasUpdates = commitsBehind > 0
log.info(`本地分支落后远程分支 ${commitsBehind} 个提交hasUpdate: ${hasUpdates}`)
resolve(hasUpdates)
} else {
log.warn('无法比较本地和远程分支,假设有更新')
resolve(true) // 如果无法确定,假设有更新
}
})
revListProc.on('error', () => {
log.warn('git rev-list执行失败假设有更新')
resolve(true)
})
} else {
reject(new Error(`git status失败退出码: ${code}`))
}
})
statusProc.on('error', reject)
})
log.info(`Git更新检查完成hasUpdate: ${hasUpdate}`)
return { hasUpdate }
} catch (error) {
log.error('检查Git更新失败:', error)
return { hasUpdate: false, error: error instanceof Error ? error.message : String(error) }
// 如果检查失败返回true以触发更新流程确保代码是最新的
return { hasUpdate: true, error: error instanceof Error ? error.message : String(error) }
}
})

View File

@@ -37,24 +37,24 @@
type="primary"
ghost
size="middle"
@click="handleMAAConfig(script)"
@click="handleStartMAAConfig(script)"
>
<template #icon>
<SettingOutlined />
</template>
置MAA全局配置
置MAA
</a-button>
<a-button
v-if="script.type === 'MAA' && props.activeConnections.has(script.id)"
type="primary"
danger
size="middle"
@click="handleDisconnectMAA(script)"
style="background: #52c41a; border-color: #52c41a;"
@click="handleSaveMAAConfig(script)"
>
<template #icon>
<StopOutlined />
<SaveOutlined />
</template>
断开配置连接
保存配置
</a-button>
<a-button type="default" size="middle" @click="handleEdit(script)">
<template #icon>
@@ -291,8 +291,8 @@ import type { Script, User } from '../types/script'
import {
DeleteOutlined,
EditOutlined,
SaveOutlined,
SettingOutlined,
StopOutlined,
UserAddOutlined,
} from '@ant-design/icons-vue'
@@ -312,9 +312,9 @@ interface Emits {
(e: 'deleteUser', user: User): void
(e: 'maaConfig', script: Script): void
(e: 'startMaaConfig', script: Script): void
(e: 'disconnectMaa', script: Script): void
(e: 'saveMaaConfig', script: Script): void
(e: 'toggleUserStatus', user: User): void
}
@@ -350,12 +350,12 @@ const handleDeleteUser = (user: User) => {
emit('deleteUser', user)
}
const handleMAAConfig = (script: Script) => {
emit('maaConfig', script)
const handleStartMAAConfig = (script: Script) => {
emit('startMaaConfig', script)
}
const handleDisconnectMAA = (script: Script) => {
emit('disconnectMaa', script)
const handleSaveMAAConfig = (script: Script) => {
emit('saveMaaConfig', script)
}
const handleToggleUserStatus = (user: User) => {

File diff suppressed because it is too large Load Diff

View File

@@ -40,8 +40,8 @@
@add-user="handleAddUser"
@edit-user="handleEditUser"
@delete-user="handleDeleteUser"
@maa-config="handleMAAConfig"
@disconnect-maa="handleDisconnectMAA"
@start-maa-config="handleStartMAAConfig"
@save-maa-config="handleSaveMAAConfig"
@toggle-user-status="handleToggleUserStatus"
/>
@@ -232,6 +232,8 @@ import { useScriptApi } from '@/composables/useScriptApi'
import { useUserApi } from '@/composables/useUserApi'
import { useWebSocket } from '@/composables/useWebSocket'
import { useTemplateApi, type WebConfigTemplate } from '@/composables/useTemplateApi'
import { Service } from '@/api/services/Service'
import { TaskCreateIn } from '@/api/models/TaskCreateIn'
import MarkdownIt from 'markdown-it'
const router = useRouter()
@@ -494,51 +496,89 @@ const handleDeleteUser = async (user: User) => {
}
}
const handleMAAConfig = async (script: Script) => {
const handleStartMAAConfig = async (script: Script) => {
try {
// 检查是否已有连接
const existingConnection = activeConnections.value.get(script.id)
if (existingConnection) {
message.warning('该脚本已在配置中,请先断开连接')
message.warning('该脚本已在配置中,请先保存配置')
return
}
// 新订阅
subscribe(script.id, {
onError: error => {
console.error(`脚本 ${script.name} 连接错误:`, error)
message.error(`MAA配置连接失败: ${error}`)
activeConnections.value.delete(script.id)
},
// 调用启动配置任务API
const response = await Service.addTaskApiDispatchStartPost({
taskId: script.id,
mode: TaskCreateIn.mode.SettingScriptMode
})
// 记录连接
activeConnections.value.set(script.id, script.id)
message.success(`已开始配置 ${script.name}`)
// 可选设置自动断开连接的定时器比如30分钟后
setTimeout(
() => {
if (activeConnections.value.has(script.id)) {
unsubscribe(script.id)
if (response.code === 200) {
// 订阅WebSocket消息
subscribe(response.websocketId, {
onError: error => {
console.error(`脚本 ${script.name} 连接错误:`, error)
message.error(`MAA配置连接失败: ${error}`)
activeConnections.value.delete(script.id)
message.info(`${script.name} 配置会话已超时断开`)
},
onResult: (data: any) => {
// 处理配置完成消息(兼容任何结构)
if (data.Accomplish) {
message.success(`${script.name} 配置已完成`)
activeConnections.value.delete(script.id)
}
}
},
30 * 60 * 1000
) // 30分钟
})
// 记录连接和websocketId
activeConnections.value.set(script.id, response.websocketId)
message.success(`已启动 ${script.name} 的MAA配置`)
// 设置自动断开连接的定时器30分钟后
setTimeout(
() => {
if (activeConnections.value.has(script.id)) {
const wsId = activeConnections.value.get(script.id)
if (wsId) {
unsubscribe(wsId)
}
activeConnections.value.delete(script.id)
message.info(`${script.name} 配置会话已超时断开`)
}
},
30 * 60 * 1000
) // 30分钟
} else {
message.error(response.message || '启动MAA配置失败')
}
} catch (error) {
console.error('MAA配置失败:', error)
message.error('MAA配置失败')
console.error('启动MAA配置失败:', error)
message.error('启动MAA配置失败')
}
}
const handleDisconnectMAA = (script: Script) => {
const connectionId = activeConnections.value.get(script.id)
if (connectionId) {
unsubscribe(script.id)
activeConnections.value.delete(script.id)
message.success(`已断开 ${script.name} 的配置连接`)
const handleSaveMAAConfig = async (script: Script) => {
try {
const websocketId = activeConnections.value.get(script.id)
if (!websocketId) {
message.error('未找到活动的配置会话')
return
}
// 调用停止配置任务API
const response = await Service.stopTaskApiDispatchStopPost({
taskId: websocketId
})
if (response.code === 200) {
// 取消订阅
unsubscribe(websocketId)
activeConnections.value.delete(script.id)
message.success(`${script.name} 的配置已保存`)
} else {
message.error(response.message || '保存配置失败')
}
} catch (error) {
console.error('保存MAA配置失败:', error)
message.error('保存MAA配置失败')
}
}