feat: 完善项目架构并增强分析页面功能
- 新增项目文档和 Docker 配置 - 添加 README.md 和 TODO.md 项目文档 - 为各服务添加 Dockerfile 和 docker-compose 配置 - 重构后端架构 - 新增 adapter 层(HTTP/Python 适配器) - 新增 repository 层(数据访问抽象) - 新增 router 模块统一管理路由 - 新增账单处理 handler - 扩展前端 UI 组件库 - 新增 Calendar、DateRangePicker、Drawer、Popover 等组件 - 集成 shadcn-svelte 组件库 - 增强分析页面功能 - 添加时间范围筛选器(支持本月默认值) - 修复 DateRangePicker 默认值显示问题 - 优化数据获取和展示逻辑 - 完善分析器服务 - 新增 FastAPI 服务接口 - 改进账单清理器实现
This commit is contained in:
94
server/adapter/python/cleaner.go
Normal file
94
server/adapter/python/cleaner.go
Normal file
@@ -0,0 +1,94 @@
|
||||
// Package python 实现通过子进程调用 Python 脚本的清洗器
|
||||
package python
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"billai-server/adapter"
|
||||
"billai-server/config"
|
||||
)
|
||||
|
||||
// Cleaner 通过子进程调用 Python 脚本的清洗器实现
|
||||
type Cleaner struct {
|
||||
pythonPath string // Python 解释器路径
|
||||
scriptPath string // 清洗脚本路径
|
||||
workDir string // 工作目录
|
||||
}
|
||||
|
||||
// NewCleaner 创建 Python 清洗器
|
||||
func NewCleaner() *Cleaner {
|
||||
return &Cleaner{
|
||||
pythonPath: config.ResolvePath(config.Global.PythonPath),
|
||||
scriptPath: config.ResolvePath(config.Global.CleanScript),
|
||||
workDir: config.Global.ProjectRoot,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCleanerWithConfig 使用自定义配置创建 Python 清洗器
|
||||
func NewCleanerWithConfig(pythonPath, scriptPath, workDir string) *Cleaner {
|
||||
return &Cleaner{
|
||||
pythonPath: pythonPath,
|
||||
scriptPath: scriptPath,
|
||||
workDir: workDir,
|
||||
}
|
||||
}
|
||||
|
||||
// Clean 执行 Python 清洗脚本
|
||||
func (c *Cleaner) Clean(inputPath, outputPath string, opts *adapter.CleanOptions) (*adapter.CleanResult, error) {
|
||||
// 构建命令参数
|
||||
args := []string{c.scriptPath, inputPath, outputPath}
|
||||
|
||||
if opts != nil {
|
||||
if opts.Year != "" {
|
||||
args = append(args, "--year", opts.Year)
|
||||
}
|
||||
if opts.Month != "" {
|
||||
args = append(args, "--month", opts.Month)
|
||||
}
|
||||
if opts.Start != "" {
|
||||
args = append(args, "--start", opts.Start)
|
||||
}
|
||||
if opts.End != "" {
|
||||
args = append(args, "--end", opts.End)
|
||||
}
|
||||
if opts.Format != "" {
|
||||
args = append(args, "--format", opts.Format)
|
||||
}
|
||||
}
|
||||
|
||||
// 执行 Python 脚本
|
||||
fmt.Printf("🐍 执行清洗脚本...\n")
|
||||
cmd := exec.Command(c.pythonPath, args...)
|
||||
cmd.Dir = c.workDir
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
outputStr := string(output)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("清洗脚本执行失败: %w\n输出: %s", err, outputStr)
|
||||
}
|
||||
|
||||
// 从输出中检测账单类型
|
||||
billType := detectBillTypeFromOutput(outputStr)
|
||||
|
||||
return &adapter.CleanResult{
|
||||
BillType: billType,
|
||||
Output: outputStr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// detectBillTypeFromOutput 从 Python 脚本输出中检测账单类型
|
||||
func detectBillTypeFromOutput(output string) string {
|
||||
if strings.Contains(output, "支付宝") {
|
||||
return "alipay"
|
||||
}
|
||||
if strings.Contains(output, "微信") {
|
||||
return "wechat"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 确保 Cleaner 实现了 adapter.Cleaner 接口
|
||||
var _ adapter.Cleaner = (*Cleaner)(nil)
|
||||
Reference in New Issue
Block a user