feat: 顺运宝支持指定日期同步 (#53)
This commit is contained in:
+56
-12
@@ -86,7 +86,17 @@ func (h *Handler) renderSybListWithLoginReason(c *gin.Context, keyword, pageRaw,
|
||||
// 现在「打开页面」纯粹是看数据,不触发任何对外部系统的动作;
|
||||
// 真正会登录的只有「同步」这一个按钮。这与 Client 侧
|
||||
// 「『获取任务』是唯一会产生外部后果的命令」是同一条原则。
|
||||
needLogin := loginReason != ""
|
||||
needLogin := c.Query("login") == "1"
|
||||
today := service.SybToday(time.Now())
|
||||
dateFrom := c.Query("date_from")
|
||||
dateTo := c.Query("date_to")
|
||||
hasSyncRange := dateFrom != "" || dateTo != ""
|
||||
if dateFrom == "" {
|
||||
dateFrom = today
|
||||
}
|
||||
if dateTo == "" {
|
||||
dateTo = today
|
||||
}
|
||||
|
||||
cfg, cfgErr := config.Load()
|
||||
switch {
|
||||
@@ -119,6 +129,12 @@ func (h *Handler) renderSybListWithLoginReason(c *gin.Context, keyword, pageRaw,
|
||||
"LoginHint": loginHint,
|
||||
"Username": username,
|
||||
"ConfigProblem": configProblem,
|
||||
"Today": today,
|
||||
"SyncDateFrom": dateFrom,
|
||||
"SyncDateTo": dateTo,
|
||||
"HasSyncRange": hasSyncRange,
|
||||
"NeedRangeSync": c.Query("range_sync") == "1",
|
||||
"RangeError": c.Query("range_error"),
|
||||
"Pagination": service.NewPaginationView(result.Page, result.TotalPages, values.Encode()),
|
||||
}))
|
||||
}
|
||||
@@ -142,6 +158,12 @@ func sybStatusLine(result *service.SybListResult) string {
|
||||
// │ └→ 识别失败/OCR 不可达 ──┐
|
||||
// └→ OCR 未配置(留空)────────────────────┴→ 跳回列表页,弹手工登录框
|
||||
func (h *Handler) SybSync(c *gin.Context) {
|
||||
options, err := service.NewSybSyncOptions(c.PostForm("date_from"), c.PostForm("date_to"), time.Now())
|
||||
if err != nil {
|
||||
h.sybRedirectRange(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
fail(c, http.StatusBadRequest, err.Error())
|
||||
@@ -166,7 +188,7 @@ func (h *Handler) SybSync(c *gin.Context) {
|
||||
h.sybRedirectLogin(c, reason)
|
||||
return
|
||||
}
|
||||
if !h.startSybSync(client, *cfg) {
|
||||
if !h.startSybSync(client, *cfg, options) {
|
||||
h.sybRedirect(c, "验证码自动识别成功,已自动登录;但已经有一个同步任务在跑,请稍后刷新页面查看结果")
|
||||
return
|
||||
}
|
||||
@@ -174,7 +196,7 @@ func (h *Handler) SybSync(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if !h.startSybSync(client, *cfg) {
|
||||
if !h.startSybSync(client, *cfg, options) {
|
||||
h.sybRedirect(c, "已经有一个同步任务在跑,请稍后刷新页面查看结果,不要重复点击")
|
||||
return
|
||||
}
|
||||
@@ -244,6 +266,12 @@ func (h *Handler) SybCaptcha(c *gin.Context) {
|
||||
// `[必须]` 密码从 config.yaml 读,不接受表单传入、不回显、不进日志——
|
||||
// 界面上只有验证码是操作员手输的,见工单 #46。
|
||||
func (h *Handler) SybLoginAndSync(c *gin.Context) {
|
||||
options, optionErr := service.NewSybSyncOptions(c.PostForm("date_from"), c.PostForm("date_to"), time.Now())
|
||||
if optionErr != nil {
|
||||
h.sybRedirectRange(c, optionErr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
fail(c, http.StatusBadRequest, err.Error())
|
||||
@@ -275,7 +303,7 @@ func (h *Handler) SybLoginAndSync(c *gin.Context) {
|
||||
log.Printf("syb_session_save_failed username=%s err=%v", result.User.Username, err)
|
||||
}
|
||||
|
||||
if !h.startSybSync(client, *cfg) {
|
||||
if !h.startSybSync(client, *cfg, options) {
|
||||
h.sybRedirect(c, "登录成功,但已经有一个同步任务在跑,请稍后刷新页面查看结果")
|
||||
return
|
||||
}
|
||||
@@ -290,13 +318,13 @@ func (h *Handler) SybLoginAndSync(c *gin.Context) {
|
||||
//
|
||||
// `[必须]` 后台协程用 context.Background(),不能用 c.Request.Context()——
|
||||
// 那个请求上下文会在这次 HTTP 请求返回后就被取消,同步跑到一半会被打断。
|
||||
func (h *Handler) startSybSync(client *syb.Client, cfg config.Config) bool {
|
||||
func (h *Handler) startSybSync(client *syb.Client, cfg config.Config, options service.SybSyncOptions) bool {
|
||||
if !service.TryStartSybSync() {
|
||||
return false
|
||||
}
|
||||
db := h.db
|
||||
go func() {
|
||||
report := service.RunSybSync(context.Background(), db, client, cfg.Syb, time.Now())
|
||||
report := service.RunSybSyncWithOptions(context.Background(), db, client, cfg.Syb, time.Now(), options)
|
||||
service.FinishSybSync(report)
|
||||
}()
|
||||
return true
|
||||
@@ -306,9 +334,7 @@ func (h *Handler) startSybSync(client *syb.Client, cfg config.Config) bool {
|
||||
// 用 303 跳转是为了让浏览器地址栏变成 GET /syb,按 F5 不会重复提交。
|
||||
func (h *Handler) sybRedirect(c *gin.Context, msg string) {
|
||||
params := url.Values{}
|
||||
if q := c.PostForm("order_no"); q != "" {
|
||||
params.Set("order_no", q)
|
||||
}
|
||||
appendSybFormState(params, c)
|
||||
if msg != "" {
|
||||
params.Set("msg", msg)
|
||||
}
|
||||
@@ -325,9 +351,8 @@ func (h *Handler) sybRedirect(c *gin.Context, msg string) {
|
||||
// (比如 ocr_url 留空,压根没尝试过自动识别)弹窗不显示任何原因说明。
|
||||
func (h *Handler) sybRedirectLogin(c *gin.Context, reason string) {
|
||||
params := url.Values{}
|
||||
if q := c.PostForm("order_no"); q != "" {
|
||||
params.Set("order_no", q)
|
||||
}
|
||||
appendSybFormState(params, c)
|
||||
params.Set("login", "1")
|
||||
if reason != "" {
|
||||
params.Set("login_reason", reason)
|
||||
}
|
||||
@@ -338,6 +363,25 @@ func (h *Handler) sybRedirectLogin(c *gin.Context, reason string) {
|
||||
c.Redirect(http.StatusSeeOther, target)
|
||||
}
|
||||
|
||||
// sybRedirectRange 把服务端日期校验错误带回指定日期弹窗。输入值一并保留,
|
||||
// 操作员只需改错的那一端,不必重新填整张表单。
|
||||
func (h *Handler) sybRedirectRange(c *gin.Context, message string) {
|
||||
params := url.Values{}
|
||||
appendSybFormState(params, c)
|
||||
params.Set("range_sync", "1")
|
||||
params.Set("range_error", message)
|
||||
c.Redirect(http.StatusSeeOther, "/syb?"+params.Encode())
|
||||
}
|
||||
|
||||
// appendSybFormState 保存同步/登录跳转后仍需要的页面状态。
|
||||
func appendSybFormState(params url.Values, c *gin.Context) {
|
||||
for _, name := range []string{"order_no", "date_from", "date_to"} {
|
||||
if value := strings.TrimSpace(c.PostForm(name)); value != "" {
|
||||
params.Set(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SybMatch 保存规格匹配结果。
|
||||
//
|
||||
// 关键:保存的是**可复用的 SKU 映射**(写 sku_mappings),
|
||||
|
||||
Reference in New Issue
Block a user