feat: 修复 H5 底部导航覆盖 + 更新项目进度文档
## H5 底部导航修复 (Bug #10) - 精简 App.vue,移除重复 tabbar,仅保留全局样式 - uni-page 设置 height: calc(100% - 50px) + overflow-y: auto - 内容区域精确停在底部导航上方,独立滚动不再叠加 - 恢复 custom-tab-bar 组件 ## 项目进度文档 - PROGRESS.md 更新至 10 个 Bug 修复 - 新增 H5 底部导航修复记录 - 新增历史变更条目
This commit is contained in:
+197
-27
@@ -1,4 +1,4 @@
|
||||
const BASE_URL = 'http://localhost:8000/api/v1'
|
||||
export const BASE_URL = 'http://localhost:8000/api/v1'
|
||||
|
||||
const getAuthHeader = () => {
|
||||
const token = uni.getStorageSync('token')
|
||||
@@ -33,10 +33,104 @@ const request = (url, method = 'GET', data = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
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 }),
|
||||
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`,
|
||||
generateFromInquiry: (inquiryText, customerId = null) =>
|
||||
request('/quotations/generate-from-inquiry', 'POST', { inquiry_text: inquiryText, customer_id: customerId }),
|
||||
}
|
||||
|
||||
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'),
|
||||
}
|
||||
|
||||
export const adminApi = {
|
||||
getDashboard: () => request('/admin/dashboard'),
|
||||
listUsers: (page = 1, size = 20) => request(`/admin/users?page=${page}&size=${size}`),
|
||||
updateUserTier: (userId, tier) => request(`/admin/users/${userId}/tier`, 'PATCH', { tier }),
|
||||
}
|
||||
|
||||
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 = {
|
||||
@@ -44,6 +138,88 @@ export const translateApi = {
|
||||
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 customerApi = {
|
||||
@@ -59,30 +235,24 @@ export const customerApi = {
|
||||
getSilent: (days = 3) => request(`/customers/silent?days=${days}`),
|
||||
getConversation: (id, page = 1, size = 50) =>
|
||||
request(`/customers/${id}/conversation?page=${page}&size=${size}`),
|
||||
}
|
||||
|
||||
export const marketingApi = {
|
||||
generate: (productName, description, category, target = 'US importers', style = 'professional') =>
|
||||
request('/marketing/generate', 'POST', {
|
||||
product_name: productName,
|
||||
description,
|
||||
category,
|
||||
target,
|
||||
style,
|
||||
}),
|
||||
}
|
||||
|
||||
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 }),
|
||||
}
|
||||
|
||||
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}/customers/export/csv`,
|
||||
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,
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user