index.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. <template>
  2. <view :style="{ height: windowHeight + 'px'}">
  3. <view style="display: flex;justify-content: flex-end;">
  4. <view class="view0 step1"></view>
  5. </view>
  6. <view class="view1 step2"></view>
  7. <view class="view2 step3"></view>
  8. <view class="view3 step4"></view>
  9. <view class="view4 step5"></view>
  10. <view class="view5 step6"></view>
  11. <view style="display: flex;justify-content: flex-end;">
  12. <view class="view6 step7"></view>
  13. </view>
  14. <image src="@/static/image/white-bg.png" :style="{ height: windowHeight + 'px',width:'750rpx'}"></image>
  15. <z-paging ref="paging" v-model="dataList" @query="queryList" :style="{ height: windowHeight - 50 + 'px'}"
  16. :show-scrollbar="false">
  17. <template #top>
  18. <page-navbar>
  19. <template #navLeft>
  20. <view style="display:flex;flex-direction: row;justify-content: center; align-items: center;">
  21. <image src="@/static/icon/loacltion.png" style="width: 30rpx; height: 38rpx;"></image>
  22. <text style="margin-left:10rpx;font-size: 28rpx;">
  23. 杭州
  24. </text>
  25. <image src="@/static/icon/down.png" style="width: 30rpx; height: 16rpx;"></image>
  26. </view>
  27. </template>
  28. <template #navCenter>
  29. <view style="width: 520rpx;height: 50rpx;margin-left:126rpx;">
  30. <uv-input placeholder="“潮玩大作战” 派对季重磅开启!" border="none"
  31. :custom-style="{background:'#8BDB67',paddingLeft:'20rpx'}" shape="circle">
  32. <template #prefix>
  33. <image src="@/static/icon/fiery.png" style="width: 14px;height: 18px;"></image>
  34. </template>
  35. <template #suffix>
  36. <view style="width: 77rpx;height: 42rpx;
  37. background-color: #57A335;border-radius: 20rpx;
  38. margin-right: 5rpx;display: flex;align-items: center;justify-content: center;">
  39. <image src="@/static/icon/search.png" style="width: 32rpx;height: 32rpx;">
  40. </image>
  41. </view>
  42. </template>
  43. </uv-input>
  44. </view>
  45. </template>
  46. </page-navbar>
  47. </template>
  48. <z-paging-cell>
  49. <sortble :default-sorts="['uvSwiper','classModel','uvSwiperCard']">
  50. <template #uvSwiper>
  51. <uv-swiper :list="bannerList" :autoplay="true" circular :interval="5000" indicator
  52. indicator-mode="dot" height='380' radius='0'></uv-swiper>
  53. </template>
  54. <template #classModel>
  55. <view class="classModel">
  56. <view class="classModel-bg classModel-bg1" ref="classModel1">
  57. <image class="classModel-img" src="@/static/zhHans-text-icon/text-2.png" mode="">
  58. </image>
  59. </view>
  60. <view class="classModel-bg classModel-bg2" ref="classModel2">
  61. <image class="classModel-img" src="@/static/zhHans-text-icon/text-3.png" mode="">
  62. </image>
  63. </view>
  64. <view class="classModel-bg" ref="classModel3">
  65. <image class="classModel-img" src="@/static/zhHans-text-icon/text-4.png" mode="">
  66. </image>
  67. </view>
  68. </view>
  69. </template>
  70. <!-- <template #uvSwiperCard>
  71. <view style="background: #fff;padding: 30rpx 0;">
  72. <image src="/static/zhHans-text-icon/text-1.png" ref="classModel4"
  73. style="width: 432rpx;height: 34rpx;margin-left: 28rpx;margin-bottom: 43rpx"></image>
  74. <swiper-card :width="257" :height="290">
  75. <template v-for="(item,index) in cardList" :slot="`card-${index}`">
  76. <view style="position: relative;align-items: center;"
  77. :style="{width:`${257}rpx`,height:`${290}rpx`}">
  78. <image style="position: absolute;top:15px;" :src="item.img"
  79. :style="{width:`${257}rpx`,height:`${290}rpx`}">
  80. </image>
  81. <image style="position: absolute;" :src="item.bgimg"
  82. :style="{width:`${257}rpx`,height:`${290}rpx`}"></image>
  83. </view>
  84. </template>
  85. </swiper-card>
  86. </view>
  87. </template> -->
  88. </sortble>
  89. </z-paging-cell>
  90. <z-paging-cell>
  91. <view class="tab-nav">
  92. <view v-for="(tab, index) in tabs" :key="index"
  93. :class="['tab-item', currentTab === index ? 'active' : '']" @click="switchTab(index)">
  94. {{ tab }}
  95. </view>
  96. </view>
  97. <view v-if="currentTab === 2" class="hot-topics">
  98. <view class="hot-topics-header">
  99. <text class="hot-topics-title">热搜资讯!</text>
  100. </view>
  101. <swiper class="hot-topics-swiper" :current="currentTopicPage" @change="handleTopicPageChange">
  102. <swiper-item v-for="(page, pageIndex) in topicPages" :key="pageIndex">
  103. <view class="hot-topics-list">
  104. <view v-for="(topic, index) in page" :key="index" class="topic-item">
  105. <text class="topic-index">{{ pageIndex * 5 + index + 1 }}</text>
  106. <view class="topic-content">
  107. <view class="topic-title-row">
  108. <text class="topic-title">{{ topic.title }}</text>
  109. <text v-if="topic.isHot" class="hot-tag">HOT</text>
  110. </view>
  111. <text class="topic-participants">{{ topic.num_like }}人正在热议</text>
  112. </view>
  113. </view>
  114. </view>
  115. </swiper-item>
  116. </swiper>
  117. <view class="indicator-dots">
  118. <view v-for="i in 2" :key="i" :class="['dot', currentTopicPage === i-1 ? 'active' : '']"></view>
  119. </view>
  120. </view>
  121. <!-- 根据当前标签显示不同样式的列表 -->
  122. <!-- 关注列表 - 类似my.vue -->
  123. <view v-if="currentTab === 0" class="follow-list">
  124. <block v-if="followList.length > 0">
  125. <view class="works-list">
  126. <view class="work-item" v-for="(item, index) in followList" :key="index">
  127. <image class="work-image" :src="item.images || item.img_url" mode="aspectFill"></image>
  128. <view class="work-title">{{item.title || '作品'+index}}</view>
  129. </view>
  130. </view>
  131. </block>
  132. <view class="no-data" v-else-if="!isLoadingFollow">
  133. <text>暂无关注数据</text>
  134. </view>
  135. </view>
  136. <!-- 推荐列表 - 瀑布流样式 -->
  137. <w-waterfall v-if="currentTab === 1 && recommendList.length > 0" :data="recommendList">
  138. <template v-slot:content="{item,width}">
  139. <card :item="formatItem(item)" :width="width" :custom-style="{background:'#fff'}" textColor="#000"></card>
  140. </template>
  141. </w-waterfall>
  142. <!-- 探索列表 - 热点新闻已经有现成的热搜资讯组件,只需添加新闻列表 -->
  143. <view v-if="currentTab === 2 && newsList.length > 0" class="news-list">
  144. <view class="news-grid">
  145. <view class="news-item" v-for="(item, index) in newsList" :key="index">
  146. <image class="news-image" :src="item.img_url || item.images" mode="aspectFill"></image>
  147. <view class="news-title">{{item.title || '新闻标题'}}</view>
  148. <view class="news-footer">
  149. <view class="news-author">{{item.author || '作者'}}</view>
  150. <view class="news-views">
  151. <image src="/static/icon/icon-4.png" class="view-icon"></image>
  152. <text>{{item.num_view || '0'}}</text>
  153. </view>
  154. </view>
  155. </view>
  156. </view>
  157. </view>
  158. <view class="no-data" v-if="currentTab === 1 && recommendList.length === 0 && !isLoadingRecommend">
  159. <text>暂无推荐数据</text>
  160. </view>
  161. <view class="no-data" v-if="currentTab === 2 && newsList.length === 0 && !isLoadingNews">
  162. <text>暂无新闻数据</text>
  163. </view>
  164. </z-paging-cell>
  165. </z-paging>
  166. <tabbar-vue :tabbars="tabbars" :currentIndex="0" ref="tabbar"></tabbar-vue>
  167. <novice-guidance :step="step"></novice-guidance>
  168. </view>
  169. </template>
  170. <script>
  171. import sortble from "@/components/sortble/sortble.vue";
  172. import tabbarVue from "@/components/tabbar/tabbar.vue";
  173. import pageNavbar from "@/components/page-navbar/page-navbar.vue";
  174. import wWaterfall from "@/components/w-waterfall/w-waterfall.vue";
  175. import tabbar from "@/mixins/tabbar";
  176. import card from "@/components/card/card.vue";
  177. // import noviceGuidance from "@/components/novice-guidance/index.vue";
  178. export default {
  179. components: {
  180. sortble,
  181. tabbarVue,
  182. pageNavbar,
  183. wWaterfall,
  184. // noviceGuidance
  185. },
  186. mixins: [tabbar],
  187. data() {
  188. return {
  189. step: {
  190. name: 'workbenchSet5',
  191. guideList: [{
  192. el: '.step1',
  193. tips: '这里是第一步的介绍~',
  194. next: '下一步',
  195. }, {
  196. el: '.step2',
  197. tips: '这里是第二步的介绍~',
  198. next: '下一步',
  199. }, {
  200. el: '.step3',
  201. tips: '这里是第三步的介绍~',
  202. next: '下一步',
  203. }, {
  204. el: '.step4',
  205. tips: '这里是第四步的介绍~',
  206. next: '下一步',
  207. }, {
  208. el: '.step5',
  209. tips: '这里是第五步的介绍~',
  210. next: '下一步',
  211. }, {
  212. el: '.step6',
  213. tips: '这里是第六步的介绍~',
  214. next: '下一步',
  215. }, {
  216. el: '.step7',
  217. tips: '最后一步啦~',
  218. next: '完成',
  219. }]
  220. },
  221. windowHeight: uni.getWindowInfo().windowHeight,
  222. bannerList: [
  223. 'https://e.zhichao.art/AI_images/a_1112_10.png',
  224. 'https://e.zhichao.art/AI_images/a_1112_108.png',
  225. 'https://e.zhichao.art/AI_images/a_1112_113.png',
  226. ],
  227. cardList: [{
  228. img: '/static/img/img-1.png',
  229. bgimg: '/static/image/bg-2.png'
  230. }, {
  231. img: '/static/img/img-3.png',
  232. bgimg: '/static/image/bg-3.png'
  233. }, {
  234. img: '/static/img/img-2.png',
  235. bgimg: '/static/image/bg-1.png'
  236. }, ],
  237. list: [], // 瀑布流全部数据
  238. dataList: [],
  239. tabs: ['关注', '推荐', '探索'],
  240. currentTab: 1,
  241. currentTopicPage: 0,
  242. followList: [], // 关注列表数据
  243. recommendList: [], // 推荐列表数据
  244. exploreList: [], // 探索列表数据
  245. hotNewsList: [], // 热点新闻数据
  246. newsList: [], // 新闻列表数据
  247. followOffset: 0, // 关注列表偏移量
  248. recommendOffset: 0, // 推荐列表偏移量
  249. exploreOffset: 0, // 探索列表偏移量
  250. newsOffset: 0, // 新闻列表偏移量
  251. hasMoreFollow: true, // 是否有更多关注列表数据
  252. hasMoreRecommend: true, // 是否有更多推荐列表数据
  253. hasMoreExplore: true, // 是否有更多探索列表数据
  254. hasMoreNews: true, // 是否有更多新闻列表数据
  255. isLoadingFollow: false, // 是否正在加载关注列表
  256. isLoadingRecommend: false, // 是否正在加载推荐列表
  257. isLoadingExplore: false, // 是否正在加载探索列表
  258. isLoadingNews: false, // 是否正在加载新闻列表
  259. hotTopics: [],
  260. }
  261. },
  262. computed: {
  263. currentList() {
  264. switch (this.currentTab) {
  265. case 0:
  266. return this.followList;
  267. case 1:
  268. return this.recommendList; // 使用专门的推荐列表
  269. case 2:
  270. return this.exploreList;
  271. default:
  272. return [];
  273. }
  274. },
  275. topicPages() {
  276. const pages = [];
  277. for (let i = 0; i < this.hotTopics.length; i += 5) {
  278. pages.push(this.hotTopics.slice(i, i + 5));
  279. }
  280. return pages;
  281. }
  282. },
  283. onLoad() {
  284. let that = this;
  285. // 不在onLoad中直接加载数据,避免与z-paging组件重复请求
  286. // 让z-paging组件通过queryList方法控制数据加载
  287. },
  288. // 上拉加载更多
  289. onReachBottom() {
  290. this.loadMoreData();
  291. },
  292. // 下拉刷新数据
  293. methods: {
  294. queryList() {
  295. // 根据当前标签刷新数据
  296. switch (this.currentTab) {
  297. case 0:
  298. // 重置关注列表
  299. this.followList = [];
  300. this.followOffset = 0;
  301. this.hasMoreFollow = true;
  302. this.loadFollowList();
  303. break;
  304. case 1:
  305. // 重置推荐列表
  306. this.recommendList = [];
  307. this.recommendOffset = 0;
  308. this.hasMoreRecommend = true;
  309. this.loadRecommendList();
  310. break;
  311. case 2:
  312. // 重置热点新闻和新闻列表
  313. this.hotNewsList = [];
  314. this.newsList = [];
  315. this.newsOffset = 0;
  316. this.hasMoreNews = true;
  317. // 加载热点新闻和新闻列表
  318. this.loadHotNews();
  319. this.loadNewsList();
  320. break;
  321. }
  322. },
  323. async init() {
  324. const {
  325. data
  326. } = await this.getData();
  327. this.list.push.apply(this.list, data);
  328. },
  329. // 模拟的后端数据
  330. getData() {
  331. return new Promise((resolve) => {
  332. const imgs = [{
  333. url: 'https://e.zhichao.art/AI_images/a_1112_10.png',
  334. },
  335. {
  336. url: 'https://e.zhichao.art/AI_images/a_1112_108.png',
  337. },
  338. {
  339. url: 'https://e.zhichao.art/AI_images/a_1112_113.png',
  340. },
  341. {
  342. url: 'https://e.zhichao.art/AI_images/a_1112_13.png',
  343. },
  344. {
  345. url: 'https://e.zhichao.art/AI_images/a_1112_137.png',
  346. },
  347. {
  348. url: 'https://e.zhichao.art/AI_images/a_1112_141.png',
  349. },
  350. {
  351. url: 'https://e.zhichao.art/AI_images/a_1114__562.png',
  352. },
  353. {
  354. url: 'https://e.zhichao.art/AI_images/a_1114__568.png',
  355. },
  356. {
  357. url: 'https://e.zhichao.art/AI_images/a_1114__569.png',
  358. },
  359. {
  360. url: 'https://e.zhichao.art/AI_images/a_1114__570.png',
  361. },
  362. {
  363. url: 'https://e.zhichao.art/AI_images/a_1114__571.png',
  364. },
  365. {
  366. url: 'https://e.zhichao.art/AI_images/a_1114__575.png',
  367. },
  368. ];
  369. let list = [];
  370. const doFn = (i) => {
  371. const randomIndex = Math.floor(Math.random() * 10);
  372. return {
  373. allowEdit: i == 0,
  374. image: imgs[randomIndex].url,
  375. w: imgs[randomIndex].width,
  376. h: imgs[randomIndex].height,
  377. title: i % 2 == 0 ? `玛丽` : `凌音`,
  378. desc: i % 2 == 0 ?
  379. `欢迎使用uv-ui,uni-app生态专用的UI框架` : `开发者编写一套代码, 可发布到iOS、Android、H5、以及各种小程序`
  380. }
  381. };
  382. // 模拟异步
  383. setTimeout(() => {
  384. for (let i = 0; i < 20; i++) {
  385. list.push(doFn(i));
  386. }
  387. resolve({
  388. data: list
  389. });
  390. }, 200)
  391. })
  392. },
  393. switchTab(index) {
  394. this.currentTab = index;
  395. // 根据需要加载对应标签的数据
  396. this.loadTabData(index);
  397. },
  398. loadTabData(index) {
  399. // 这里添加加载不同标签数据的逻辑
  400. switch (index) {
  401. case 0:
  402. if (!this.followList.length) {
  403. this.loadFollowList();
  404. }
  405. break;
  406. case 1:
  407. if (!this.recommendList.length) {
  408. this.loadRecommendList();
  409. }
  410. break;
  411. case 2:
  412. // 加载热点新闻和新闻列表
  413. if (!this.hotNewsList.length) {
  414. this.loadHotNews();
  415. }
  416. if (!this.newsList.length) {
  417. this.loadNewsList();
  418. }
  419. break;
  420. }
  421. },
  422. loadFollowList() {
  423. if (this.isLoadingFollow) return;
  424. this.isLoadingFollow = true;
  425. uni.request({
  426. url: this.$apiHost + '/Work/getlist',
  427. data: {
  428. uuid: getApp().globalData.uuid,
  429. skey: getApp().globalData.skey,
  430. type: 'attention', // 关注列表
  431. offset: this.followOffset
  432. },
  433. header: {
  434. "content-type": "application/json",
  435. 'sign': getApp().globalData.headerSign
  436. },
  437. success: (res) => {
  438. console.log("关注列表数据:", res.data);
  439. // 确保在任何情况下都完成加载
  440. if (res.data.success == 'yes' && res.data.list && res.data.list.length > 0) {
  441. // 只有当列表有数据时才追加
  442. this.followList = [...this.followList, ...res.data.list];
  443. this.followOffset += res.data.list.length;
  444. if (res.data.list.length < 20) {
  445. this.hasMoreFollow = false;
  446. }
  447. } else {
  448. // 如果列表为空,确保标记没有更多数据
  449. this.hasMoreFollow = false;
  450. }
  451. // 无论是否有数据,都需要通知z-paging组件完成刷新
  452. if (this.$refs.paging) {
  453. this.$refs.paging.complete(this.followList);
  454. }
  455. },
  456. complete: () => {
  457. this.isLoadingFollow = false;
  458. },
  459. fail: (e) => {
  460. console.log("请求关注列表失败:", e);
  461. this.isLoadingFollow = false;
  462. // 加载失败时也要通知组件完成
  463. if (this.$refs.paging) {
  464. this.$refs.paging.complete(false);
  465. }
  466. }
  467. });
  468. },
  469. loadRecommendList() {
  470. if (this.isLoadingRecommend) return;
  471. this.isLoadingRecommend = true;
  472. uni.request({
  473. url: this.$apiHost + '/Work/getlist',
  474. data: {
  475. uuid: getApp().globalData.uuid,
  476. skey: getApp().globalData.skey,
  477. type: 'recommend', // 推荐列表
  478. offset: this.recommendOffset
  479. },
  480. header: {
  481. "content-type": "application/json",
  482. 'sign': getApp().globalData.headerSign
  483. },
  484. success: (res) => {
  485. console.log("推荐列表数据:", res.data);
  486. if (res.data.success == 'yes' && res.data.list && res.data.list.length > 0) {
  487. this.recommendList = [...this.recommendList, ...res.data.list];
  488. this.recommendOffset += res.data.list.length;
  489. if (res.data.list.length < 20) {
  490. this.hasMoreRecommend = false;
  491. }
  492. } else {
  493. this.hasMoreRecommend = false;
  494. }
  495. // 无论是否有数据,都需要通知z-paging组件完成刷新
  496. if (this.$refs.paging) {
  497. this.$refs.paging.complete(this.recommendList);
  498. }
  499. },
  500. complete: () => {
  501. this.isLoadingRecommend = false;
  502. },
  503. fail: (e) => {
  504. console.log("请求推荐列表失败:", e);
  505. this.isLoadingRecommend = false;
  506. // 加载失败时也要通知组件完成
  507. if (this.$refs.paging) {
  508. this.$refs.paging.complete(false);
  509. }
  510. }
  511. });
  512. },
  513. loadHotNews() {
  514. if (this.isLoadingExplore) return;
  515. this.isLoadingExplore = true;
  516. uni.request({
  517. url: this.$apiHost + '/Article/getlist',
  518. data: {
  519. uuid: getApp().globalData.uuid,
  520. skey: getApp().globalData.skey,
  521. type: 'hot' // 热点新闻
  522. },
  523. header: {
  524. "content-type": "application/json",
  525. 'sign': getApp().globalData.headerSign
  526. },
  527. success: (res) => {
  528. console.log("热点新闻数据:", res.data);
  529. if (res.data.success == 'yes' && res.data.list && res.data.list.length > 0) {
  530. this.hotNewsList = res.data.list;
  531. // 如果有热点新闻数据,更新热搜资讯
  532. if (this.hotNewsList.length > 0) {
  533. // 将API返回的热点新闻转换为热搜资讯格式
  534. this.hotTopics = this.hotNewsList.map((item, index) => {
  535. return {
  536. title: item.title || '热门话题',
  537. num_like: item.num_like || 0,
  538. isHot: index % 2 === 0 // 偶数索引的设为热点
  539. };
  540. });
  541. }
  542. }
  543. },
  544. complete: () => {
  545. this.isLoadingExplore = false;
  546. },
  547. fail: (e) => {
  548. console.log("请求热点新闻失败:", e);
  549. this.isLoadingExplore = false;
  550. }
  551. });
  552. },
  553. loadNewsList() {
  554. if (this.isLoadingNews) return;
  555. this.isLoadingNews = true;
  556. uni.request({
  557. url: this.$apiHost + '/Article/getlist',
  558. data: {
  559. uuid: getApp().globalData.uuid,
  560. skey: getApp().globalData.skey,
  561. type: 'list', // 新闻列表
  562. offset: this.newsOffset
  563. },
  564. header: {
  565. "content-type": "application/json",
  566. 'sign': getApp().globalData.headerSign
  567. },
  568. success: (res) => {
  569. console.log("新闻列表数据:", res.data);
  570. if (res.data.success == 'yes' && res.data.list && res.data.list.length > 0) {
  571. this.newsList = [...this.newsList, ...res.data.list];
  572. this.newsOffset += res.data.list.length;
  573. if (res.data.list.length < 20) {
  574. this.hasMoreNews = false;
  575. }
  576. } else {
  577. this.hasMoreNews = false;
  578. }
  579. // 无论是否有数据,都需要通知z-paging组件完成刷新
  580. if (this.$refs.paging) {
  581. this.$refs.paging.complete(this.newsList);
  582. }
  583. },
  584. complete: () => {
  585. this.isLoadingNews = false;
  586. },
  587. fail: (e) => {
  588. console.log("请求新闻列表失败:", e);
  589. this.isLoadingNews = false;
  590. // 加载失败时也要通知组件完成
  591. if (this.$refs.paging) {
  592. this.$refs.paging.complete(false);
  593. }
  594. }
  595. });
  596. },
  597. loadMoreData() {
  598. // 根据当前标签加载更多数据
  599. switch (this.currentTab) {
  600. case 0:
  601. if (this.hasMoreFollow && !this.isLoadingFollow) {
  602. this.loadFollowList();
  603. }
  604. break;
  605. case 1:
  606. if (this.hasMoreRecommend && !this.isLoadingRecommend) {
  607. this.loadRecommendList();
  608. }
  609. break;
  610. case 2:
  611. if (this.hasMoreNews && !this.isLoadingNews) {
  612. this.loadNewsList();
  613. }
  614. break;
  615. }
  616. },
  617. handleTopicPageChange(e) {
  618. this.currentTopicPage = e.detail.current;
  619. },
  620. formatItem(item) {
  621. // 处理接口返回的数据,使其适配card组件
  622. return {
  623. allowEdit: false,
  624. image: item.images || item.img_url || item.image, // 优先使用images字段
  625. w: item.width,
  626. h: item.height,
  627. title: item.title || '',
  628. desc: item.desc || ''
  629. }
  630. },
  631. }
  632. }
  633. </script>
  634. <style lang="scss">
  635. .classModel {
  636. width: 750rpx;
  637. height: 110rpx;
  638. // #ifndef APP-NVUE
  639. display: flex;
  640. // #endif
  641. // #ifdef APP-NVUE
  642. flex-direction: row;
  643. // #endif
  644. justify-content: space-around;
  645. margin-bottom: 20rpx;
  646. .classModel-bg {
  647. width: 210rpx;
  648. height: 90rpx;
  649. background-color: #3F4141;
  650. border-radius: 60rpx;
  651. box-shadow: 3px 3px 2px rgba(174, 230, 93, 1);
  652. .classModel-img {
  653. width: 175rpx;
  654. height: 75rpx;
  655. }
  656. }
  657. }
  658. .tab-nav {
  659. display: flex;
  660. justify-content: center;
  661. padding: 20rpx 0;
  662. background: #161616;
  663. .tab-item {
  664. padding: 0 30rpx;
  665. color: #808080;
  666. font-size: 28rpx;
  667. &.active {
  668. color: #ffffff;
  669. font-weight: bold;
  670. }
  671. }
  672. }
  673. .hot-topics {
  674. padding: 20rpx;
  675. background: #28292D;
  676. margin: 20rpx;
  677. border-radius: 16rpx;
  678. .hot-topics-header {
  679. margin-bottom: 20rpx;
  680. .hot-topics-title {
  681. font-size: 32rpx;
  682. font-weight: bold;
  683. color: #ffffff;
  684. }
  685. }
  686. .hot-topics-swiper {
  687. height: 400rpx; // Adjust this value based on your content
  688. }
  689. .hot-topics-list {
  690. padding: 10rpx 0;
  691. }
  692. .topic-item {
  693. display: flex;
  694. align-items: center;
  695. padding: 15rpx 0;
  696. .topic-index {
  697. width: 40rpx;
  698. color: #808080;
  699. text-align: center;
  700. flex-shrink: 0;
  701. }
  702. .topic-content {
  703. flex: 1;
  704. width: 0; /* 重要:确保flex子项不会超过容器宽度 */
  705. overflow: hidden;
  706. .topic-title-row {
  707. display: flex;
  708. align-items: center;
  709. width: 100%;
  710. .topic-title {
  711. color: #ffffff;
  712. font-size: 28rpx;
  713. white-space: nowrap;
  714. overflow: hidden;
  715. text-overflow: ellipsis;
  716. flex: 1;
  717. width: 0; /* 重要:确保flex子项不会超过容器宽度 */
  718. }
  719. .hot-tag {
  720. margin-left: 10rpx;
  721. padding: 4rpx 10rpx;
  722. background: #FF4B4B;
  723. color: #ffffff;
  724. font-size: 20rpx;
  725. border-radius: 8rpx;
  726. flex-shrink: 0;
  727. }
  728. }
  729. .topic-participants {
  730. font-size: 24rpx;
  731. color: #808080;
  732. margin-top: 6rpx;
  733. }
  734. }
  735. }
  736. .indicator-dots {
  737. display: flex;
  738. justify-content: center;
  739. margin-top: 20rpx;
  740. .dot {
  741. width: 12rpx;
  742. height: 12rpx;
  743. border-radius: 50%;
  744. background: #808080;
  745. margin: 0 6rpx;
  746. &.active {
  747. background: #ffffff;
  748. }
  749. }
  750. }
  751. }
  752. .follow-list {
  753. padding: 20rpx;
  754. background: #161616;
  755. margin: 0rpx;
  756. border-radius: 0rpx;
  757. .works-list {
  758. display: flex;
  759. flex-wrap: wrap;
  760. padding: 10rpx;
  761. .work-item {
  762. width: 48%;
  763. margin: 1%;
  764. margin-bottom: 20rpx;
  765. .work-image {
  766. width: 100%;
  767. aspect-ratio: 1;
  768. border-radius: 12rpx;
  769. }
  770. .work-title {
  771. font-size: 28rpx;
  772. color: #ffffff;
  773. margin-top: 10rpx;
  774. padding: 0 10rpx;
  775. white-space: nowrap;
  776. overflow: hidden;
  777. text-overflow: ellipsis;
  778. }
  779. }
  780. }
  781. .no-data {
  782. display: flex;
  783. flex-direction: column;
  784. align-items: center;
  785. justify-content: center;
  786. padding: 60rpx 0;
  787. text {
  788. color: #808080;
  789. font-size: 28rpx;
  790. }
  791. }
  792. }
  793. .no-data {
  794. text-align: center;
  795. padding: 40rpx 0;
  796. color: #808080;
  797. font-size: 28rpx;
  798. }
  799. .news-list {
  800. padding: 20rpx;
  801. background: #161616;
  802. .news-grid {
  803. display: flex;
  804. flex-wrap: wrap;
  805. justify-content: space-between;
  806. .news-item {
  807. width: 48%;
  808. margin-bottom: 30rpx;
  809. background: #28292D;
  810. border-radius: 12rpx;
  811. overflow: hidden;
  812. .news-image {
  813. width: 100%;
  814. aspect-ratio: 1;
  815. height: auto;
  816. border-radius: 12rpx 12rpx 0 0;
  817. }
  818. .news-title {
  819. font-size: 28rpx;
  820. color: #ffffff;
  821. padding: 15rpx;
  822. white-space: nowrap;
  823. overflow: hidden;
  824. text-overflow: ellipsis;
  825. height: 60rpx;
  826. line-height: 60rpx;
  827. }
  828. .news-footer {
  829. display: flex;
  830. justify-content: space-between;
  831. align-items: center;
  832. padding: 0 15rpx 15rpx;
  833. .news-author {
  834. font-size: 24rpx;
  835. color: #808080;
  836. max-width: 60%;
  837. white-space: nowrap;
  838. overflow: hidden;
  839. text-overflow: ellipsis;
  840. }
  841. .news-views {
  842. display: flex;
  843. align-items: center;
  844. font-size: 24rpx;
  845. color: #808080;
  846. .view-icon {
  847. width: 26rpx;
  848. height: 18rpx;
  849. margin-right: 6rpx;
  850. }
  851. }
  852. }
  853. }
  854. }
  855. }
  856. </style>