Files
ai-agent/web/lib/api/ticket.ts
T
mlogclub 62416baabc Refactor API endpoints to use /api/dashboard instead of /api/console
- Updated all relevant API functions in agent.ts, company.ts, customer-contact.ts, customer.ts, dashboard.ts, ticket-config.ts, and ticket.ts to point to the new /api/dashboard paths.
- Ensured that all request methods and payload structures remain unchanged to maintain existing functionality.
2026-04-15 17:12:30 +08:00

488 lines
11 KiB
TypeScript

import { request } from "@/lib/api/client"
import type { Tag } from "@/lib/api/admin"
export type Paging = {
page: number
limit: number
total: number
}
export type PageResult<T> = {
results: T[]
page: Paging
}
export type TicketCustomer = {
id: number
name: string
companyId?: number
company?: {
id: number
name: string
code?: string
remark?: string
createdAt?: string
updatedAt?: string
}
primaryMobile?: string
primaryEmail?: string
}
export type TicketSLA = {
slaType: string
targetMinutes: number
status: string
startedAt?: string
pausedAt?: string
stoppedAt?: string
breachedAt?: string
elapsedMin: number
}
export type TicketComment = {
id: number
ticketId: number
commentType: string
authorType: string
authorId: number
authorName?: string
contentType: string
content: string
payload?: string
createdAt?: string
}
export type TicketEvent = {
id: number
ticketId: number
eventType: string
operatorType: string
operatorId: number
operatorName?: string
oldValue?: string
newValue?: string
content?: string
payload?: string
createdAt?: string
}
export type TicketItem = {
id: number
ticketNo: string
title: string
description: string
source: string
channel: string
customerId: number
conversationId: number
tags?: Tag[]
type: string
priority: number
priorityName?: string
severity: number
status: string
currentTeamId: number
currentTeamName?: string
currentAssigneeId: number
currentAssigneeName?: string
watchedByMe: boolean
pendingReason?: string
closeReason?: string
resolutionCode?: string
resolutionCodeName?: string
resolutionSummary?: string
firstResponseAt?: string
resolvedAt?: string
closedAt?: string
dueAt?: string
nextReplyDeadlineAt?: string
resolveDeadlineAt?: string
reopenedCount: number
createdAt?: string
updatedAt?: string
customer?: TicketCustomer
sla?: TicketSLA[]
}
export type TicketDetail = {
ticket: TicketItem
watchers?: Array<{
id: number
userId: number
userName?: string
}>
collaborators?: TicketCollaborator[]
comments?: TicketComment[]
events?: TicketEvent[]
relatedTickets?: TicketRelation[]
}
export type TicketCollaborator = {
id: number
userId: number
userName?: string
teamName?: string
}
export type TicketRelation = {
id: number
ticketId: number
relatedTicketId: number
relationType: string
relatedTicketNo?: string
relatedTicketTitle?: string
relatedTicketStatus?: string
currentTeamName?: string
currentAssigneeName?: string
updatedAt?: string
}
export type TicketSummary = {
all: number
mine: number
watching: number
collaboration: number
participating: number
mentioned: number
unassigned: number
pendingCustomer: number
pendingInternal: number
overdue: number
}
export type TicketRiskReason = {
code: string
title: string
description: string
count: number
}
export type TicketRiskOverview = {
overdue: number
highRisk: number
unassigned: number
pendingInternal: number
pendingCustomer: number
riskWindowMins: number
reasons?: TicketRiskReason[]
}
export type TicketSavedView = {
id: number
name: string
filters?: Record<string, unknown>
sortNo: number
}
export type TicketListQuery = {
page?: number
limit?: number
keyword?: string
status?: string
priority?: number
severity?: number
tagId?: number
currentTeamId?: number
currentAssigneeId?: number
customerId?: number
conversationId?: number
source?: string
watching?: number
collaboration?: number
collaborating?: number
mentioned?: number
mine?: number
unassigned?: number
overdue?: number
}
export type TicketRiskListQuery = {
riskType: "overdue" | "high_risk" | "unassigned" | "pending_internal" | "pending_customer"
currentTeamId?: number
riskWindowMins?: number
page?: number
limit?: number
}
export type CreateTicketPayload = {
title: string
description: string
source?: string
channel?: string
customerId?: number
conversationId?: number
tagIds?: number[]
type?: string
priority: number
severity: number
currentTeamId?: number
currentAssigneeId?: number
dueAt?: string
customFields?: Record<string, unknown>
}
export type CreateTicketFromConversationPayload = {
conversationId: number
title: string
description: string
tagIds?: number[]
priority: number
severity: number
currentTeamId?: number
currentAssigneeId?: number
syncToConversation: boolean
customFields?: Record<string, unknown>
}
export type UpdateTicketPayload = {
ticketId: number
title: string
description: string
tagIds?: number[]
type?: string
priority: number
severity: number
currentTeamId?: number
currentAssigneeId?: number
dueAt?: string
customFields?: Record<string, unknown>
}
function toQueryString(query?: Record<string, string | number | undefined>) {
if (!query) {
return ""
}
const params = new URLSearchParams()
Object.entries(query).forEach(([key, value]) => {
if (value === undefined || value === "") {
return
}
params.set(key, String(value))
})
const output = params.toString()
return output ? `?${output}` : ""
}
export function fetchTickets(query?: TicketListQuery) {
return request<PageResult<TicketItem>>(`/api/dashboard/ticket/list${toQueryString(query)}`)
}
export function fetchTicketDetail(id: number) {
return request<TicketDetail>(`/api/dashboard/ticket/${id}`)
}
export function fetchTicketSummary() {
return request<TicketSummary>("/api/dashboard/ticket/summary")
}
export function fetchTicketViews() {
return request<TicketSavedView[]>("/api/dashboard/ticket/view_list")
}
export function saveTicketView(payload: {
id?: number
name: string
filters?: Record<string, unknown>
}) {
return request<TicketSavedView>("/api/dashboard/ticket/save_view", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function deleteTicketView(id: number) {
return request<void>("/api/dashboard/ticket/delete_view", {
method: "POST",
body: JSON.stringify({ id }),
})
}
export function fetchTicketRiskOverview(query?: {
currentTeamId?: number
riskWindowMins?: number
}) {
return request<TicketRiskOverview>(`/api/dashboard/ticket/risk_overview${toQueryString(query)}`)
}
export function fetchTicketRiskList(query: TicketRiskListQuery) {
return request<PageResult<TicketItem>>(`/api/dashboard/ticket/risk_list${toQueryString(query)}`)
}
export function createTicket(payload: CreateTicketPayload) {
return request<TicketItem>("/api/dashboard/ticket/create", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function createTicketFromConversation(payload: CreateTicketFromConversationPayload) {
return request<TicketItem>("/api/dashboard/ticket/create_from_conversation", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function updateTicket(payload: UpdateTicketPayload) {
return request<void>("/api/dashboard/ticket/update", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function linkTicketToCustomer(payload: {
ticketId: number
customerId: number
}) {
return request<void>("/api/dashboard/ticket/link_customer", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function assignTicket(payload: {
ticketId: number
toUserId: number
toTeamId?: number
reason?: string
}) {
return request<void>("/api/dashboard/ticket/assign", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function batchAssignTickets(payload: {
ticketIds: number[]
toUserId: number
toTeamId?: number
reason?: string
}) {
return request<void>("/api/dashboard/ticket/batch_assign", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function changeTicketStatus(payload: {
ticketId: number
status: string
pendingReason?: string
closeReason?: string
resolutionCode?: string
resolutionSummary?: string
reason?: string
}) {
return request<void>("/api/dashboard/ticket/change_status", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function batchChangeTicketStatus(payload: {
ticketIds: number[]
status: string
pendingReason?: string
closeReason?: string
resolutionCode?: string
resolutionSummary?: string
reason?: string
}) {
return request<void>("/api/dashboard/ticket/batch_change_status", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function replyTicket(payload: {
ticketId: number
contentType?: string
content: string
payload?: string
}) {
return request<TicketComment>("/api/dashboard/ticket/reply", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function addTicketInternalNote(payload: {
ticketId: number
contentType?: string
content: string
payload?: string
}) {
return request<TicketComment>("/api/dashboard/ticket/internal_note", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function closeTicket(payload: { ticketId: number; closeReason: string }) {
return request<void>("/api/dashboard/ticket/close", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function reopenTicket(payload: { ticketId: number; reason: string }) {
return request<void>("/api/dashboard/ticket/reopen", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function watchTicket(ticketId: number) {
return request<void>("/api/dashboard/ticket/watch", {
method: "POST",
body: JSON.stringify({ ticketId }),
})
}
export function unwatchTicket(ticketId: number) {
return request<void>("/api/dashboard/ticket/unwatch", {
method: "POST",
body: JSON.stringify({ ticketId }),
})
}
export function batchWatchTickets(payload: { ticketIds: number[]; watched: boolean }) {
return request<void>("/api/dashboard/ticket/batch_watch", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function addTicketRelation(payload: {
ticketId: number
relatedTicketId?: number
relatedTicketNo?: string
relationType: string
}) {
return request<void>("/api/dashboard/ticket/add_relation", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function deleteTicketRelation(payload: { ticketId: number; relationId: number }) {
return request<void>("/api/dashboard/ticket/delete_relation", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function addTicketCollaborator(payload: { ticketId: number; userId: number }) {
return request<void>("/api/dashboard/ticket/add_collaborator", {
method: "POST",
body: JSON.stringify(payload),
})
}
export function deleteTicketCollaborator(payload: { ticketId: number; collaboratorId: number }) {
return request<void>("/api/dashboard/ticket/delete_collaborator", {
method: "POST",
body: JSON.stringify(payload),
})
}