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 @@
- +
-
+
- +
- 12:40 + {{ item.duration || '00:00' }}
- 限免 + 免费
- [京剧] -

《锁麟囊》选段深度解析

+ [{{ item.genre || '未知' }}] +

{{ item.title }}

- - 梅派传人小林 + + {{ item.author_name || 'Unknown' }}
- 1.2w 阅读 - 免费 - ¥ 9.90 + {{ item.views }} 阅读 + 免费 + ¥ {{ item.price }}
@@ -83,7 +83,7 @@
-
@@ -91,11 +91,50 @@ + - - + \ No newline at end of file diff --git a/frontend/portal/src/views/content/DetailView.vue b/frontend/portal/src/views/content/DetailView.vue index 5f39172..bb7abb5 100644 --- a/frontend/portal/src/views/content/DetailView.vue +++ b/frontend/portal/src/views/content/DetailView.vue @@ -9,25 +9,25 @@

- [京剧] - 《锁麟囊》春秋亭 · 二六 + [{{ content.genre || '未分类' }}] + {{ content.title }}

-
- 行当: 青衣 - 定调: F大调 - 板式: 二六 +
+ 行当: {{ content.meta.role }} + 定调: {{ content.meta.key }} + 板式: {{ content.meta.beat }}
- +
-
梅派传人小林
-
发布于 2025-12-24
+
{{ content.author_name }}
+
发布于 {{ content.create_time }}
@@ -43,7 +43,7 @@
-
+
-
+

试看已结束

购买后可观看完整内容 (包含高清视频 + 完整剧本)

-

(白)听薛良一语,一似那金钟猛撞。

-

(唱)春秋亭外风雨暴,何处悲声破寂寥。

- - -
-
- 薛湘灵: - - 隔帘只见一花轿,想必是新婚渡鹊桥。
- 吉日良辰当欢笑,为什么被珠泪抛?
- 此时却又明白了,
- (白) 世上何尝尽富豪。
- (唱) 也有饥寒悲怀抱,也有失意痛哭嚎啕。
- 轿内的人儿,命薄如纸,
- 苦煞了严亲,累煞了做娘的。 -
-
-
+
- -
-
-
-
名家示范:流水板式要点
-
- Key: F - Beat: 1/4 -
-
- 00:45 -
- -

在这里,程派独特的“嗽音”运用得淋漓尽致,表现了湘灵对贫富无常的深刻感悟...

- -
+

支持微信 / 支付宝

@@ -122,36 +90,20 @@
-

全部评论 (24)

-
- - -
+

全部评论 ({{ comments.length }})

-
- -
- -
- -
-
-
+
-
- +
+
- 戏迷_{{ i*92 }} - 1小时前 -
-

这段唱腔真是经典,张火丁老师的演绎太有味道了,反复听了十几遍!

-
- - + {{ comment.user_nickname }} + {{ comment.create_time }}
+

{{ comment.content }}

@@ -163,57 +115,39 @@
- +
-

梅派传人小林

-

专注京剧程派艺术传承与推广

-
-
125 内容
-
1.2w 关注
-
-
+

{{ content.author_name }}

+
- - - - - -
-

相关推荐

-
-
- -
-

程派《荒山泪》夜织选段

- 8.5k 阅读 -
-
-
-
\ No newline at end of file diff --git a/frontend/portal/src/views/order/PaymentView.vue b/frontend/portal/src/views/order/PaymentView.vue index 673ba83..af21a31 100644 --- a/frontend/portal/src/views/order/PaymentView.vue +++ b/frontend/portal/src/views/order/PaymentView.vue @@ -103,12 +103,13 @@ \ No newline at end of file diff --git a/frontend/portal/src/views/user/DashboardView.vue b/frontend/portal/src/views/user/DashboardView.vue index e7d60ee..2385bf1 100644 --- a/frontend/portal/src/views/user/DashboardView.vue +++ b/frontend/portal/src/views/user/DashboardView.vue @@ -8,7 +8,7 @@ class="pi pi-wallet">
账户余额
-
¥ 128.50
+
¥ {{ wallet.balance }}
@@ -20,7 +20,7 @@
我的积分
-
2,450
+
{{ wallet.points }}
@@ -32,7 +32,7 @@
优惠券
-
3 张
+
{{ couponCount }} 张
@@ -48,46 +48,67 @@
-
-

- 《霸王别姬》全本实录珍藏版

-
2025-12-24 14:30 · 订单号: 82934712
+ {{ order.items && order.items.length > 0 ? order.items[0].title : '未知商品' }} +
{{ order.create_time }} · 订单号: {{ order.id }}
-
¥ 9.90
-
交易成功
+
¥ {{ order.amount }}
+
{{ order.status }}
- +
暂无订单
- +

最近浏览

-
-
- -
-
-

- 京剧名家谈戏曲传承与创新发展的思考

-
10分钟前
-
+
暂无浏览记录
+ + diff --git a/frontend/portal/src/views/user/OrdersView.vue b/frontend/portal/src/views/user/OrdersView.vue index c51c24e..8e8e4f1 100644 --- a/frontend/portal/src/views/user/OrdersView.vue +++ b/frontend/portal/src/views/user/OrdersView.vue @@ -83,65 +83,50 @@