feat: 建立顺运宝采购处理状态 (#67)
This commit is contained in:
@@ -54,7 +54,8 @@ func sybLoginHint(ocrURL string) string {
|
||||
// 是配置错了还是服务挂了,不能弹一个空的手工输入框了事。
|
||||
func (h *Handler) renderSybListWithLoginReason(c *gin.Context, keyword, pageRaw, msg, loginReason string) {
|
||||
pageNum := service.ParsePage(pageRaw)
|
||||
result, err := service.ListSybOrdersView(h.db, keyword, pageNum)
|
||||
stage := service.ParseSybStage(c.Query("stage"))
|
||||
result, err := service.ListSybOrdersView(h.db, keyword, stage, pageNum)
|
||||
if err != nil {
|
||||
fail(c, http.StatusInternalServerError,
|
||||
"读取顺运宝货运单列表失败,数据没有被改动。刷新页面重试;一直失败请把这句话报给维护者。")
|
||||
@@ -80,6 +81,17 @@ func (h *Handler) renderSybListWithLoginReason(c *gin.Context, keyword, pageRaw,
|
||||
if keyword != "" {
|
||||
values.Set("order_no", keyword)
|
||||
}
|
||||
if stage != "" {
|
||||
values.Set("stage", stage)
|
||||
}
|
||||
detailValues := url.Values{}
|
||||
if keyword != "" {
|
||||
detailValues.Set("order_no", keyword)
|
||||
}
|
||||
if stage != "" {
|
||||
detailValues.Set("stage", stage)
|
||||
}
|
||||
detailValues.Set("page", strconv.Itoa(result.Page))
|
||||
|
||||
// `[必须]` 密码不读出来显示、也不回显到 HTML,见工单 #46。
|
||||
// 这里只取 username(只读展示)和 base_url 是否配置正确。
|
||||
@@ -139,6 +151,9 @@ func (h *Handler) renderSybListWithLoginReason(c *gin.Context, keyword, pageRaw,
|
||||
|
||||
c.HTML(http.StatusOK, "syb/list", page(c, "syb", "顺运宝数据", gin.H{
|
||||
"Keyword": keyword,
|
||||
"StageFilter": stage,
|
||||
"StageOptions": service.SybStageOptions(),
|
||||
"CurrentPage": result.Page,
|
||||
"Rows": result.Rows,
|
||||
"Status": status,
|
||||
"HasAny": result.HasAny,
|
||||
@@ -163,9 +178,28 @@ func (h *Handler) renderSybListWithLoginReason(c *gin.Context, keyword, pageRaw,
|
||||
"HistoryFetchPagination": sybHistoryPartialPagination(history.Page, history.TotalPages,
|
||||
keyword, dateFrom, dateTo),
|
||||
"Pagination": service.NewPaginationView(result.Page, result.TotalPages, values.Encode()),
|
||||
"DetailURL": "/syb/detail?" + detailValues.Encode(),
|
||||
}))
|
||||
}
|
||||
|
||||
// SybDetail 返回一条货运单明细的采购处理弹窗片段。
|
||||
func (h *Handler) SybDetail(c *gin.Context) {
|
||||
detail, err := service.GetSybProcessingDetail(h.db, c.Query("id"))
|
||||
if err != nil {
|
||||
fail(c, http.StatusInternalServerError, "读取顺运宝处理详情失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
if detail == nil {
|
||||
fail(c, http.StatusNotFound, "顺运宝货运单明细不存在。")
|
||||
return
|
||||
}
|
||||
c.HTML(http.StatusOK, "syb/detail_modal", gin.H{
|
||||
"D": detail, "CSRFToken": csrfToken(c),
|
||||
"Keyword": c.Query("order_no"), "StageFilter": c.Query("stage"),
|
||||
"CurrentPage": service.ParsePage(c.Query("page")),
|
||||
})
|
||||
}
|
||||
|
||||
// SybSyncHistory 只返回同步记录弹窗内部的 HTML。它只读本地数据库,不调用
|
||||
// 顺运宝;完整页面和局部刷新共用同一份模板,避免字段或分页标记漂移。
|
||||
func (h *Handler) SybSyncHistory(c *gin.Context) {
|
||||
@@ -243,6 +277,9 @@ func sybHistoryPartialURL(pageNum int, keyword, dateFrom, dateTo string) string
|
||||
// `[必须]` 显示筛选后的**全量**总数,不是本页行数,见工单 #43 定下的规则。
|
||||
func sybStatusLine(result *service.SybListResult) string {
|
||||
prefix := fmt.Sprintf("共 %d 条货运单明细", result.Total)
|
||||
if label := service.SybStageLabel(result.Stage); label != "" {
|
||||
prefix = fmt.Sprintf("%s:%d 条", label, result.Total)
|
||||
}
|
||||
if !result.HasAny {
|
||||
return "还没有货运单明细。点上方「同步」从顺运宝拉取。"
|
||||
}
|
||||
@@ -510,13 +547,24 @@ func (h *Handler) sybRedirectRange(c *gin.Context, message string) {
|
||||
|
||||
// appendSybFormState 保存同步/登录跳转后仍需要的页面状态。
|
||||
func appendSybFormState(params url.Values, c *gin.Context) {
|
||||
for _, name := range []string{"order_no", "date_from", "date_to"} {
|
||||
for _, name := range []string{"order_no", "stage", "page", "date_from", "date_to"} {
|
||||
if value := strings.TrimSpace(c.PostForm(name)); value != "" {
|
||||
params.Set(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SybSelectSKU 保存采购员确认的蝦皮规格。Service 会再次验证 SKU 归属,
|
||||
// 不能靠表单隐藏字段决定商品关系。
|
||||
func (h *Handler) SybSelectSKU(c *gin.Context) {
|
||||
err := service.AssignSybShopeeSKU(h.db, c.PostForm("syb_id"), c.PostForm("shopee_sku_id"))
|
||||
if err != nil {
|
||||
h.sybRedirect(c, "蝦皮规格未保存:"+err.Error())
|
||||
return
|
||||
}
|
||||
h.sybRedirect(c, "蝦皮规格已确认,下一步按处理状态继续。")
|
||||
}
|
||||
|
||||
// SybMatch 保存规格匹配结果。
|
||||
//
|
||||
// 关键:保存的是**可复用的 SKU 映射**(写 sku_mappings),
|
||||
|
||||
@@ -71,10 +71,12 @@ func Register(r *gin.Engine, db *sql.DB, onlineThreshold time.Duration) {
|
||||
|
||||
// 3. 顺运宝数据
|
||||
pages.GET("/syb", h.SybList)
|
||||
pages.GET("/syb/detail", h.SybDetail) // 采购处理弹窗
|
||||
pages.GET("/syb/sync-history", h.SybSyncHistory) // 弹窗局部刷新,只读本地同步记录
|
||||
pages.GET("/syb/captcha", h.SybCaptcha) // 登录弹窗里的验证码图片
|
||||
pages.POST("/syb/sync", h.SybSync)
|
||||
pages.POST("/syb/login-and-sync", h.SybLoginAndSync)
|
||||
pages.POST("/syb/select-sku", h.SybSelectSKU)
|
||||
pages.POST("/syb/match", h.SybMatch)
|
||||
pages.POST("/syb/create-task", h.SybCreateTask)
|
||||
pages.POST("/syb/delete", h.SybDelete)
|
||||
|
||||
Reference in New Issue
Block a user