重构: 迁移后端代码到 app 目录,前端移动到 WebUI,添加完整测试套件

主要变更:
- 后端代码从根目录迁移到 app/ 目录
- 前端代码从 frontend/ 重命名为 WebUI/
- 更新所有导入路径以适配新结构
- 提取公共 API 响应函数到 app/api/common.py
- 精简验证器服务代码
- 更新启动脚本和文档

测试:
- 新增完整测试套件 (tests/)
- 单元测试: 模型、仓库层
- 集成测试: 覆盖所有 22+ API 端点
- E2E 测试: 4个完整工作流场景
- 添加 pytest 配置和测试运行脚本
This commit is contained in:
祀梦
2026-04-04 13:32:36 +08:00
parent df3cc87f88
commit 38bd66128b
109 changed files with 2017 additions and 548 deletions

107
WebUI/src/stores/plugins.js Normal file
View File

@@ -0,0 +1,107 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { pluginService } from '../services/pluginService'
/**
* Plugins Store
* 管理插件列表和状态
*/
export const usePluginsStore = defineStore('plugins', () => {
// ==================== State ====================
const plugins = ref([])
const loading = ref(false)
// ==================== Getters ====================
const enabledCount = computed(() => plugins.value.filter(p => p.enabled).length)
const totalCount = computed(() => plugins.value.length)
// ==================== Actions ====================
/**
* 获取插件列表
* @returns {Promise<boolean>}
*/
async function fetchPlugins() {
loading.value = true
try {
const response = await pluginService.getPlugins()
if (response.code === 200) {
plugins.value = response.data.plugins || []
return true
}
} catch (error) {
console.error('获取插件列表失败:', error)
} finally {
loading.value = false
}
return false
}
/**
* 切换插件启用状态
* @param {string|number} pluginId
* @param {boolean} enabled
* @returns {Promise<boolean>}
*/
async function togglePlugin(pluginId, enabled) {
try {
const response = await pluginService.togglePlugin(pluginId, enabled)
if (response.code === 200) {
const plugin = plugins.value.find(p => p.id === pluginId)
if (plugin) {
plugin.enabled = enabled
}
return true
}
} catch (error) {
console.error('切换插件状态失败:', error)
}
return false
}
/**
* 触发插件爬取
* @param {string|number} pluginId
* @returns {Promise<boolean>}
*/
async function crawlPlugin(pluginId) {
try {
const response = await pluginService.crawlPlugin(pluginId)
return response.code === 200
} catch (error) {
console.error('触发插件爬取失败:', error)
return false
}
}
/**
* 根据 ID 获取插件
* @param {string|number} id
* @returns {object|undefined}
*/
function getPluginById(id) {
return plugins.value.find(p => p.id === id)
}
/**
* 重置状态
*/
function reset() {
plugins.value = []
}
return {
// State
plugins,
loading,
// Getters
enabledCount,
totalCount,
// Actions
fetchPlugins,
togglePlugin,
crawlPlugin,
getPluginById,
reset
}
})