diff --git a/frontend/portal/src/api/auth.js b/frontend/portal/src/api/auth.js new file mode 100644 index 0000000..77e779f --- /dev/null +++ b/frontend/portal/src/api/auth.js @@ -0,0 +1,6 @@ +import { request } from '../utils/request'; + +export const authApi = { + sendOTP: (phone) => request('/auth/otp', { method: 'POST', body: { phone } }), + login: (phone, otp) => request('/auth/login', { method: 'POST', body: { phone, otp } }), +}; diff --git a/frontend/portal/src/api/common.js b/frontend/portal/src/api/common.js new file mode 100644 index 0000000..24dd004 --- /dev/null +++ b/frontend/portal/src/api/common.js @@ -0,0 +1,10 @@ +import { request } from '../utils/request'; + +export const commonApi = { + upload: (file, type) => { + const formData = new FormData(); + formData.append('file', file); + formData.append('type', type); + return request('/upload', { method: 'POST', body: formData }); + }, +}; diff --git a/frontend/portal/src/api/content.js b/frontend/portal/src/api/content.js new file mode 100644 index 0000000..e269041 --- /dev/null +++ b/frontend/portal/src/api/content.js @@ -0,0 +1,13 @@ +import { request } from '../utils/request'; + +export const contentApi = { + list: (params) => { + const qs = new URLSearchParams(params).toString(); + return request(`/contents?${qs}`); + }, + get: (id) => request(`/contents/${id}`), + listComments: (id, page) => request(`/contents/${id}/comments?page=${page || 1}`), + createComment: (id, data) => request(`/contents/${id}/comments`, { method: 'POST', body: data }), + likeComment: (id) => request(`/comments/${id}/like`, { method: 'POST' }), + listTopics: () => request('/topics'), +}; diff --git a/frontend/portal/src/api/creator.js b/frontend/portal/src/api/creator.js new file mode 100644 index 0000000..4d293fd --- /dev/null +++ b/frontend/portal/src/api/creator.js @@ -0,0 +1,24 @@ +import { request } from '../utils/request'; + +export const creatorApi = { + apply: (data) => request('/creator/apply', { method: 'POST', body: data }), + getDashboard: () => request('/creator/dashboard'), + listContents: (params) => { + const qs = new URLSearchParams(params).toString(); + return request(`/creator/contents?${qs}`); + }, + createContent: (data) => request('/creator/contents', { method: 'POST', body: data }), + updateContent: (id, data) => request(`/creator/contents/${id}`, { method: 'PUT', body: data }), + deleteContent: (id) => request(`/creator/contents/${id}`, { method: 'DELETE' }), + listOrders: (params) => { + const qs = new URLSearchParams(params).toString(); + return request(`/creator/orders?${qs}`); + }, + refundOrder: (id, data) => request(`/creator/orders/${id}/refund`, { method: 'POST', body: data }), + getSettings: () => request('/creator/settings'), + updateSettings: (data) => request('/creator/settings', { method: 'PUT', body: data }), + listPayoutAccounts: () => request('/creator/payout-accounts'), + addPayoutAccount: (data) => request('/creator/payout-accounts', { method: 'POST', body: data }), + removePayoutAccount: (id) => request(`/creator/payout-accounts?id=${id}`, { method: 'DELETE' }), + withdraw: (data) => request('/creator/withdraw', { method: 'POST', body: data }), +}; diff --git a/frontend/portal/src/api/order.js b/frontend/portal/src/api/order.js new file mode 100644 index 0000000..7ae8b94 --- /dev/null +++ b/frontend/portal/src/api/order.js @@ -0,0 +1,7 @@ +import { request } from '../utils/request'; + +export const orderApi = { + create: (data) => request('/orders', { method: 'POST', body: data }), + pay: (id, data) => request(`/orders/${id}/pay`, { method: 'POST', body: data }), + status: (id) => request(`/orders/${id}/status`), +}; diff --git a/frontend/portal/src/api/user.js b/frontend/portal/src/api/user.js new file mode 100644 index 0000000..a85dc3a --- /dev/null +++ b/frontend/portal/src/api/user.js @@ -0,0 +1,21 @@ +import { request } from '../utils/request'; + +export const userApi = { + getMe: () => request('/me'), + updateMe: (data) => request('/me', { method: 'PUT', body: data }), + realName: (data) => request('/me/realname', { method: 'POST', body: data }), + getWallet: () => request('/me/wallet'), + recharge: (data) => request('/me/wallet/recharge', { method: 'POST', body: data }), + getOrders: (status) => request(`/me/orders?status=${status || 'all'}`), + getOrder: (id) => request(`/me/orders/${id}`), + getLibrary: () => request('/me/library'), + getFavorites: () => request('/me/favorites'), + addFavorite: (contentId) => request(`/me/favorites?content_id=${contentId}`, { method: 'POST' }), + removeFavorite: (contentId) => request(`/me/favorites/${contentId}`, { method: 'DELETE' }), + getLikes: () => request('/me/likes'), + addLike: (contentId) => request(`/me/likes?content_id=${contentId}`, { method: 'POST' }), + removeLike: (contentId) => request(`/me/likes/${contentId}`, { method: 'DELETE' }), + getNotifications: (type, page) => request(`/me/notifications?type=${type || 'all'}&page=${page || 1}`), + getFollowing: () => request('/me/following'), + getCoupons: (status) => request(`/me/coupons?status=${status || 'unused'}`), +}; diff --git a/frontend/portal/src/utils/request.js b/frontend/portal/src/utils/request.js new file mode 100644 index 0000000..9d6178b --- /dev/null +++ b/frontend/portal/src/utils/request.js @@ -0,0 +1,50 @@ +// Simple Fetch Wrapper +const BASE_URL = '/v1'; + +export async function request(endpoint, options = {}) { + const token = localStorage.getItem('token'); + + const headers = { + 'Content-Type': 'application/json', + ...options.headers, + }; + + if (token) { + headers['Authorization'] = `Bearer ${token}`; + } + + if (options.body && !(options.body instanceof FormData)) { + options.body = JSON.stringify(options.body); + } + + if (options.body instanceof FormData) { + delete headers['Content-Type']; // Let browser set boundary + } + + try { + const res = await fetch(`${BASE_URL}${endpoint}`, { + ...options, + headers + }); + + const contentType = res.headers.get("content-type"); + let data; + if (contentType && contentType.indexOf("application/json") !== -1) { + data = await res.json(); + } else { + data = await res.text(); + } + + if (!res.ok) { + // Handle errorx response { code, message, error_id } + const errorMsg = data.message || `Request failed with status ${res.status}`; + throw new Error(errorMsg); + } + + return data; + + } catch (err) { + console.error('API Request Error:', err); + throw err; + } +} diff --git a/frontend/portal/src/views/ExploreView.vue b/frontend/portal/src/views/ExploreView.vue index cfa0ba0..d8c8665 100644 --- a/frontend/portal/src/views/ExploreView.vue +++ b/frontend/portal/src/views/ExploreView.vue @@ -45,37 +45,37 @@
购买后可观看完整内容 (包含高清视频 + 完整剧本)
(白)听薛良一语,一似那金钟猛撞。
-(唱)春秋亭外风雨暴,何处悲声破寂寥。
- - -在这里,程派独特的“嗽音”运用得淋漓尽致,表现了湘灵对贫富无常的深刻感悟...
- -支持微信 / 支付宝
这段唱腔真是经典,张火丁老师的演绎太有味道了,反复听了十几遍!
-{{ comment.content }}
专注京剧程派艺术传承与推广
-