This commit is contained in:
sjk
2025-11-28 15:18:10 +08:00
parent ad4a600af9
commit 5683f35942
188 changed files with 53680 additions and 1062 deletions

588
web/assets/js/api.js Normal file
View File

@@ -0,0 +1,588 @@
// API接口调用模块
// 环境检测函数
function getAPIBaseURL() {
// 优先使用 localStorage 中的手动配置(用于调试)
const manualBaseURL = localStorage.getItem('API_BASE_URL');
if (manualBaseURL) {
console.log('[API] 使用手动配置的后端地址:', manualBaseURL);
return manualBaseURL;
}
const hostname = window.location.hostname;
const protocol = window.location.protocol;
// 开发环境判断localhost 或 127.0.0.1
if (hostname === 'localhost' || hostname === '127.0.0.1') {
return 'http://localhost:8081/api/v1';
}
// 生产环境根据域名映射API地址
// vizee.cn 域名使用 https://tral.cc/api/v1
if (hostname.includes('vizee.cn')) {
console.log('[API] 检测到 vizee.cn 域名,使用 tral.cc API');
return 'https://tral.cc/api/v1';
}
// gvizee.com 域名使用相对路径,由 Nginx 代理到后端
if (hostname.includes('gvizee.com')) {
console.log('[API] 检测到 gvizee.com 域名,使用 Nginx 代理');
// 使用相对路径自动继承当前页面的协议HTTPS
// Nginx 会将 /api/v1 请求代理到 http://104.244.91.212:8060/api/v1
return '/api/v1';
}
// 默认使用 tral.cc
console.log('[API] 使用默认 API 地址: tral.cc');
return 'https://tral.cc/api/v1';
}
// API配置
const API_CONFIG = {
baseURL: getAPIBaseURL(),
timeout: 30000,
headers: {
'Content-Type': 'application/json'
},
// 环境信息
env: {
isDevelopment: window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1',
isProduction: window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1'
}
};
// 控制台输出当前环境信息
console.log('[API] 当前环境:', API_CONFIG.env.isDevelopment ? '开发环境' : '生产环境');
console.log('[API] 后端地址:', API_CONFIG.baseURL);
// 全局辅助函数(用于开发调试)
window.API_DEBUG = {
// 设置后端地址
setBaseURL: function(url) {
localStorage.setItem('API_BASE_URL', url);
console.log('[API] 后端地址已设置为:', url);
console.log('[API] 请刷新页面使配置生效');
},
// 重置为自动检测
resetBaseURL: function() {
localStorage.removeItem('API_BASE_URL');
console.log('[API] 已重置为自动检测模式');
console.log('[API] 请刷新页面使配置生效');
},
// 查看当前配置
getConfig: function() {
return {
baseURL: API_CONFIG.baseURL,
environment: API_CONFIG.env.isDevelopment ? 'development' : 'production',
manualConfig: localStorage.getItem('API_BASE_URL') || 'auto',
currentURL: window.location.href
};
},
// 测试连接
testConnection: function() {
console.log('[API] 测试后端连接...');
fetch(API_CONFIG.baseURL.replace('/api/v1', '/health'))
.then(response => response.json())
.then(data => {
console.log('[API] ✅ 后端连接成功:', data);
})
.catch(error => {
console.error('[API] ❌ 后端连接失败:', error.message);
console.log('[API] 请确认后端服务已启动');
});
},
// 使用说明
help: function() {
console.log(`
=== API调试工具使用说明 ===
域名映射规则:
- vizee.cn 域名使用: https://tral.cc/api/v1
- gvizee.com 域名使用: https://104.244.91.212:8060/api/v1
- localhost/127.0.0.1 使用: http://localhost:8081/api/v1
- 其他域名默认使用: https://tral.cc/api/v1
1. 查看当前配置:
API_DEBUG.getConfig()
2. 手动设置后端地址:
API_DEBUG.setBaseURL('http://localhost:8080/api/v1')
API_DEBUG.setBaseURL('https://api.example.com/api/v1')
3. 重置为自动检测:
API_DEBUG.resetBaseURL()
4. 测试后端连接:
API_DEBUG.testConnection()
5. 查看帮助:
API_DEBUG.help()
`);
}
};
// 启动时提示
if (API_CONFIG.env.isDevelopment) {
console.log('[API] 💡 开发提示:在控制台输入 API_DEBUG.help() 查看调试工具使用说明');
}
// API模块
const API = {
// 获取Token
getToken: function() {
const user = localStorage.getItem('currentUser');
if (user) {
try {
const userData = JSON.parse(user);
return userData.token || '';
} catch (e) {
return '';
}
}
return '';
},
// 设置Token
setToken: function(token) {
const user = localStorage.getItem('currentUser');
if (user) {
try {
const userData = JSON.parse(user);
userData.token = token;
localStorage.setItem('currentUser', JSON.stringify(userData));
} catch (e) {
console.error('设置Token失败:', e);
}
}
},
// 通用请求方法
request: function(options) {
const url = API_CONFIG.baseURL + options.url;
const method = options.method || 'GET';
const data = options.data || null;
const headers = Object.assign({}, API_CONFIG.headers, options.headers || {});
// 添加认证Token
const token = this.getToken();
if (token) {
headers['Authorization'] = 'Bearer ' + token;
}
const ajaxOptions = {
url: url,
method: method,
headers: headers,
timeout: API_CONFIG.timeout,
xhrFields: {
withCredentials: true
}
};
// 添加数据
if (data) {
if (method === 'GET') {
ajaxOptions.data = data;
} else {
ajaxOptions.data = JSON.stringify(data);
}
}
// 返回Promise
return new Promise((resolve, reject) => {
$.ajax(ajaxOptions)
.done(function(response) {
// 检查响应格式
if (response && response.code === 200) {
resolve(response.data);
} else {
reject(response);
}
})
.fail(function(xhr, status, error) {
// 处理错误
const errorMsg = xhr.responseJSON?.message || error || '网络请求失败';
// 401未授权提示并跳转登录
if (xhr.status === 401) {
// 判断是未登录还是登录过期
const hadToken = !!localStorage.getItem('currentUser');
const message = hadToken ? '登录已过期,请重新登录' : '请先登录';
console.log('[401 拦截]', message);
// 清除登录状态
localStorage.removeItem('currentUser');
// 使用 Toast.alert 显示提示iOS 风格)
if (typeof Toast !== 'undefined' && Toast.alert) {
Toast.alert(message).then(() => {
// 用户点击确定后跳转
handleRedirectToLogin();
});
} else if (typeof Toast !== 'undefined' && Toast.warning) {
// 降级使用 warning
Toast.warning(message);
setTimeout(handleRedirectToLogin, 2000);
} else {
// 最后降级使用原生 alert
alert(message);
handleRedirectToLogin();
}
// 跳转逻辑封装
function handleRedirectToLogin() {
console.log('[401 跳转] 准备跳转登录页');
// 记录当前页面,登录后可以返回(排除登录页和用户中心)
const currentPage = window.location.pathname + window.location.search;
const shouldRedirect = !currentPage.includes('login.html') &&
!currentPage.includes('user-center.html');
if (shouldRedirect) {
localStorage.setItem('redirectUrl', currentPage);
console.log('[401 跳转] 保存 redirectUrl:', currentPage);
} else {
// 确保清除之前的redirectUrl
localStorage.removeItem('redirectUrl');
console.log('[401 跳转] 不保存 redirectUrl');
}
window.location.href = 'login.html';
}
reject({
code: 401,
message: message,
data: xhr.responseJSON
});
return;
}
reject({
code: xhr.status,
message: errorMsg,
data: xhr.responseJSON
});
});
});
},
// GET请求
get: function(url, params) {
return this.request({
url: url,
method: 'GET',
data: params
});
},
// POST请求
post: function(url, data) {
return this.request({
url: url,
method: 'POST',
data: data
});
},
// PUT请求
put: function(url, data) {
return this.request({
url: url,
method: 'PUT',
data: data
});
},
// DELETE请求
delete: function(url, data) {
return this.request({
url: url,
method: 'DELETE',
data: data
});
}
};
// 价格工具函数
const PriceUtils = {
/**
* 将后端返回的价格(分)转换为前端显示的价格(元)
* @param {number} price - 以分为单位的价格
* @returns {number} - 以元为单位的价格
*/
fenToYuan: function(price) {
return (price || 0) / 100;
},
/**
* 将前端输入的价格(元)转换为后端需要的价格(分)
* @param {number} price - 以元为单位的价格
* @returns {number} - 以分为单位的价格
*/
yuanToFen: function(price) {
return Math.round((price || 0) * 100);
},
/**
* 格式化价格显示(带货币符号)
* @param {number} price - 以分为单位的价格
* @param {string} currency - 货币符号,默认为¥
* @returns {string} - 格式化后的价格字符串
*/
formatPrice: function(price, currency = '¥') {
return currency + this.fenToYuan(price).toFixed(2);
}
};
// 具体业务API
const UserAPI = {
// 用户登录(邮箱密码)
login: function(email, password) {
return API.post('/users/email-login', {
email: email,
password: password
});
},
// 用户注册(邮箱密码)
register: function(email, password, nickname) {
return API.post('/users/email-register', {
email: email,
password: password,
nickname: nickname
});
},
// 获取用户信息
getProfile: function() {
return API.get('/users/profile');
},
// 更新用户信息
updateProfile: function(data) {
return API.put('/users/profile', data);
},
// 获取地址列表
getAddresses: function() {
return API.get('/users/addresses');
},
// 添加地址
addAddress: function(data) {
return API.post('/users/addresses', data);
},
// 更新地址
updateAddress: function(id, data) {
return API.put('/users/addresses/' + id, data);
},
// 删除地址
deleteAddress: function(id) {
return API.delete('/users/addresses/' + id);
}
};
const ProductAPI = {
// 获取商品列表
getList: function(params) {
return API.get('/products', params);
},
// 获取商品详情
getDetail: function(id) {
return API.get('/products/' + id);
},
// 获取热门商品
getHot: function() {
return API.get('/products/hot');
},
// 获取推荐商品
getRecommend: function() {
return API.get('/products/recommend');
},
// 搜索商品
search: function(keyword) {
return API.get('/products/search', { keyword: keyword });
},
// 获取商品评价
getReviews: function(id, params) {
return API.get('/products/' + id + '/reviews', params);
},
// 获取分类列表
getCategories: function() {
return API.get('/products/categories', { platform: 'web' });
}
};
const CartAPI = {
// 获取购物车
getCart: function() {
return API.get('/cart');
},
// 添加到购物车
addToCart: function(productId, skuId, quantity) {
return API.post('/cart', {
product_id: productId,
sku_id: skuId,
quantity: quantity
});
},
// 更新购物车数量
updateQuantity: function(productId, quantity) {
return API.put('/cart/' + productId, {
quantity: quantity
});
},
// 删除购物车商品
removeItem: function(productId) {
return API.delete('/cart/' + productId);
},
// 清空购物车
clearCart: function() {
return API.delete('/cart');
},
// 获取购物车数量
getCount: function() {
return API.get('/cart/count');
}
};
const OrderAPI = {
// 创建订单
createOrder: function(data) {
return API.post('/orders', data);
},
// 获取订单列表
getList: function(params) {
return API.get('/orders', params);
},
// 获取订单详情
getDetail: function(id) {
return API.get('/orders/' + id);
},
// 取消订单
cancelOrder: function(id, reason) {
return API.post('/orders/' + id + '/cancel', {
reason: reason
});
},
// 确认收货
confirmReceive: function(id) {
return API.post('/orders/' + id + '/confirm');
}
};
const BannerAPI = {
// 获取轮播图
getList: function() {
return API.get('/banners');
}
};
const CouponAPI = {
// 获取可用优惠券
getAvailable: function() {
return API.get('/coupons');
},
// 获取我的优惠券
getMyCoupons: function(status) {
return API.get('/coupons/user', { status: status });
},
// 领取优惠券
receive: function(id) {
return API.post('/coupons/' + id + '/receive');
}
};
const CommentAPI = {
// 获取商品评论
getProductComments: function(productId, params) {
return API.get('/comments/products/' + productId, params);
},
// 获取评论统计
getStats: function(productId) {
return API.get('/comments/products/' + productId + '/stats');
},
// 创建评论
create: function(data) {
return API.post('/comments', data);
}
};
const UploadAPI = {
// 上传图片
uploadImage: function(file) {
const formData = new FormData();
formData.append('file', file);
return new Promise((resolve, reject) => {
const token = API.getToken();
$.ajax({
url: API_CONFIG.baseURL + '/upload/image',
method: 'POST',
data: formData,
processData: false,
contentType: false,
headers: {
'Authorization': 'Bearer ' + token
},
xhrFields: {
withCredentials: true
}
})
.done(function(response) {
if (response && response.code === 200) {
resolve(response.data);
} else {
reject(response);
}
})
.fail(function(xhr, status, error) {
reject({
code: xhr.status,
message: xhr.responseJSON?.message || error,
data: xhr.responseJSON
});
});
});
}
};
const LiveStreamAPI = {
// 获取启用的投流源
getActiveLiveStreams: function() {
return API.get('/livestreams');
},
// 增加观看次数
incrementViewCount: function(id) {
return API.post('/livestreams/' + id + '/view');
}
};