1256 lines
34 KiB
Go
1256 lines
34 KiB
Go
package main
|
||
|
||
/*
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
*/
|
||
import "C"
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"path/filepath"
|
||
"runtime"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
"unicode/utf8"
|
||
"unsafe"
|
||
"xianyv/controller"
|
||
|
||
route "xianyv/http/route"
|
||
"xianyv/http/service"
|
||
_type "xianyv/type"
|
||
"xianyv/utils/iniConfigUtil"
|
||
"xianyv/utils/tokenConsumerUtil"
|
||
|
||
"github.com/redis/go-redis/v9"
|
||
)
|
||
|
||
// ServerManager 使用结构体封装服务器状态,避免全局变量
|
||
type ServerManager struct {
|
||
mu sync.RWMutex
|
||
server *service.HTTPServer
|
||
cfg _type.Config
|
||
isRunning bool
|
||
configPath string
|
||
configLoaded bool
|
||
tokenService *tokenConsumerUtil.RedisTokenConsumerService
|
||
redisClient *redis.Client
|
||
tokenInitOnce sync.Once
|
||
configLoadOnce sync.Once // 新增:专门用于配置加载
|
||
configLoadErr error
|
||
}
|
||
|
||
// ConsoleCommand 定义控制台命令结构
|
||
type ConsoleCommand struct {
|
||
Action string `json:"action"`
|
||
Data map[string]interface{} `json:"data"`
|
||
Result chan ConsoleResult `json:"-"`
|
||
}
|
||
|
||
// ConsoleResult 定义控制台命令结果
|
||
type ConsoleResult struct {
|
||
Success bool `json:"success"`
|
||
Message string `json:"message"`
|
||
Data []byte `json:"data,omitempty"`
|
||
}
|
||
|
||
var (
|
||
serverManager *ServerManager
|
||
once sync.Once
|
||
consoleChan chan ConsoleCommand
|
||
consoleMode bool // 标记是否处于控制台模式
|
||
)
|
||
|
||
// 初始化ServerManager单例
|
||
func getServerManager() *ServerManager {
|
||
once.Do(func() {
|
||
serverManager = &ServerManager{}
|
||
consoleChan = make(chan ConsoleCommand, 10)
|
||
})
|
||
return serverManager
|
||
}
|
||
|
||
//export FreeCString
|
||
func FreeCString(str *C.char) {
|
||
if str != nil {
|
||
C.free(unsafe.Pointer(str))
|
||
}
|
||
}
|
||
|
||
//export StartServer
|
||
func StartServer(configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
manager.mu.Lock()
|
||
defer manager.mu.Unlock()
|
||
|
||
if manager.isRunning {
|
||
return C.CString("Server is already running")
|
||
}
|
||
|
||
// 设置配置文件路径
|
||
if configFile != nil {
|
||
manager.configPath = C.GoString(configFile)
|
||
} else {
|
||
manager.configPath = "config.ini"
|
||
}
|
||
|
||
// 读取配置文件
|
||
if err := manager.readConfigFile(configFile); err != nil {
|
||
return C.CString("Error reading config: " + err.Error())
|
||
}
|
||
|
||
// 启动HTTP服务
|
||
router := route.RegisterRoutes(&manager.cfg)
|
||
manager.server = service.NewServer(manager.cfg.Http.Addr, router)
|
||
|
||
// 使用可取消的上下文
|
||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||
defer cancel()
|
||
|
||
// 启动服务器
|
||
started := make(chan error, 1)
|
||
|
||
go func() {
|
||
log.Println("HTTP服务启动中...")
|
||
started <- manager.server.Start(ctx)
|
||
}()
|
||
|
||
// 等待服务器启动或超时
|
||
select {
|
||
case err := <-started:
|
||
if err != nil {
|
||
return C.CString("Error starting service: " + err.Error())
|
||
}
|
||
manager.isRunning = true
|
||
|
||
return C.CString("Server started successfully on " + manager.cfg.Http.Addr)
|
||
case <-ctx.Done():
|
||
return C.CString("Server start timeout")
|
||
}
|
||
}
|
||
|
||
//export StopServer
|
||
func StopServer() *C.char {
|
||
manager := getServerManager()
|
||
manager.mu.Lock()
|
||
defer manager.mu.Unlock()
|
||
|
||
if !manager.isRunning {
|
||
return C.CString("Server is not running")
|
||
}
|
||
|
||
if manager.server != nil {
|
||
if err := manager.server.Stop(); err != nil {
|
||
return C.CString("Error stopping service: " + err.Error())
|
||
}
|
||
manager.server = nil
|
||
}
|
||
|
||
manager.isRunning = false
|
||
return C.CString("Server stopped successfully")
|
||
}
|
||
|
||
//export GetServerStatus
|
||
func GetServerStatus() *C.char {
|
||
manager := getServerManager()
|
||
manager.mu.RLock()
|
||
defer manager.mu.RUnlock()
|
||
|
||
if manager.isRunning {
|
||
return C.CString("Running")
|
||
}
|
||
return C.CString("Stopped")
|
||
}
|
||
|
||
//export GetServerAddress
|
||
func GetServerAddress() *C.char {
|
||
manager := getServerManager()
|
||
manager.mu.RLock()
|
||
defer manager.mu.RUnlock()
|
||
|
||
if manager.isRunning && manager.server != nil {
|
||
return C.CString(manager.cfg.Http.Addr)
|
||
}
|
||
return C.CString("")
|
||
}
|
||
|
||
//export ReloadConfig
|
||
func ReloadConfig(configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
manager.mu.Lock()
|
||
defer manager.mu.Unlock()
|
||
|
||
if configFile != nil {
|
||
manager.configPath = C.GoString(configFile)
|
||
}
|
||
|
||
if err := manager.readConfigFile(configFile); err != nil {
|
||
return C.CString("Error reloading config: " + err.Error())
|
||
}
|
||
|
||
return C.CString("Config reloaded successfully")
|
||
}
|
||
|
||
//export ExecuteGoodsCreat
|
||
func ExecuteGoodsCreat(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
// 添加调试输出
|
||
jsonStr := C.GoString(bodyJson)
|
||
|
||
return manager.executeGoodsCreatInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGoodsCreatNew
|
||
func ExecuteGoodsCreatNew(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
// 添加调试输出
|
||
jsonStr := C.GoString(bodyJson)
|
||
|
||
return manager.executeGoodsCreatInternalNew(jsonStr)
|
||
}
|
||
|
||
//export ExecuteOtherTypeGoods
|
||
func ExecuteOtherTypeGoods(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
// 添加调试输出
|
||
jsonStr := C.GoString(bodyJson)
|
||
|
||
return manager.executeOtherTypeGoodsInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGoodsPublish
|
||
func ExecuteGoodsPublish(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGoodsPublishInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGoodsDownShelf
|
||
func ExecuteGoodsDownShelf(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGoodsDownShelfInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGoodsFlash
|
||
func ExecuteGoodsFlash(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGoodsFlashInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGoodsEditPrice
|
||
func ExecuteGoodsEditPrice(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGoodsEditPriceInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGoodsEditStock
|
||
func ExecuteGoodsEditStock(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGoodsEditStockInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteSelectGoodsListPrice
|
||
func ExecuteSelectGoodsListPrice(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
res := manager.executeSelectGoodsListInternal(jsonStr)
|
||
|
||
return res
|
||
}
|
||
|
||
//export ExecuteSelectShopListPrice
|
||
func ExecuteSelectShopListPrice(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeSelectShopListInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteOpenExpressCompanies
|
||
func ExecuteOpenExpressCompanies(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeOpenExpressCompanies(jsonStr)
|
||
}
|
||
|
||
//export ExecuteOpenOrderShip
|
||
func ExecuteOpenOrderShip(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeOpenOrderShip(jsonStr)
|
||
}
|
||
|
||
//export ExecuteXyOrderSynchronization
|
||
func ExecuteXyOrderSynchronization(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeXyOrderSynchronization(jsonStr)
|
||
}
|
||
|
||
//export ExecuteGetGoodsDetail
|
||
func ExecuteGetGoodsDetail(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGetGoosDetailInternal(jsonStr)
|
||
}
|
||
|
||
//export ExecuteCountOuterId
|
||
func ExecuteCountOuterId(bodyJson *C.char, configFile *C.char) *C.char {
|
||
manager := getServerManager()
|
||
|
||
if err := manager.ensureConfigLoaded(configFile); err != nil {
|
||
return C.CString("加载配置时出错: " + err.Error())
|
||
}
|
||
|
||
jsonStr := C.GoString(bodyJson)
|
||
return manager.executeGetOuterIdInternal(jsonStr)
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsCreatInternal(jsonStr string) *C.char {
|
||
var memStatsStart, memStatsEnd runtime.MemStats
|
||
runtime.ReadMemStats(&memStatsStart)
|
||
start := time.Now()
|
||
|
||
defer func() {
|
||
runtime.ReadMemStats(&memStatsEnd)
|
||
duration := time.Since(start)
|
||
alloc := memStatsEnd.TotalAlloc - memStatsStart.TotalAlloc
|
||
numGC := memStatsEnd.NumGC - memStatsStart.NumGC
|
||
|
||
log.Printf("ExecuteGoodsCreat - Duration: %v, Alloc: %d bytes, GC: %d times",
|
||
duration, alloc, numGC)
|
||
}()
|
||
|
||
// 清理输入字符串(计时)
|
||
t0 := time.Now()
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
log.Printf("cleanInputString elapsed=%v", time.Since(t0))
|
||
|
||
// 解析JSON(计时)
|
||
t1 := time.Now()
|
||
var body _type.Body
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
log.Printf("json.Unmarshal failed: %v (elapsed=%v)", err, time.Since(t1))
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
log.Printf("json.Unmarshal elapsed=%v", time.Since(t1))
|
||
|
||
// 创建商品控制器(计时)
|
||
t2 := time.Now()
|
||
goodsController := &controller.GoodsController{
|
||
ExcelPath: sm.cfg.File.ExcelPath,
|
||
TxtPath: sm.cfg.File.TxtPath,
|
||
SheetName: sm.cfg.File.SheetName,
|
||
}
|
||
log.Printf("create GoodsController elapsed=%v", time.Since(t2))
|
||
|
||
// 执行商品创建(计时)
|
||
t3 := time.Now()
|
||
createResponse, err := goodsController.GoodsCreatController(
|
||
body,
|
||
sm.cfg.BatchCreatRequest.Path,
|
||
sm.cfg.App.Domain,
|
||
false,
|
||
)
|
||
log.Printf("GoodsCreatController elapsed=%v", time.Since(t3))
|
||
|
||
if err != nil {
|
||
if createResponse == nil || len(createResponse) == 0 {
|
||
return C.CString("")
|
||
}
|
||
log.Printf("alloc C.CString for error response elapsed=%v", time.Since(start))
|
||
return C.CString(string(createResponse))
|
||
}
|
||
|
||
// 返回成功结果
|
||
if createResponse == nil || len(createResponse) == 0 {
|
||
return C.CString("")
|
||
}
|
||
log.Printf("alloc C.CString for success response elapsed=%v", time.Since(start))
|
||
return C.CString(string(createResponse))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsCreatInternalNew(jsonStr string) *C.char {
|
||
var memStatsStart, memStatsEnd runtime.MemStats
|
||
runtime.ReadMemStats(&memStatsStart)
|
||
start := time.Now()
|
||
|
||
defer func() {
|
||
runtime.ReadMemStats(&memStatsEnd)
|
||
duration := time.Since(start)
|
||
alloc := memStatsEnd.TotalAlloc - memStatsStart.TotalAlloc
|
||
numGC := memStatsEnd.NumGC - memStatsStart.NumGC
|
||
|
||
log.Printf("ExecuteGoodsCreat - Duration: %v, Alloc: %d bytes, GC: %d times",
|
||
duration, alloc, numGC)
|
||
}()
|
||
|
||
// 清理输入字符串(计时)
|
||
t0 := time.Now()
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
log.Printf("cleanInputString elapsed=%v", time.Since(t0))
|
||
|
||
// 解析JSON(计时)
|
||
t1 := time.Now()
|
||
var body _type.BodyNew
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
log.Printf("json.Unmarshal failed: %v (elapsed=%v)", err, time.Since(t1))
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
log.Printf("json.Unmarshal elapsed=%v", time.Since(t1))
|
||
|
||
// 创建商品控制器(计时)
|
||
t2 := time.Now()
|
||
goodsController := &controller.GoodsController{
|
||
ExcelPath: sm.cfg.File.ExcelPath,
|
||
TxtPath: sm.cfg.File.TxtPath,
|
||
SheetName: sm.cfg.File.SheetName,
|
||
}
|
||
log.Printf("create GoodsController elapsed=%v", time.Since(t2))
|
||
|
||
// 执行商品创建(计时)
|
||
t3 := time.Now()
|
||
createResponse, err := goodsController.GoodsCreatControllerNew(
|
||
body,
|
||
sm.cfg.BatchCreatRequest.Path,
|
||
sm.cfg.App.Domain,
|
||
false,
|
||
)
|
||
log.Printf("GoodsCreatController elapsed=%v", time.Since(t3))
|
||
|
||
if err != nil {
|
||
if createResponse == nil || len(createResponse) == 0 {
|
||
return C.CString("")
|
||
}
|
||
log.Printf("alloc C.CString for error response elapsed=%v", time.Since(start))
|
||
return C.CString(string(createResponse))
|
||
}
|
||
|
||
// 返回成功结果
|
||
if createResponse == nil || len(createResponse) == 0 {
|
||
return C.CString("")
|
||
}
|
||
log.Printf("alloc C.CString for success response elapsed=%v", time.Since(start))
|
||
return C.CString(string(createResponse))
|
||
}
|
||
|
||
func (sm *ServerManager) executeOtherTypeGoodsInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
|
||
// 解析JSON
|
||
var body _type.Body
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
// 创建商品控制器
|
||
goodsController := &controller.GoodsController{
|
||
ExcelPath: sm.cfg.File.ExcelPath,
|
||
TxtPath: sm.cfg.File.TxtPath,
|
||
SheetName: sm.cfg.File.SheetName,
|
||
}
|
||
|
||
// 执行商品创建
|
||
createResponse, err := goodsController.GoodsCreatController(
|
||
body,
|
||
sm.cfg.BatchCreatRequest.Path,
|
||
sm.cfg.App.Domain,
|
||
true,
|
||
)
|
||
|
||
if err != nil {
|
||
if createResponse == nil || len(createResponse) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(createResponse))
|
||
}
|
||
|
||
// 返回成功结果
|
||
if createResponse == nil || len(createResponse) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(createResponse))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsPublishInternal(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.ListedProducts
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========PublishBody: %v", body)
|
||
|
||
response, err := controller.Publish(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsDownShelfInternal(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
time.Sleep(100 * time.Millisecond)
|
||
// 解析JSON
|
||
var body _type.DownAndFlash
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========DownShelfBody: %v", body)
|
||
response, err := controller.DownShelf(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsFlashInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.DownAndFlash
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========FlashBody: %v", body)
|
||
response, err := controller.Flash(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsEditPriceInternal(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.EditPrices
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========EditPriceBody: %v", body)
|
||
response, err := controller.EditPrices(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeSelectShopListInternal(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.GetShopList
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========EditStockBody: %v", body)
|
||
response, err := controller.GetShopList(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeOpenExpressCompanies(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.GetShopList
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========EditStockBody: %v", body)
|
||
response, err := controller.ExpressCompanies(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeOpenOrderShip(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.GetOrderShip
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========EditStockBody: %v", body)
|
||
response, err := controller.OrderShip(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeXyOrderSynchronization(jsonStr string) *C.char {
|
||
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.GetOrderShip
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========EditStockBody: %v", body)
|
||
response, err := controller.XyOrderSynchronization(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeSelectGoodsListInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
|
||
// 先检查JSON中是否有online_time字段
|
||
var tempMap map[string]interface{}
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &tempMap); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
var response []byte
|
||
var err error
|
||
|
||
if onlineTime, exists := tempMap["online_time"]; exists && onlineTime != nil {
|
||
var bodyWithTime _type.SelectGoodsListWithTime
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &bodyWithTime); err != nil {
|
||
return C.CString("Error: Invalid JSON format for WithTime - " + err.Error())
|
||
}
|
||
fmt.Printf("===========SelectGoodsListWithTime: %v", bodyWithTime)
|
||
|
||
response, err = controller.SelectGoodsListWithTime(bodyWithTime)
|
||
} else {
|
||
var bodyWithoutTime _type.SelectGoodsListWithoutTime
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &bodyWithoutTime); err != nil {
|
||
return C.CString("Error: Invalid JSON format for WithoutTime - " + err.Error())
|
||
}
|
||
fmt.Printf("===========SelectGoodsListWithoutTime: %v", bodyWithoutTime)
|
||
response, err = controller.SelectGoodsListWithoutTime(bodyWithoutTime)
|
||
}
|
||
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGoodsEditStockInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.EditStock
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
fmt.Printf("===========SelectShopListBody: %v", body)
|
||
response, err := controller.EditStock(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGetGoosDetailInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
// 解析JSON
|
||
var body _type.GetGoosDetail
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &body); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
fmt.Printf("===========GetGoodsDetailBody: %v", body)
|
||
response, err := controller.GetGoosDetail(body)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGetShopDetailInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
|
||
// 先检查JSON中是否有online_time字段
|
||
var tempMap map[string]interface{}
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &tempMap); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
var response []byte
|
||
var err error
|
||
|
||
if onlineTime, exists := tempMap["online_time"]; exists && onlineTime != nil {
|
||
var bodyWithTime _type.SelectGoodsListWithTime
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &bodyWithTime); err != nil {
|
||
return C.CString("Error: Invalid JSON format for WithTime - " + err.Error())
|
||
}
|
||
fmt.Printf("===========SelectGoodsListWithTime: %v", bodyWithTime)
|
||
|
||
response, err = controller.SelectGoodsListWithTime(bodyWithTime)
|
||
} else {
|
||
var bodyWithoutTime _type.SelectGoodsListWithoutTime
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &bodyWithoutTime); err != nil {
|
||
return C.CString("Error: Invalid JSON format for WithoutTime - " + err.Error())
|
||
}
|
||
fmt.Printf("===========SelectGoodsListWithoutTime: %v", bodyWithoutTime)
|
||
response, err = controller.SelectGoodsListWithoutTime(bodyWithoutTime)
|
||
}
|
||
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
|
||
// 添加统计逻辑
|
||
responseWithStats, err := addOuterIDStatsToResponse(response)
|
||
if err != nil {
|
||
// 如果统计失败,仍然返回原始数据
|
||
fmt.Printf("===========统计outer_id失败: %v\n", err)
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
return C.CString(string(responseWithStats))
|
||
}
|
||
|
||
func (sm *ServerManager) executeGetOuterIdInternal(jsonStr string) *C.char {
|
||
// 清理输入字符串
|
||
cleanedJSON := cleanInputString(jsonStr)
|
||
|
||
// 先检查JSON中是否有online_time字段
|
||
var tempMap map[string]interface{}
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &tempMap); err != nil {
|
||
return C.CString("Error: Invalid JSON format - " + err.Error())
|
||
}
|
||
|
||
var response []byte
|
||
var err error
|
||
|
||
// 我们先调用一次拿到分页信息(count,page_size),然后根据 count 和 page_size 计算总页数,循环获取所有页并合并 list 来做整体统计
|
||
var initialPageNo int32 = 1
|
||
var pageSize int32 = 100
|
||
var combinedList []map[string]interface{}
|
||
|
||
if onlineTime, exists := tempMap["online_time"]; exists && onlineTime != nil {
|
||
var bodyWithTime _type.SelectGoodsListWithTime
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &bodyWithTime); err != nil {
|
||
return C.CString("Error: Invalid JSON format for WithTime - " + err.Error())
|
||
}
|
||
fmt.Printf("===========SelectGoodsListWithTime: %v", bodyWithTime)
|
||
|
||
initialPageNo = bodyWithTime.PageNo
|
||
if bodyWithTime.PageSize > 0 {
|
||
pageSize = bodyWithTime.PageSize
|
||
}
|
||
|
||
// 第一次请求
|
||
response, err = controller.SelectGoodsListWithTime(bodyWithTime)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
// 解析第一次响应以获取 count 和 list
|
||
var resp struct {
|
||
Code int `json:"code"`
|
||
Msg string `json:"msg"`
|
||
Data struct {
|
||
Count int `json:"count"`
|
||
List []map[string]interface{} `json:"list"`
|
||
PageNo int `json:"page_no"`
|
||
PageSize int `json:"page_size"`
|
||
} `json:"data"`
|
||
}
|
||
if err := json.Unmarshal(response, &resp); err != nil {
|
||
// 无法解析则直接返回原始响应
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
combinedList = append(combinedList, resp.Data.List...)
|
||
|
||
totalCount := resp.Data.Count
|
||
if resp.Data.PageSize > 0 {
|
||
pageSize = int32(resp.Data.PageSize)
|
||
}
|
||
|
||
// 计算总页数
|
||
totalPages := 1
|
||
if pageSize > 0 {
|
||
totalPages = (totalCount + int(pageSize) - 1) / int(pageSize)
|
||
}
|
||
|
||
// 逐页拉取其余页(跳过已取得的 initialPageNo)
|
||
for p := 1; p <= totalPages; p++ {
|
||
if int32(p) == initialPageNo {
|
||
continue
|
||
}
|
||
bodyWithTime.PageNo = int32(p)
|
||
pageResp, pageErr := controller.SelectGoodsListWithTime(bodyWithTime)
|
||
if pageErr != nil {
|
||
// 记录并继续(使用已有数据)
|
||
fmt.Printf("Warning: 获取第 %d 页失败: %v\n", p, pageErr)
|
||
continue
|
||
}
|
||
var pageParsed struct {
|
||
Data struct {
|
||
List []map[string]interface{} `json:"list"`
|
||
} `json:"data"`
|
||
}
|
||
if perr := json.Unmarshal(pageResp, &pageParsed); perr != nil {
|
||
fmt.Printf("Warning: 解析第 %d 页响应失败: %v\n", p, perr)
|
||
continue
|
||
}
|
||
combinedList = append(combinedList, pageParsed.Data.List...)
|
||
}
|
||
|
||
// 将 combinedList 按要求注入到最终响应中并返回(在原始 response 的 data 中添加 outer_id_stats)
|
||
finalRespMap := make(map[string]interface{})
|
||
if err := json.Unmarshal(response, &finalRespMap); err != nil {
|
||
ptr := C.CBytes(response)
|
||
return (*C.char)(ptr)
|
||
}
|
||
// 计算统计
|
||
stats := make(map[string]interface{})
|
||
outerCount := make(map[string]int)
|
||
for _, item := range combinedList {
|
||
if v, ok := item["outer_id"].(string); ok {
|
||
if v == "" {
|
||
outerCount["__empty__"]++
|
||
} else {
|
||
outerCount[v]++
|
||
}
|
||
}
|
||
}
|
||
stats["total_count"] = len(combinedList)
|
||
stats["distribution"] = outerCount
|
||
|
||
// 注入到 data
|
||
if dataMap, ok := finalRespMap["data"].(map[string]interface{}); ok {
|
||
dataMap["outer_id_stats"] = stats
|
||
}
|
||
|
||
bts, merr := json.Marshal(finalRespMap)
|
||
if merr != nil {
|
||
return C.CString(string(response))
|
||
}
|
||
return C.CString(string(bts))
|
||
|
||
} else {
|
||
var bodyWithoutTime _type.SelectGoodsListWithoutTime
|
||
if err := json.Unmarshal([]byte(cleanedJSON), &bodyWithoutTime); err != nil {
|
||
return C.CString("Error: Invalid JSON format for WithoutTime - " + err.Error())
|
||
}
|
||
fmt.Printf("===========SelectGoodsListWithoutTime: %v", bodyWithoutTime)
|
||
|
||
initialPageNo = bodyWithoutTime.PageNo
|
||
if bodyWithoutTime.PageSize > 0 {
|
||
pageSize = bodyWithoutTime.PageSize
|
||
}
|
||
|
||
response, err = controller.SelectGoodsListWithoutTime(bodyWithoutTime)
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
var resp struct {
|
||
Code int `json:"code"`
|
||
Msg string `json:"msg"`
|
||
Data struct {
|
||
Count int `json:"count"`
|
||
List []map[string]interface{} `json:"list"`
|
||
PageNo int `json:"page_no"`
|
||
PageSize int `json:"page_size"`
|
||
} `json:"data"`
|
||
}
|
||
if err := json.Unmarshal(response, &resp); err != nil {
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
combinedList = append(combinedList, resp.Data.List...)
|
||
|
||
totalCount := resp.Data.Count
|
||
if resp.Data.PageSize > 0 {
|
||
pageSize = int32(resp.Data.PageSize)
|
||
}
|
||
|
||
totalPages := 1
|
||
if pageSize > 0 {
|
||
totalPages = (totalCount + int(pageSize) - 1) / int(pageSize)
|
||
}
|
||
|
||
for p := 1; p <= totalPages; p++ {
|
||
if int32(p) == initialPageNo {
|
||
continue
|
||
}
|
||
bodyWithoutTime.PageNo = int32(p)
|
||
pageResp, pageErr := controller.SelectGoodsListWithoutTime(bodyWithoutTime)
|
||
if pageErr != nil {
|
||
fmt.Printf("Warning: 获取第 %d 页失败: %v\n", p, pageErr)
|
||
continue
|
||
}
|
||
var pageParsed struct {
|
||
Data struct {
|
||
List []map[string]interface{} `json:"list"`
|
||
} `json:"data"`
|
||
}
|
||
if perr := json.Unmarshal(pageResp, &pageParsed); perr != nil {
|
||
fmt.Printf("Warning: 解析第 %d 页响应失败: %v\n", p, perr)
|
||
continue
|
||
}
|
||
combinedList = append(combinedList, pageParsed.Data.List...)
|
||
}
|
||
|
||
finalRespMap := make(map[string]interface{})
|
||
if err := json.Unmarshal(response, &finalRespMap); err != nil {
|
||
ptr := C.CBytes(response)
|
||
return (*C.char)(ptr)
|
||
}
|
||
|
||
stats := make(map[string]interface{})
|
||
outerCount := make(map[string]int)
|
||
for _, item := range combinedList {
|
||
if v, ok := item["outer_id"].(string); ok {
|
||
if v == "" {
|
||
outerCount["__empty__"]++
|
||
} else {
|
||
outerCount[v]++
|
||
}
|
||
}
|
||
}
|
||
stats["total_count"] = len(combinedList)
|
||
stats["distribution"] = outerCount
|
||
|
||
if dataMap, ok := finalRespMap["data"].(map[string]interface{}); ok {
|
||
dataMap["outer_id_stats"] = stats
|
||
}
|
||
|
||
bts, merr := json.Marshal(finalRespMap)
|
||
if merr != nil {
|
||
return C.CString(string(response))
|
||
}
|
||
return C.CString(string(bts))
|
||
}
|
||
|
||
if err != nil {
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
ptr := C.CBytes(response)
|
||
return (*C.char)(ptr)
|
||
}
|
||
if response == nil || len(response) == 0 {
|
||
return C.CString("")
|
||
}
|
||
|
||
return C.CString(string(response))
|
||
}
|
||
|
||
func main() {
|
||
}
|
||
|
||
func (sm *ServerManager) readConfigFile(configFile *C.char) error {
|
||
|
||
if configFile == nil {
|
||
return fmt.Errorf("configFile参数为空指针")
|
||
}
|
||
goConfigFile := C.GoString(configFile)
|
||
if !utf8.ValidString(goConfigFile) {
|
||
return fmt.Errorf("invalid UTF-8 encoding in config file path")
|
||
}
|
||
if goConfigFile == "" {
|
||
return fmt.Errorf("configFile参数为空字符串")
|
||
}
|
||
|
||
// 设置硬编码路径或使用默认值
|
||
if sm.configPath == "" {
|
||
sm.configPath = goConfigFile
|
||
log.Printf("使用配置文件路径: %s", sm.configPath)
|
||
} else {
|
||
log.Printf("警告:configPath参数将被忽略,使用Go代码中的硬编码配置路径: %s", sm.configPath)
|
||
}
|
||
|
||
if _, err := os.Stat(sm.configPath); os.IsNotExist(err) {
|
||
exePath, _ := os.Executable()
|
||
exeDir := filepath.Dir(exePath)
|
||
defaultConfig := filepath.Join(exeDir, "config.ini")
|
||
|
||
if _, err := os.Stat(defaultConfig); err == nil {
|
||
sm.configPath = defaultConfig
|
||
} else {
|
||
log.Printf("配置文件不存在: %s", sm.configPath)
|
||
return err
|
||
}
|
||
}
|
||
|
||
if err := iniConfigUtil.LoadConfig(&sm.cfg, sm.configPath); err != nil {
|
||
log.Printf("加载配置失败: %v", err)
|
||
return err
|
||
}
|
||
|
||
fmt.Printf("Config-bathCreat:\n requestPath: %v\n", sm.cfg.BatchCreatRequest.Path)
|
||
fmt.Printf("Config-File:\n txtPath: %v,\n excelPath: %v,\n sheetName: %v\n", sm.cfg.File.TxtPath, sm.cfg.File.ExcelPath, sm.cfg.File.SheetName)
|
||
|
||
return nil
|
||
}
|
||
|
||
func cleanInputString(input string) string {
|
||
// 移除BOM字符
|
||
if len(input) >= 3 && input[0] == 0xEF && input[1] == 0xBB && input[2] == 0xBF {
|
||
input = input[3:]
|
||
}
|
||
|
||
// 标准化换行符
|
||
input = strings.ReplaceAll(input, "\r\n", "\n")
|
||
input = strings.ReplaceAll(input, "\r", "\n")
|
||
|
||
// 移除首尾空白
|
||
return strings.TrimSpace(input)
|
||
}
|
||
|
||
// 统一的配置加载方法
|
||
func (sm *ServerManager) ensureConfigLoaded(configFile *C.char) error {
|
||
sm.configLoadOnce.Do(func() {
|
||
sm.mu.Lock()
|
||
defer sm.mu.Unlock()
|
||
|
||
if configFile != nil {
|
||
sm.configPath = C.GoString(configFile)
|
||
} else if sm.configPath == "" {
|
||
sm.configPath = "config.ini"
|
||
}
|
||
|
||
sm.configLoadErr = sm.readConfigFile(configFile)
|
||
if sm.configLoadErr == nil {
|
||
sm.configLoaded = true
|
||
log.Printf("配置加载完成,AppId: %d", sm.cfg.App.AppId)
|
||
}
|
||
})
|
||
return sm.configLoadErr
|
||
}
|
||
|
||
// 将统计结果添加到响应中的辅助函数
|
||
func addOuterIDStatsToResponse(originalResponse []byte) ([]byte, error) {
|
||
var responseMap map[string]interface{}
|
||
if err := json.Unmarshal(originalResponse, &responseMap); err != nil {
|
||
return nil, fmt.Errorf("解析响应JSON失败: %v", err)
|
||
}
|
||
|
||
// 获取统计结果
|
||
stats := getOuterIDStats(originalResponse)
|
||
|
||
// 将统计结果添加到response的data中
|
||
if data, exists := responseMap["data"].(map[string]interface{}); exists {
|
||
data["outer_id_stats"] = stats
|
||
responseMap["data"] = data
|
||
}
|
||
|
||
return json.Marshal(responseMap)
|
||
}
|
||
|
||
// 获取outer_id统计
|
||
func getOuterIDStats(responseData []byte) map[string]interface{} {
|
||
stats := make(map[string]interface{})
|
||
|
||
var data struct {
|
||
Data struct {
|
||
List []struct {
|
||
OuterID string `json:"outer_id"`
|
||
} `json:"list"`
|
||
} `json:"data"`
|
||
}
|
||
|
||
if err := json.Unmarshal(responseData, &data); err != nil {
|
||
return stats
|
||
}
|
||
|
||
outerIDCount := make(map[string]int)
|
||
totalCount := len(data.Data.List)
|
||
|
||
for _, item := range data.Data.List {
|
||
outerID := item.OuterID
|
||
if outerID == "" {
|
||
outerID = "(空)"
|
||
}
|
||
outerIDCount[outerID]++
|
||
}
|
||
|
||
stats["total_count"] = totalCount
|
||
stats["distribution"] = outerIDCount
|
||
|
||
return stats
|
||
}
|