328 lines
13 KiB
Go
328 lines
13 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
)
|
|
|
|
func registerAfterSalesRoutes(router *http.ServeMux) {
|
|
router.HandleFunc("/api/after-sales/issues", handleAfterSalesIssues)
|
|
router.HandleFunc("/api/after-sales/issues/save", handleAfterSalesSaveIssue)
|
|
router.HandleFunc("/api/after-sales/issues/resolve", handleAfterSalesResolveIssue)
|
|
router.HandleFunc("/api/after-sales/issues/delete", handleAfterSalesDeleteIssue)
|
|
router.HandleFunc("/api/after-sales/collect", handleAfterSalesCollect)
|
|
router.HandleFunc("/api/after-sales/import-history", handleAfterSalesImportHistory)
|
|
router.HandleFunc("/api/after-sales/status", handleAfterSalesStatus)
|
|
router.HandleFunc("/api/after-sales/auto-collect", handleAfterSalesAutoCollect)
|
|
router.HandleFunc("/api/after-sales/knowledge/cases", handleAfterSalesKnowledgeCases)
|
|
router.HandleFunc("/api/after-sales/knowledge/cases/update", handleAfterSalesKnowledgeCaseUpdate)
|
|
router.HandleFunc("/api/after-sales/knowledge/cases/reveal", handleAfterSalesKnowledgeCaseReveal)
|
|
router.HandleFunc("/api/after-sales/dispatch/config", handleAfterSalesDispatchConfig)
|
|
router.HandleFunc("/api/after-sales/dispatch/queue", handleAfterSalesDispatchQueue)
|
|
router.HandleFunc("/api/after-sales/dispatch/assign", handleAfterSalesDispatchAssign)
|
|
router.HandleFunc("/api/after-sales/dispatch/notify", handleAfterSalesDispatchNotify)
|
|
router.HandleFunc("/api/after-sales/dispatch/batch-notify", handleAfterSalesDispatchBatchNotify)
|
|
}
|
|
|
|
func handleAfterSalesIssues(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{
|
|
"success": true,
|
|
"message": "ok",
|
|
"data": getAfterSalesIssueEngine().snapshotIssues(),
|
|
})
|
|
}
|
|
|
|
func handleAfterSalesStatus(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{
|
|
"success": true,
|
|
"message": "ok",
|
|
"data": getAfterSalesIssueEngine().snapshotStatus(),
|
|
})
|
|
}
|
|
|
|
func handleAfterSalesSaveIssue(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var issue AfterSalesIssue
|
|
if err := json.NewDecoder(r.Body).Decode(&issue); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
if err := getAfterSalesIssueEngine().saveIssue(issue); err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "saved"})
|
|
}
|
|
|
|
func handleAfterSalesResolveIssue(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
IssueID string `json:"issueId"`
|
|
ResolutionContent string `json:"resolutionContent"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
knowledgeCase, err := getAfterSalesIssueEngine().resolveIssue(payload.IssueID, payload.ResolutionContent)
|
|
if err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "已处理并保存到知识库", "data": knowledgeCase})
|
|
}
|
|
|
|
func handleAfterSalesDeleteIssue(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
ID string `json:"id"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
if !getAfterSalesIssueEngine().deleteIssue(payload.ID) {
|
|
sendJSONResponse(w, http.StatusNotFound, map[string]interface{}{"success": false, "message": "问题不存在"})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "deleted"})
|
|
}
|
|
|
|
func handleAfterSalesCollect(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
ConversationID string `json:"conversationId"`
|
|
}
|
|
if r.Body != nil {
|
|
_ = json.NewDecoder(r.Body).Decode(&payload)
|
|
}
|
|
ok, message := getAfterSalesIssueEngine().triggerCollectAsync(payload.ConversationID, true)
|
|
status := http.StatusOK
|
|
if !ok {
|
|
status = http.StatusConflict
|
|
}
|
|
sendJSONResponse(w, status, map[string]interface{}{"success": ok, "message": message})
|
|
}
|
|
|
|
func handleAfterSalesImportHistory(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload AfterSalesHistoryImportRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
result, err := getAfterSalesIssueEngine().importHistoryAndCollectDetailed(payload)
|
|
if err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{
|
|
"success": true,
|
|
"message": afterSalesHistoryImportMessage(result.Imported, result.Segments, result.Added),
|
|
"data": map[string]interface{}{
|
|
"imported": result.Imported,
|
|
"segments": result.Segments,
|
|
"added": result.Added,
|
|
"status": getAfterSalesIssueEngine().snapshotStatus(),
|
|
},
|
|
})
|
|
}
|
|
|
|
func handleAfterSalesAutoCollect(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
if err := getAfterSalesIssueEngine().setAutoCollectEnabled(payload.Enabled); err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{
|
|
"success": true,
|
|
"message": "saved",
|
|
"data": getAfterSalesIssueEngine().snapshotStatus(),
|
|
})
|
|
}
|
|
|
|
func handleAfterSalesKnowledgeCases(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
if err := getAfterSalesIssueEngine().syncResolvedKnowledgeCases(); err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error(), "data": []AfterSalesKnowledgeCase{}})
|
|
return
|
|
}
|
|
cases, err := listAfterSalesKnowledgeCases()
|
|
if err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error(), "data": []AfterSalesKnowledgeCase{}})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "ok", "data": cases})
|
|
}
|
|
|
|
func handleAfterSalesKnowledgeCaseUpdate(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
IssueID string `json:"issueId"`
|
|
ResolutionContent string `json:"resolutionContent"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
knowledgeCase, err := getAfterSalesIssueEngine().resolveIssue(payload.IssueID, payload.ResolutionContent)
|
|
if err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "知识案例已更新", "data": knowledgeCase})
|
|
}
|
|
|
|
func handleAfterSalesKnowledgeCaseReveal(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
IssueID string `json:"issueId"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
ok, message := revealAfterSalesKnowledgeCase(payload.IssueID)
|
|
status := http.StatusOK
|
|
if !ok {
|
|
status = http.StatusBadRequest
|
|
}
|
|
sendJSONResponse(w, status, map[string]interface{}{"success": ok, "message": message})
|
|
}
|
|
|
|
func handleAfterSalesDispatchConfig(w http.ResponseWriter, r *http.Request) {
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
cfg, err := readAfterSalesDispatchConfig()
|
|
if err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "ok", "data": cfg})
|
|
case http.MethodPost:
|
|
var cfg AfterSalesDispatchConfig
|
|
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
if err := saveAfterSalesDispatchConfig(cfg); err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "saved"})
|
|
default:
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
}
|
|
}
|
|
|
|
func handleAfterSalesDispatchQueue(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
queue, err := getAfterSalesIssueEngine().dispatchQueue()
|
|
if err != nil {
|
|
sendJSONResponse(w, http.StatusInternalServerError, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "ok", "data": queue})
|
|
}
|
|
|
|
func handleAfterSalesDispatchAssign(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
IssueID string `json:"issueId"`
|
|
EngineerUserID string `json:"engineerUserId"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
if err := getAfterSalesIssueEngine().assignEngineer(payload.IssueID, payload.EngineerUserID); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
sendJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true, "message": "assigned"})
|
|
}
|
|
|
|
func handleAfterSalesDispatchNotify(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
IssueID string `json:"issueId"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
result := getAfterSalesIssueEngine().notifyEngineer(payload.IssueID)
|
|
status := http.StatusOK
|
|
if !result.Success {
|
|
status = http.StatusBadRequest
|
|
}
|
|
sendJSONResponse(w, status, map[string]interface{}{"success": result.Success, "message": result.Message, "data": result})
|
|
}
|
|
|
|
func handleAfterSalesDispatchBatchNotify(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var payload struct {
|
|
IssueIDs []string `json:"issueIds"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
sendJSONResponse(w, http.StatusBadRequest, map[string]interface{}{"success": false, "message": err.Error()})
|
|
return
|
|
}
|
|
result := getAfterSalesIssueEngine().batchNotifyEngineers(payload.IssueIDs)
|
|
sendJSONResponse(w, http.StatusOK, result)
|
|
}
|