Files
trade-assistant/uni-app/src/utils/api.js
T
TradeMate Dev 4755cc75ba feat: 管理后台完整可用 + 注册登录记日志 + 提取信息结构化展示 + 微信配置就绪
- 管理后台用户/统计/日志/配置四页签全部对接真实后端API
- auth注册/登录/游客/微信登录事件写入usage_logs表
- 提取信息结果从原始JSON改为卡片式字段列表(中文标签)
- 管理后台搜索按钮增加加载态和结果数提示
- 配置WECHAT_APP_ID/WECHAT_APP_SECRET
- 客户/产品/报价单CRUD页面完整(导出导入批量操作)
2026-05-18 23:50:48 +08:00

325 lines
12 KiB
JavaScript

export const BASE_URL = '/api/v1'
const getAuthHeader = () => {
const token = uni.getStorageSync('token')
return token ? { Authorization: `Bearer ${token}` } : {}
}
const request = (url, method = 'GET', data = {}) => {
return new Promise((resolve, reject) => {
uni.request({
url: `${BASE_URL}${url}`,
method,
data,
header: {
'Content-Type': 'application/json',
...getAuthHeader(),
},
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data)
} else if (res.statusCode === 401) {
uni.removeStorageSync('token')
uni.reLaunch({ url: '/pages/login/login' })
reject(new Error('Unauthorized'))
} else {
reject(new Error(res.data?.detail || 'Request failed'))
}
},
fail: (err) => {
reject(err)
},
})
})
}
const requestWithoutAuth = (url, method = 'GET', data = {}) => {
return new Promise((resolve, reject) => {
uni.request({
url: `${BASE_URL}${url}`,
method,
data,
header: {
'Content-Type': 'application/json',
},
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data)
} else {
reject(new Error(res.data?.detail || 'Request failed'))
}
},
fail: (err) => {
reject(err)
},
})
})
}
export const authApi = {
login: (phone, password) => request('/auth/login', 'POST', { username: phone, password }),
register: (phone, password, username) => request('/auth/register', 'POST', { phone, password, username }),
getUserInfo: () => request('/auth/me'),
wechatLogin: (code) => request('/auth/wechat-login', 'POST', { code }),
wechatConfig: () => request('/auth/wechat/config'),
guestLogin: () => requestWithoutAuth('/auth/login/guest', 'POST'),
}
export const marketingApi = {
generate: (productName, description, category, target = 'US importers', style = 'professional') =>
request('/marketing/generate', 'POST', {
product_name: productName,
description,
category,
target,
style,
}),
getKeywords: (productName, description, category = '', language = 'en', count = 10) =>
request('/marketing/keywords', 'POST', {
product_name: productName,
description,
category,
language,
count,
}),
competitorAnalysis: (productName, description, category = '', market = 'US') =>
request('/marketing/competitor-analysis', 'POST', {
product_name: productName,
description,
category,
market,
}),
}
export const quotationApi = {
list: (page = 1, size = 20) => request(`/quotations?page=${page}&size=${size}`),
get: (id) => request(`/quotations/${id}`),
create: (data) => request('/quotations', 'POST', data),
updateStatus: (id, status) => request(`/quotations/${id}/status`, 'PATCH', { status }),
exportPdf: (id) => `${BASE_URL}/quotations/${id}/pdf`,
exportCsv: () => `${BASE_URL}/quotations/export/csv`,
exportXlsx: () => `${BASE_URL}/quotations/export/xlsx`,
generateFromInquiry: (inquiryText, customerId = null) =>
request('/quotations/generate-from-inquiry', 'POST', { inquiry_text: inquiryText, customer_id: customerId }),
importQuotations: (file) => {
return new Promise((resolve, reject) => {
const token = uni.getStorageSync('token')
uni.uploadFile({
url: `${BASE_URL}/quotations/import`,
filePath: file,
name: 'file',
header: token ? { Authorization: `Bearer ${token}` } : {},
success: (res) => {
try {
resolve(JSON.parse(res.data))
} catch (e) {
resolve(res.data)
}
},
fail: reject,
})
})
},
}
export const productApi = {
list: (page = 1, size = 20) => request(`/products?page=${page}&size=${size}`),
get: (id) => request(`/products/${id}`),
create: (data) => request('/products', 'POST', data),
update: (id, data) => request(`/products/${id}`, 'PATCH', data),
delete: (id) => request(`/products/${id}`, 'DELETE'),
exportCsv: () => `${BASE_URL}/products/export/csv`,
exportXlsx: () => `${BASE_URL}/products/export/xlsx`,
importProducts: (file) => {
return new Promise((resolve, reject) => {
const token = uni.getStorageSync('token')
uni.uploadFile({
url: `${BASE_URL}/products/import`,
filePath: file,
name: 'file',
header: token ? { Authorization: `Bearer ${token}` } : {},
success: (res) => {
try {
resolve(JSON.parse(res.data))
} catch (e) {
resolve(res.data)
}
},
fail: reject,
})
})
},
}
export const adminApi = {
getDashboard: () => request('/admin/dashboard'),
listUsers: (page = 1, size = 20, role) => {
let url = `/admin/users?page=${page}&size=${size}`
if (role) url += `&role=${role}`
return request(url)
},
updateUserTier: (userId, tier) => request(`/admin/users/${userId}/tier`, 'PATCH', { tier }),
updateUserRole: (userId, role) => request(`/admin/users/${userId}/role`, 'PATCH', { role }),
toggleUserActive: (userId) => request(`/admin/users/${userId}/toggle-active`, 'POST'),
getUserDetail: (userId) => request(`/admin/users/${userId}`),
searchUsers: (q) => request(`/admin/users/search?q=${encodeURIComponent(q)}`),
getUsageStats: () => request('/admin/usage-stats'),
getLogs: (page = 1, size = 50, filters = {}) => {
let url = `/admin/logs?page=${page}&size=${size}`
if (filters.action) url += `&action=${encodeURIComponent(filters.action)}`
if (filters.user_id) url += `&user_id=${encodeURIComponent(filters.user_id)}`
if (filters.date_from) url += `&date_from=${filters.date_from}`
if (filters.date_to) url += `&date_to=${filters.date_to}`
return request(url)
},
getConfig: () => request('/admin/config'),
updateConfig: (key, value) => request(`/admin/config/${key}`, 'PUT', { value }),
}
export const analyticsApi = {
getOverview: () => request('/analytics/overview'),
getCustomers: () => request('/analytics/customers'),
getTranslations: () => request('/analytics/translations'),
getQuotations: () => request('/analytics/quotations'),
getMessages: () => request('/analytics/messages'),
}
export const teamApi = {
list: () => request('/teams'),
get: (id) => request(`/teams/${id}`),
create: (name, description) => request('/teams', 'POST', { name, description }),
invite: (teamId, userId) => request(`/teams/${teamId}/invite`, 'POST', { user_id: userId }),
removeMember: (teamId, memberId) => request(`/teams/${teamId}/members/${memberId}`, 'DELETE'),
leave: (teamId) => request(`/teams/${teamId}/leave`, 'POST'),
updateRole: (teamId, memberId, role) => request(`/teams/${teamId}/members/${memberId}/role`, 'PATCH', { role }),
}
export const translateApi = {
translate: (text, targetLang, sourceLang = 'auto') =>
request('/translate', 'POST', { text, target_lang: targetLang, source_lang: sourceLang }),
getReply: (inquiry, tone = 'professional', count = 3) =>
request('/translate/reply', 'POST', { inquiry, tone, count }),
extract: (text, extractType = 'auto') =>
request('/translate/extract', 'POST', { text, extract_type: extractType }),
sendFeedback: (entryId, rating) =>
request('/translate/feedback', 'POST', { entry_id: entryId, rating }),
publicTranslate: (text, targetLang, sourceLang = 'auto') =>
requestWithoutAuth('/translate/public/translate', 'POST', { text, target_lang: targetLang, source_lang: sourceLang }),
publicExtract: (text, extractType = 'auto') =>
requestWithoutAuth('/translate/public/extract', 'POST', { text, extract_type: extractType }),
}
export const notificationApi = {
list: (page = 1, size = 20, unreadOnly = false) =>
request(`/notifications?page=${page}&size=${size}&unread_only=${unreadOnly}`),
unreadCount: () => request('/notifications/unread-count'),
markRead: (id) => request(`/notifications/${id}/read`, 'PATCH'),
markAllRead: () => request('/notifications/read-all', 'POST'),
delete: (id) => request(`/notifications/${id}`, 'DELETE'),
}
export const paymentApi = {
plans: () => request('/payment/plans'),
subscription: () => request('/payment/subscription'),
createOrder: (plan) => request('/payment/create-order', 'POST', { plan }),
}
export const feedbackApi = {
submit: (content, category = 'general', contact = '') =>
request('/feedback', 'POST', { content, category, contact }),
}
export const onboardingApi = {
status: () => request('/onboarding/status'),
createProduct: (name, description, category, target) =>
request('/onboarding/product', 'POST', { name, description, category, target }),
}
export const interactionApi = {
selectSuggestion: (messageId, selectedIndex) =>
request('/interaction/select', 'POST', { message_id: messageId, selected_index: selectedIndex }),
recordEdit: (messageId, editedText) =>
request('/interaction/edit', 'POST', { message_id: messageId, edited_text: editedText }),
analyzePreferences: () => request('/interaction/analyze', 'POST'),
getPreferences: () => request('/interaction/preferences'),
trackMarketingEffect: (data) => request('/interaction/marketing-effect', 'POST', data),
getMarketingEffects: (page = 1, size = 20) =>
request(`/interaction/marketing-effects?page=${page}&size=${size}`),
getMarketingEffectStats: () => request('/interaction/marketing-effects/stats'),
}
export const exchangeApi = {
convert: (fromCurrency = 'USD', toCurrency = 'CNY', amount = 1) =>
request(`/exchange/convert?from_currency=${fromCurrency}&to_currency=${toCurrency}&amount=${amount}`),
rates: (base = 'USD') => request(`/exchange/rates?base=${base}`),
}
export const pushApi = {
register: (clientId, platform = 'weapp', pushToken = null, deviceInfo = null) =>
request('/push/register', 'POST', { client_id: clientId, platform, push_token: pushToken, device_info: deviceInfo }),
unregister: (clientId) =>
request('/push/unregister', 'POST', { client_id: clientId }),
listDevices: () => request('/push/devices'),
}
export const silentPatternApi = {
getRiskAnalysis: () => request('/silent-pattern/risk-analysis'),
getSuggestions: (customerId) => request(`/silent-pattern/${customerId}/suggestions`),
}
export const followupApi = {
strategies: () => request('/followup/strategies'),
pending: (page = 1) => request(`/followup/pending?page=${page}`),
logs: (page = 1) => request(`/followup/logs?page=${page}`),
markSent: (id) => request(`/followup/${id}/send`, 'POST'),
editAndSend: (id, editedText) => request(`/followup/${id}/edit`, 'POST', { edited_text: editedText }),
stats: () => request('/followup/stats'),
scan: () => request('/followup/scan', 'POST'),
}
export const healthApi = {
overview: () => request('/customers/health-overview'),
allScores: () => request('/customers/health-scores'),
customerHealth: (id) => request(`/customers/${id}/health`),
}
export const whatsappApi = {
send: (to, text, templateName = null, templateParams = null, mediaUrl = null, mediaType = null) =>
request('/whatsapp/send', 'POST', { to, text, template_name: templateName, template_params: templateParams, media_url: mediaUrl, media_type: mediaType }),
}
export const customerApi = {
list: (page = 1, size = 20, status) => {
let params = `page=${page}&size=${size}`
if (status) params += `&status=${status}`
return request(`/customers?${params}`)
},
get: (id) => request(`/customers/${id}`),
create: (data) => request('/customers', 'POST', data),
update: (id, data) => request(`/customers/${id}`, 'PATCH', data),
delete: (id) => request(`/customers/${id}`, 'DELETE'),
getSilent: (days = 3) => request(`/customers/silent?days=${days}`),
getConversation: (id, page = 1, size = 50) =>
request(`/customers/${id}/conversation?page=${page}&size=${size}`),
exportCsv: () => `${BASE_URL}/customers/export/csv`,
exportXlsx: () => `${BASE_URL}/customers/export/xlsx`,
importCustomers: (file) => {
return new Promise((resolve, reject) => {
const token = uni.getStorageSync('token')
uni.uploadFile({
url: `${BASE_URL}/customers/import`,
filePath: file,
name: 'file',
header: token ? { Authorization: `Bearer ${token}` } : {},
success: (res) => {
try {
resolve(JSON.parse(res.data))
} catch (e) {
resolve(res.data)
}
},
fail: reject,
})
})
},
}