index.vue 28 KB

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