index.vue 28 KB

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