index.vue 28 KB

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