存客宝 React

This commit is contained in:
柳清爽
2025-03-29 16:50:39 +08:00
parent caea0b4b99
commit 7e7c199996
388 changed files with 53282 additions and 2076 deletions

69
Cunkebao/lib/api/auth.ts Normal file
View File

@@ -0,0 +1,69 @@
// API请求工具函数
import { toast } from "@/components/ui/use-toast"
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.example.com"
// 带有认证的请求函数
export async function authFetch(url: string, options: RequestInit = {}) {
const token = localStorage.getItem("token")
// 合并headers
let headers = { ...options.headers }
// 如果有token添加到请求头
if (token) {
headers = {
...headers,
Token: `${token}`,
}
}
try {
const response = await fetch(`${API_BASE_URL}${url}`, {
...options,
headers,
})
const data = await response.json()
// 检查token是否过期仅当有token时
if (token && (data.code === 401 || data.code === 403)) {
// 清除token
localStorage.removeItem("token")
// 暂时不重定向到登录页
// if (typeof window !== "undefined") {
// window.location.href = "/login"
// }
console.warn("登录已过期")
}
return data
} catch (error) {
console.error("API请求错误:", error)
toast({
variant: "destructive",
title: "请求失败",
description: error instanceof Error ? error.message : "网络错误,请稍后重试",
})
throw error
}
}
// 不需要认证的请求函数
export async function publicFetch(url: string, options: RequestInit = {}) {
try {
const response = await fetch(`${API_BASE_URL}${url}`, options)
return await response.json()
} catch (error) {
console.error("API请求错误:", error)
toast({
variant: "destructive",
title: "请求失败",
description: error instanceof Error ? error.message : "网络错误,请稍后重试",
})
throw error
}
}

125
Cunkebao/lib/api/content.ts Normal file
View File

@@ -0,0 +1,125 @@
import type { ApiResponse, PaginatedResponse } from "@/types/common"
import type { ContentLibrary, ContentItem } from "@/types/content-library"
const API_BASE = "/api/content"
// 内容库API
export const contentApi = {
// 创建内容库
async createLibrary(data: Partial<ContentLibrary>): Promise<ApiResponse<ContentLibrary>> {
const response = await fetch(`${API_BASE}/libraries`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取内容库列表
async getLibraries(params: {
page?: number
pageSize?: number
search?: string
type?: string
}): Promise<ApiResponse<PaginatedResponse<ContentLibrary>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/libraries?${queryString.toString()}`)
return response.json()
},
// 获取内容库详情
async getLibraryById(id: string): Promise<ApiResponse<ContentLibrary>> {
const response = await fetch(`${API_BASE}/libraries/${id}`)
return response.json()
},
// 更新内容库
async updateLibrary(id: string, data: Partial<ContentLibrary>): Promise<ApiResponse<ContentLibrary>> {
const response = await fetch(`${API_BASE}/libraries/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除内容库
async deleteLibrary(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/libraries/${id}`, {
method: "DELETE",
})
return response.json()
},
// 创建内容项
async createItem(libraryId: string, data: Partial<ContentItem>): Promise<ApiResponse<ContentItem>> {
const response = await fetch(`${API_BASE}/libraries/${libraryId}/items`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取内容项列表
async getItems(
libraryId: string,
params: {
page?: number
pageSize?: number
search?: string
type?: string
},
): Promise<ApiResponse<PaginatedResponse<ContentItem>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/libraries/${libraryId}/items?${queryString.toString()}`)
return response.json()
},
// 获取内容项详情
async getItemById(libraryId: string, itemId: string): Promise<ApiResponse<ContentItem>> {
const response = await fetch(`${API_BASE}/libraries/${libraryId}/items/${itemId}`)
return response.json()
},
// 更新内容项
async updateItem(libraryId: string, itemId: string, data: Partial<ContentItem>): Promise<ApiResponse<ContentItem>> {
const response = await fetch(`${API_BASE}/libraries/${libraryId}/items/${itemId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除内容项
async deleteItem(libraryId: string, itemId: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/libraries/${libraryId}/items/${itemId}`, {
method: "DELETE",
})
return response.json()
},
}

131
Cunkebao/lib/api/devices.ts Normal file
View File

@@ -0,0 +1,131 @@
import type {
ApiResponse,
Device,
DeviceStats,
DeviceTaskRecord,
PaginatedResponse,
QueryDeviceParams,
CreateDeviceParams,
UpdateDeviceParams,
DeviceStatus,
} from "@/types/device"
const API_BASE = "/api/devices"
// 设备管理API
export const deviceApi = {
// 创建设备
async create(params: CreateDeviceParams): Promise<ApiResponse<Device>> {
const response = await fetch(`${API_BASE}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
})
return response.json()
},
// 更新设备
async update(params: UpdateDeviceParams): Promise<ApiResponse<Device>> {
const response = await fetch(`${API_BASE}/${params.id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
})
return response.json()
},
// 获取设备详情
async getById(id: string): Promise<ApiResponse<Device>> {
const response = await fetch(`${API_BASE}/${id}`)
return response.json()
},
// 查询设备列表
async query(params: QueryDeviceParams): Promise<ApiResponse<PaginatedResponse<Device>>> {
const queryString = new URLSearchParams({
...params,
tags: params.tags ? JSON.stringify(params.tags) : "",
dateRange: params.dateRange ? JSON.stringify(params.dateRange) : "",
}).toString()
const response = await fetch(`${API_BASE}?${queryString}`)
return response.json()
},
// 删除设备
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}`, {
method: "DELETE",
})
return response.json()
},
// 重启设备
async restart(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}/restart`, {
method: "POST",
})
return response.json()
},
// 解绑设备
async unbind(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}/unbind`, {
method: "POST",
})
return response.json()
},
// 获取设备统计数据
async getStats(id: string): Promise<ApiResponse<DeviceStats>> {
const response = await fetch(`${API_BASE}/${id}/stats`)
return response.json()
},
// 获取设备任务记录
async getTaskRecords(id: string, page = 1, pageSize = 20): Promise<ApiResponse<PaginatedResponse<DeviceTaskRecord>>> {
const response = await fetch(`${API_BASE}/${id}/tasks?page=${page}&pageSize=${pageSize}`)
return response.json()
},
// 批量更新设备标签
async updateTags(ids: string[], tags: string[]): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/tags`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ deviceIds: ids, tags }),
})
return response.json()
},
// 批量导出设备数据
async exportDevices(ids: string[]): Promise<Blob> {
const response = await fetch(`${API_BASE}/export`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ deviceIds: ids }),
})
return response.blob()
},
// 检查设备在线状态
async checkStatus(ids: string[]): Promise<ApiResponse<Record<string, DeviceStatus>>> {
const response = await fetch(`${API_BASE}/status`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ deviceIds: ids }),
})
return response.json()
},
}

View File

@@ -0,0 +1,8 @@
// 导出所有API客户端方便统一导入
export * from "./scenarios"
export * from "./devices"
export * from "./users"
export * from "./content"
export * from "./traffic"
export * from "./workspace"

View File

@@ -0,0 +1,112 @@
import type {
ApiResponse,
CreateScenarioParams,
UpdateScenarioParams,
QueryScenarioParams,
ScenarioBase,
ScenarioStats,
AcquisitionRecord,
PaginatedResponse,
} from "@/types/scenario"
const API_BASE = "/api/scenarios"
// 获客场景API
export const scenarioApi = {
// 创建场景
async create(params: CreateScenarioParams): Promise<ApiResponse<ScenarioBase>> {
const response = await fetch(`${API_BASE}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
})
return response.json()
},
// 更新场景
async update(params: UpdateScenarioParams): Promise<ApiResponse<ScenarioBase>> {
const response = await fetch(`${API_BASE}/${params.id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
})
return response.json()
},
// 获取场景详情
async getById(id: string): Promise<ApiResponse<ScenarioBase>> {
const response = await fetch(`${API_BASE}/${id}`)
return response.json()
},
// 查询场景列表
async query(params: QueryScenarioParams): Promise<ApiResponse<PaginatedResponse<ScenarioBase>>> {
const queryString = new URLSearchParams({
...params,
dateRange: params.dateRange ? JSON.stringify(params.dateRange) : "",
}).toString()
const response = await fetch(`${API_BASE}?${queryString}`)
return response.json()
},
// 删除场景
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}`, {
method: "DELETE",
})
return response.json()
},
// 启动场景
async start(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}/start`, {
method: "POST",
})
return response.json()
},
// 暂停场景
async pause(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}/pause`, {
method: "POST",
})
return response.json()
},
// 获取场景统计数据
async getStats(id: string): Promise<ApiResponse<ScenarioStats>> {
const response = await fetch(`${API_BASE}/${id}/stats`)
return response.json()
},
// 获取获客记录
async getRecords(id: string, page = 1, pageSize = 20): Promise<ApiResponse<PaginatedResponse<AcquisitionRecord>>> {
const response = await fetch(`${API_BASE}/${id}/records?page=${page}&pageSize=${pageSize}`)
return response.json()
},
// 导出获客记录
async exportRecords(id: string, dateRange?: { start: string; end: string }): Promise<Blob> {
const queryString = dateRange ? `?start=${dateRange.start}&end=${dateRange.end}` : ""
const response = await fetch(`${API_BASE}/${id}/records/export${queryString}`)
return response.blob()
},
// 批量更新标签
async updateTags(id: string, customerIds: string[], tags: string[]): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/${id}/tags`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ customerIds, tags }),
})
return response.json()
},
}

122
Cunkebao/lib/api/traffic.ts Normal file
View File

@@ -0,0 +1,122 @@
import type { ApiResponse, PaginatedResponse } from "@/types/common"
import type { TrafficPool, TrafficDistribution } from "@/types/traffic"
const API_BASE = "/api/traffic"
// 流量池API
export const trafficApi = {
// 创建流量池
async createPool(data: Partial<TrafficPool>): Promise<ApiResponse<TrafficPool>> {
const response = await fetch(`${API_BASE}/pools`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取流量池列表
async getPools(params: {
page?: number
pageSize?: number
search?: string
type?: string
}): Promise<ApiResponse<PaginatedResponse<TrafficPool>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/pools?${queryString.toString()}`)
return response.json()
},
// 获取流量池详情
async getPoolById(id: string): Promise<ApiResponse<TrafficPool>> {
const response = await fetch(`${API_BASE}/pools/${id}`)
return response.json()
},
// 更新流量池
async updatePool(id: string, data: Partial<TrafficPool>): Promise<ApiResponse<TrafficPool>> {
const response = await fetch(`${API_BASE}/pools/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除流量池
async deletePool(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/pools/${id}`, {
method: "DELETE",
})
return response.json()
},
// 创建流量分配
async createDistribution(data: Partial<TrafficDistribution>): Promise<ApiResponse<TrafficDistribution>> {
const response = await fetch(`${API_BASE}/distributions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取流量分配列表
async getDistributions(params: {
page?: number
pageSize?: number
search?: string
poolId?: string
}): Promise<ApiResponse<PaginatedResponse<TrafficDistribution>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/distributions?${queryString.toString()}`)
return response.json()
},
// 获取流量分配详情
async getDistributionById(id: string): Promise<ApiResponse<TrafficDistribution>> {
const response = await fetch(`${API_BASE}/distributions/${id}`)
return response.json()
},
// 更新流量分配
async updateDistribution(id: string, data: Partial<TrafficDistribution>): Promise<ApiResponse<TrafficDistribution>> {
const response = await fetch(`${API_BASE}/distributions/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除流量分配
async deleteDistribution(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/distributions/${id}`, {
method: "DELETE",
})
return response.json()
},
}

91
Cunkebao/lib/api/users.ts Normal file
View File

@@ -0,0 +1,91 @@
import type { TrafficUser } from "@/types/traffic"
import type { ApiResponse } from "@/types/common"
const API_BASE = "/api/users"
// 用户管理API
export const userApi = {
// 查询用户列表
async query(params: {
page?: number
pageSize?: number
search?: string
category?: string
source?: string
status?: string
startDate?: string
endDate?: string
wechatSource?: string
}): Promise<{
users: TrafficUser[]
pagination: {
total: number
totalPages: number
currentPage: number
pageSize: number
}
stats: {
total: number
todayNew: number
categoryStats: {
potential: number
customer: number
lost: number
}
}
}> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}?${queryString.toString()}`)
return response.json()
},
// 获取用户详情
async getById(id: string): Promise<ApiResponse<TrafficUser>> {
const response = await fetch(`${API_BASE}/${id}`)
return response.json()
},
// 更新用户信息
async update(id: string, data: Partial<TrafficUser>): Promise<ApiResponse<TrafficUser>> {
const response = await fetch(`${API_BASE}/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 批量更新用户标签
async updateTags(ids: string[], tags: string[]): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/tags`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ userIds: ids, tags }),
})
return response.json()
},
// 批量导出用户数据
async exportUsers(ids: string[]): Promise<Blob> {
const response = await fetch(`${API_BASE}/export`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ userIds: ids }),
})
return response.blob()
},
}

View File

@@ -0,0 +1,319 @@
import type { ApiResponse, PaginatedResponse } from "@/types/common"
import type { MomentsSync, GroupSync, GroupPush, AutoLike, AutoGroup } from "@/types/workspace"
const API_BASE = "/api/workspace"
// 工作区API
export const workspaceApi = {
// 朋友圈同步API
moments: {
// 创建朋友圈同步任务
async create(data: Partial<MomentsSync>): Promise<ApiResponse<MomentsSync>> {
const response = await fetch(`${API_BASE}/moments-sync`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取朋友圈同步任务列表
async getList(params: {
page?: number
pageSize?: number
status?: string
}): Promise<ApiResponse<PaginatedResponse<MomentsSync>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/moments-sync?${queryString.toString()}`)
return response.json()
},
// 获取朋友圈同步任务详情
async getById(id: string): Promise<ApiResponse<MomentsSync>> {
const response = await fetch(`${API_BASE}/moments-sync/${id}`)
return response.json()
},
// 更新朋友圈同步任务
async update(id: string, data: Partial<MomentsSync>): Promise<ApiResponse<MomentsSync>> {
const response = await fetch(`${API_BASE}/moments-sync/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除朋友圈同步任务
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/moments-sync/${id}`, {
method: "DELETE",
})
return response.json()
},
// 启动朋友圈同步任务
async start(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/moments-sync/${id}/start`, {
method: "POST",
})
return response.json()
},
// 暂停朋友圈同步任务
async pause(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/moments-sync/${id}/pause`, {
method: "POST",
})
return response.json()
},
},
// 群同步API
groupSync: {
// 创建群同步任务
async create(data: Partial<GroupSync>): Promise<ApiResponse<GroupSync>> {
const response = await fetch(`${API_BASE}/group-sync`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取群同步任务列表
async getList(params: {
page?: number
pageSize?: number
status?: string
}): Promise<ApiResponse<PaginatedResponse<GroupSync>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/group-sync?${queryString.toString()}`)
return response.json()
},
// 获取群同步任务详情
async getById(id: string): Promise<ApiResponse<GroupSync>> {
const response = await fetch(`${API_BASE}/group-sync/${id}`)
return response.json()
},
// 更新群同步任务
async update(id: string, data: Partial<GroupSync>): Promise<ApiResponse<GroupSync>> {
const response = await fetch(`${API_BASE}/group-sync/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除群同步任务
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/group-sync/${id}`, {
method: "DELETE",
})
return response.json()
},
},
// 群发API
groupPush: {
// 创建群发任务
async create(data: Partial<GroupPush>): Promise<ApiResponse<GroupPush>> {
const response = await fetch(`${API_BASE}/group-push`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取群发任务列表
async getList(params: {
page?: number
pageSize?: number
status?: string
}): Promise<ApiResponse<PaginatedResponse<GroupPush>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/group-push?${queryString.toString()}`)
return response.json()
},
// 获取群发任务详情
async getById(id: string): Promise<ApiResponse<GroupPush>> {
const response = await fetch(`${API_BASE}/group-push/${id}`)
return response.json()
},
// 更新群发任务
async update(id: string, data: Partial<GroupPush>): Promise<ApiResponse<GroupPush>> {
const response = await fetch(`${API_BASE}/group-push/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除群发任务
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/group-push/${id}`, {
method: "DELETE",
})
return response.json()
},
},
// 自动点赞API
autoLike: {
// 创建自动点赞任务
async create(data: Partial<AutoLike>): Promise<ApiResponse<AutoLike>> {
const response = await fetch(`${API_BASE}/auto-like`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取自动点赞任务列表
async getList(params: {
page?: number
pageSize?: number
status?: string
}): Promise<ApiResponse<PaginatedResponse<AutoLike>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/auto-like?${queryString.toString()}`)
return response.json()
},
// 获取自动点赞任务详情
async getById(id: string): Promise<ApiResponse<AutoLike>> {
const response = await fetch(`${API_BASE}/auto-like/${id}`)
return response.json()
},
// 更新自动点赞任务
async update(id: string, data: Partial<AutoLike>): Promise<ApiResponse<AutoLike>> {
const response = await fetch(`${API_BASE}/auto-like/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除自动点赞任务
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/auto-like/${id}`, {
method: "DELETE",
})
return response.json()
},
},
// 自动建群API
autoGroup: {
// 创建自动建群任务
async create(data: Partial<AutoGroup>): Promise<ApiResponse<AutoGroup>> {
const response = await fetch(`${API_BASE}/auto-group`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 获取自动建群任务列表
async getList(params: {
page?: number
pageSize?: number
status?: string
}): Promise<ApiResponse<PaginatedResponse<AutoGroup>>> {
const queryString = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== "") {
queryString.append(key, String(value))
}
})
const response = await fetch(`${API_BASE}/auto-group?${queryString.toString()}`)
return response.json()
},
// 获取自动建群任务详情
async getById(id: string): Promise<ApiResponse<AutoGroup>> {
const response = await fetch(`${API_BASE}/auto-group/${id}`)
return response.json()
},
// 更新自动建群任务
async update(id: string, data: Partial<AutoGroup>): Promise<ApiResponse<AutoGroup>> {
const response = await fetch(`${API_BASE}/auto-group/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
return response.json()
},
// 删除自动建群任务
async delete(id: string): Promise<ApiResponse<void>> {
const response = await fetch(`${API_BASE}/auto-group/${id}`, {
method: "DELETE",
})
return response.json()
},
},
}

60
Cunkebao/lib/tutorials.ts Normal file
View File

@@ -0,0 +1,60 @@
import type { PageTutorial, TutorialVideo } from "@/types/tutorial"
// 模拟后台配置的教程视频数据
export const tutorialConfig: PageTutorial[] = [
{
pageId: "home",
videos: [
{
id: "home-intro",
title: "存客宝使用介绍",
description: "了解存客宝的主要功能和基本操作流程",
url: "/videos/home-intro.mp4",
thumbnailUrl: "/placeholder.svg?height=360&width=640",
},
],
},
{
pageId: "scenarios/xiaohongshu",
videos: [
{
id: "xiaohongshu-intro",
title: "小红书获客功能介绍",
description: "学习如何使用小红书场景获取精准客户",
url: "/videos/xiaohongshu-intro.mp4",
thumbnailUrl: "/placeholder.svg?height=360&width=640",
},
{
id: "xiaohongshu-setup",
title: "小红书获客配置教程",
description: "详细了解小红书获客的各项配置选项",
url: "/videos/xiaohongshu-setup.mp4",
thumbnailUrl: "/placeholder.svg?height=360&width=640",
},
],
},
{
pageId: "scenarios/douyin",
videos: [
{
id: "douyin-intro",
title: "抖音获客功能介绍",
description: "学习如何使用抖音场景获取精准客户",
url: "/videos/douyin-intro.mp4",
thumbnailUrl: "/placeholder.svg?height=360&width=640",
},
],
},
// ... 其他页面的视频配置
]
export function getPageTutorials(path: string): TutorialVideo[] {
// 移除开头的斜杠并标准化路径
const normalizedPath = path.replace(/^\/+/, "")
// 查找匹配的页面教程
const pageTutorial = tutorialConfig.find((config) => normalizedPath.startsWith(config.pageId))
return pageTutorial?.videos || []
}

7
Cunkebao/lib/utils.ts Normal file
View File

@@ -0,0 +1,7 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}