|
|
@@ -40,18 +40,21 @@
|
|
40
|
40
|
|
|
41
|
41
|
<!-- 热门推荐 -->
|
|
42
|
42
|
<view v-if="hotNovels.length > 0" class="section">
|
|
|
43
|
+ <!-- ... -->
|
|
|
44
|
+ </view>
|
|
|
45
|
+ <view v-else class="section">
|
|
43
|
46
|
<view class="section-header">
|
|
44
|
|
- <text class="section-title">热门推荐</text>
|
|
|
47
|
+ <text class="section-title">热门推荐(演示数据)</text>
|
|
45
|
48
|
<text class="section-more" @click="goMore">更多 ></text>
|
|
46
|
49
|
</view>
|
|
47
|
50
|
<scroll-view scroll-x class="hot-list">
|
|
48
|
51
|
<view
|
|
49
|
|
- v-for="novel in hotNovels"
|
|
|
52
|
+ v-for="novel in demoHotNovels"
|
|
50
|
53
|
:key="novel.id"
|
|
51
|
54
|
class="hot-item"
|
|
52
|
55
|
@click="openNovel(novel)"
|
|
53
|
56
|
>
|
|
54
|
|
- <image :src="getCoverUrl(novel.cover)" class="hot-cover" />
|
|
|
57
|
+ <image :src="novel.cover" class="hot-cover" />
|
|
55
|
58
|
<text class="hot-title">{{ novel.title }}</text>
|
|
56
|
59
|
</view>
|
|
57
|
60
|
</scroll-view>
|
|
|
@@ -59,19 +62,22 @@
|
|
59
|
62
|
|
|
60
|
63
|
<!-- 分类小说列表 -->
|
|
61
|
64
|
<view v-if="novels.length > 0" class="section">
|
|
|
65
|
+ <!-- ... -->
|
|
|
66
|
+ </view>
|
|
|
67
|
+ <view v-else class="section">
|
|
62
|
68
|
<view class="section-header">
|
|
63
|
|
- <text class="section-title">{{ currentCategoryName }}作品</text>
|
|
|
69
|
+ <text class="section-title">小说列表(演示数据)</text>
|
|
64
|
70
|
</view>
|
|
65
|
71
|
<view class="novel-grid">
|
|
66
|
72
|
<view
|
|
67
|
|
- v-for="(novel, index) in novels"
|
|
68
|
|
- :key="index"
|
|
|
73
|
+ v-for="novel in demoNovels"
|
|
|
74
|
+ :key="novel.id"
|
|
69
|
75
|
class="novel-item"
|
|
70
|
76
|
@click="openNovel(novel)"
|
|
71
|
77
|
>
|
|
72
|
|
- <image :src="getCoverUrl(novel.cover)" class="novel-cover" />
|
|
73
|
|
- <text class="novel-title">{{ novel.title || '未知标题' }}</text>
|
|
74
|
|
- <text class="novel-author">{{ novel.author || '未知作者' }}</text>
|
|
|
78
|
+ <image :src="novel.cover" class="novel-cover" />
|
|
|
79
|
+ <text class="novel-title">{{ novel.title }}</text>
|
|
|
80
|
+ <text class="novel-author">{{ novel.author }}</text>
|
|
75
|
81
|
</view>
|
|
76
|
82
|
</view>
|
|
77
|
83
|
</view>
|
|
|
@@ -103,16 +109,49 @@ export default {
|
|
103
|
109
|
novels: [],
|
|
104
|
110
|
loading: true,
|
|
105
|
111
|
error: null,
|
|
106
|
|
- currentCategoryName: '全部'
|
|
|
112
|
+ currentCategoryName: '全部',
|
|
|
113
|
+
|
|
|
114
|
+ // 临时解决方案 - 模拟数据
|
|
|
115
|
+ mockHotNovels: [
|
|
|
116
|
+ { id: 1, title: '总裁的替身前妻', cover: '/static/demo-cover1.jpg' },
|
|
|
117
|
+ { id: 2, title: '神医毒妃', cover: '/static/demo-cover2.jpg' },
|
|
|
118
|
+ { id: 3, title: '穿越之王妃逆袭', cover: '/static/demo-cover3.jpg' }
|
|
|
119
|
+ ],
|
|
|
120
|
+ mockNovels: [
|
|
|
121
|
+ { id: 4, title: '都市最强赘婿', author: '网络作家', cover: '/static/demo-cover4.jpg' },
|
|
|
122
|
+ { id: 5, title: '修仙归来', author: '仙侠迷', cover: '/static/demo-cover5.jpg' },
|
|
|
123
|
+ { id: 6, title: '校园纯爱物语', author: '青春校园', cover: '/static/demo-cover6.jpg' }
|
|
|
124
|
+ ]
|
|
107
|
125
|
}
|
|
108
|
126
|
},
|
|
109
|
|
- async mounted() {
|
|
110
|
|
- await this.initData();
|
|
|
127
|
+ mounted() {
|
|
|
128
|
+ console.log('$http available in component:', typeof this.$http.get === 'function');
|
|
|
129
|
+
|
|
|
130
|
+ // 确保所有方法都已绑定
|
|
|
131
|
+ console.log('loadCategories:', typeof this.loadCategories);
|
|
|
132
|
+ console.log('loadHotNovels:', typeof this.loadHotNovels);
|
|
|
133
|
+ console.log('loadNovels:', typeof this.loadNovels);
|
|
|
134
|
+ console.log('loadAds:', typeof this.loadAds);
|
|
|
135
|
+
|
|
|
136
|
+ this.initData();
|
|
111
|
137
|
},
|
|
112
|
138
|
methods: {
|
|
113
|
139
|
async initData() {
|
|
|
140
|
+ // 确保所有方法都已绑定
|
|
|
141
|
+ if (
|
|
|
142
|
+ typeof this.loadCategories !== 'function' ||
|
|
|
143
|
+ typeof this.loadHotNovels !== 'function' ||
|
|
|
144
|
+ typeof this.loadNovels !== 'function' ||
|
|
|
145
|
+ typeof this.loadAds !== 'function'
|
|
|
146
|
+ ) {
|
|
|
147
|
+ console.error('一个或多个方法未绑定!');
|
|
|
148
|
+ this.error = '系统初始化失败,请刷新页面';
|
|
|
149
|
+ this.loading = false;
|
|
|
150
|
+ return;
|
|
|
151
|
+ }
|
|
|
152
|
+
|
|
114
|
153
|
try {
|
|
115
|
|
- // 顺序加载数据,避免并行请求冲突
|
|
|
154
|
+ // 顺序加载数据
|
|
116
|
155
|
await this.loadCategories();
|
|
117
|
156
|
await this.loadHotNovels();
|
|
118
|
157
|
await this.loadNovels();
|
|
|
@@ -124,91 +163,74 @@ export default {
|
|
124
|
163
|
this.loading = false;
|
|
125
|
164
|
}
|
|
126
|
165
|
},
|
|
127
|
|
-
|
|
128
|
|
- // 加载广告
|
|
129
|
|
- async loadAds() {
|
|
130
|
|
- try {
|
|
131
|
|
- const [topRes, bottomRes] = await Promise.all([
|
|
132
|
|
- this.$http.get('/java-api/ad/position?code=TOP_BANNER'),
|
|
133
|
|
- this.$http.get('/java-api/ad/position?code=BOTTOM_BANNER')
|
|
134
|
|
- ]);
|
|
135
|
|
-
|
|
136
|
|
- this.topAds = topRes?.data || topRes || [];
|
|
137
|
|
- this.bottomAds = bottomRes?.data || bottomRes || [];
|
|
138
|
|
- } catch (e) {
|
|
139
|
|
- console.error('加载广告失败', e);
|
|
140
|
|
- }
|
|
141
|
|
- },
|
|
142
|
|
-
|
|
143
|
|
- // 加载分类
|
|
|
166
|
+ // 加载分类
|
|
144
|
167
|
async loadCategories() {
|
|
145
|
168
|
try {
|
|
146
|
|
- const res = await this.$http.get('/category/tree');
|
|
147
|
|
- // 确保有"全部"选项
|
|
|
169
|
+ const res = await this.$http.get('/java-api/category/tree');
|
|
148
|
170
|
this.categories = res?.data ? [{ id: 0, name: '全部' }, ...res.data] : [];
|
|
149
|
171
|
} catch (e) {
|
|
150
|
172
|
console.error('加载分类失败', e);
|
|
151
|
173
|
this.categories = [{ id: 0, name: '全部' }];
|
|
152
|
174
|
}
|
|
153
|
175
|
},
|
|
154
|
|
-
|
|
155
|
176
|
// 加载热门小说
|
|
156
|
177
|
async loadHotNovels() {
|
|
157
|
178
|
try {
|
|
158
|
|
- const res = await this.$http.get('/api/novel/hot');
|
|
|
179
|
+ const res = await this.$http.get('/novel/hot');
|
|
159
|
180
|
|
|
160
|
|
- // 处理不同API响应格式
|
|
|
181
|
+ // 处理响应
|
|
161
|
182
|
if (res?.data?.rows) {
|
|
162
|
183
|
this.hotNovels = res.data.rows;
|
|
163
|
184
|
} else if (Array.isArray(res?.data)) {
|
|
164
|
185
|
this.hotNovels = res.data;
|
|
165
|
|
- } else if (Array.isArray(res)) {
|
|
166
|
|
- this.hotNovels = res;
|
|
167
|
186
|
} else {
|
|
168
|
187
|
console.warn('热门小说API返回格式未知', res);
|
|
169
|
|
- this.hotNovels = [];
|
|
|
188
|
+ this.hotNovels = this.mockHotNovels; // 使用模拟数据
|
|
170
|
189
|
}
|
|
171
|
190
|
} catch (e) {
|
|
172
|
191
|
console.error('加载热门小说失败', e);
|
|
173
|
|
- this.hotNovels = [];
|
|
|
192
|
+ this.hotNovels = this.mockHotNovels; // 使用模拟数据
|
|
174
|
193
|
}
|
|
175
|
194
|
},
|
|
176
|
|
-
|
|
177
|
195
|
// 加载小说列表
|
|
178
|
196
|
async loadNovels() {
|
|
179
|
197
|
this.loading = true;
|
|
180
|
198
|
this.error = null;
|
|
181
|
199
|
try {
|
|
182
|
|
- const res = await this.$http.get('/api/novel/list');
|
|
183
|
|
- console.log('小说列表API响应:', res);
|
|
|
200
|
+ const res = await this.$http.get('/novel/list');
|
|
184
|
201
|
|
|
185
|
|
- // 处理不同API响应格式
|
|
|
202
|
+ // 处理响应
|
|
186
|
203
|
if (res?.data?.rows) {
|
|
187
|
204
|
this.novels = res.data.rows;
|
|
188
|
205
|
} else if (Array.isArray(res?.data)) {
|
|
189
|
206
|
this.novels = res.data;
|
|
190
|
|
- } else if (res?.data?.list) {
|
|
191
|
|
- this.novels = res.data.list;
|
|
192
|
|
- } else if (Array.isArray(res)) {
|
|
193
|
|
- this.novels = res;
|
|
194
|
207
|
} else {
|
|
195
|
208
|
console.warn('小说列表API返回格式未知', res);
|
|
196
|
|
- this.novels = [];
|
|
197
|
|
- this.error = '数据格式错误';
|
|
|
209
|
+ this.novels = this.mockNovels; // 使用模拟数据
|
|
198
|
210
|
}
|
|
199
|
211
|
} catch (e) {
|
|
200
|
212
|
console.error('加载小说失败', e);
|
|
201
|
213
|
this.error = '加载失败,请重试';
|
|
202
|
|
- uni.showToast({
|
|
203
|
|
- title: '加载失败,请重试',
|
|
204
|
|
- icon: 'none'
|
|
205
|
|
- });
|
|
206
|
|
- this.novels = [];
|
|
|
214
|
+ this.novels = this.mockNovels; // 使用模拟数据
|
|
207
|
215
|
} finally {
|
|
208
|
216
|
this.loading = false;
|
|
209
|
217
|
}
|
|
210
|
218
|
},
|
|
211
|
219
|
|
|
|
220
|
+ // 加载广告
|
|
|
221
|
+ async loadAds() {
|
|
|
222
|
+ try {
|
|
|
223
|
+ const [topRes, bottomRes] = await Promise.all([
|
|
|
224
|
+ this.$http.get('/java-api/ad/position?code=TOP_BANNER'),
|
|
|
225
|
+ this.$http.get('/java-api/ad/position?code=BOTTOM_BANNER')
|
|
|
226
|
+ ]);
|
|
|
227
|
+
|
|
|
228
|
+ this.topAds = topRes?.data || topRes || [];
|
|
|
229
|
+ this.bottomAds = bottomRes?.data || bottomRes || [];
|
|
|
230
|
+ } catch (e) {
|
|
|
231
|
+ console.error('加载广告失败', e);
|
|
|
232
|
+ }
|
|
|
233
|
+ },
|
|
212
|
234
|
// 封面URL处理
|
|
213
|
235
|
getCoverUrl(cover) {
|
|
214
|
236
|
if (!cover) return '/static/default-cover.jpg';
|