101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
// 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 ""
|
||
}
|
||
|
||
// Convert 转换账单文件格式(xlsx -> csv,处理 GBK 编码等)
|
||
// 子进程模式不支持此功能,请使用 HTTP 模式
|
||
func (c *Cleaner) Convert(inputPath string) (outputPath string, billType string, err error) {
|
||
return "", "", fmt.Errorf("子进程模式不支持文件格式转换,请使用 HTTP 模式 (analyzer_mode: http)")
|
||
}
|
||
|
||
// 确保 Cleaner 实现了 adapter.Cleaner 接口
|
||
var _ adapter.Cleaner = (*Cleaner)(nil)
|