新增独立快捷回复模块(团队/个人)

从知识库拆出快捷回复:支持团队暂存与发布同步、个人话术、输入码与工作台 / 调用,以及 CSV 导入导出;管理页顶栏与侧栏对齐。
This commit is contained in:
yml2213
2026-07-17 21:59:10 +08:00
parent 54d23bb595
commit c5f28dca1c
11 changed files with 1491 additions and 26 deletions
+83
View File
@@ -323,6 +323,89 @@ export const updateKnowledgeEntry = (id: number, data: Partial<KnowledgeEntry>)
put<KnowledgeEntry>(`/knowledge/entries/${id}`, data)
export const deleteKnowledgeEntry = (id: number) => del(`/knowledge/entries/${id}`)
// 快捷回复(团队 / 个人)
export type QuickReplyScope = 'team' | 'personal'
export interface QuickReply {
id: number
tenant_id: number
scope: QuickReplyScope
owner_user_id?: number | null
title: string
content: string
shortcut: string
group_name: string
status: 'draft' | 'published' | string
sort_order: number
usage_count: number
created_at: string
updated_at: string
}
export const getQuickReplies = (params?: {
scope?: 'team' | 'personal' | 'all'
status?: string
q?: string
page?: number
pageSize?: number
}) => {
const search = new URLSearchParams()
if (params?.scope) search.set('scope', params.scope)
if (params?.status) search.set('status', params.status)
if (params?.q) search.set('q', params.q)
if (params?.page) search.set('page', String(params.page))
if (params?.pageSize) search.set('pageSize', String(params.pageSize))
const qs = search.toString()
return getList<QuickReply>(`/quick-replies${qs ? `?${qs}` : ''}`)
}
export const suggestQuickReplies = (prefix = '') => {
const search = new URLSearchParams()
if (prefix) search.set('prefix', prefix)
const qs = search.toString()
return get<QuickReply[]>(`/quick-replies/suggest${qs ? `?${qs}` : ''}`)
}
export const createQuickReply = (data: {
scope: QuickReplyScope
title: string
content: string
shortcut?: string
group_name?: string
status?: string
sort_order?: number
}) => post<QuickReply>('/quick-replies', data)
export const updateQuickReply = (id: number, data: {
title: string
content: string
shortcut?: string
group_name?: string
status?: string
sort_order?: number
}) => put<QuickReply>(`/quick-replies/${id}`, data)
export const deleteQuickReply = (id: number) => del(`/quick-replies/${id}`)
export const publishQuickReply = (id: number) => post<QuickReply>(`/quick-replies/${id}/publish`, {})
export const unpublishQuickReply = (id: number) => post<QuickReply>(`/quick-replies/${id}/unpublish`, {})
export const useQuickReply = (id: number) => post<{ ok: boolean; usage_count: number }>(`/quick-replies/${id}/use`, {})
export const exportQuickReplies = (scope: QuickReplyScope) =>
downloadFile(`/quick-replies/export?scope=${scope}`, `quick_replies_${scope}.csv`)
export const downloadQuickReplyTemplate = () =>
downloadFile('/quick-replies/import-template', 'quick_replies_template.csv')
export const importQuickReplies = (file: File, scope: QuickReplyScope, onConflict: 'skip' | 'overwrite' = 'skip') => {
const form = new FormData()
form.append('file', file)
form.append('scope', scope)
form.append('on_conflict', onConflict)
return postForm<{ created: number; updated: number; skipped: number; errors: string[] }>(
`/quick-replies/import?scope=${scope}`,
form,
)
}
// Channels
export const getChannels = () => get<Channel[]>('/channels')
export const createChannel = (data: { type: string; name?: string }) => post<Channel>('/channels', data)