my.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. <template>
  2. <view class="page">
  3. <!-- 用于计算主题色的隐藏Canvas -->
  4. <view style="position: absolute; top: -9999px; left: -9999px;">
  5. <canvas canvas-id="themeCanvas" id="themeCanvas" style="width: 100px; height: 100px;"></canvas>
  6. </view>
  7. <view class="topBody">
  8. <!-- <view class="header" :class="{ 'header-isvip': !isRecharge }"> -->
  9. <view class="header"
  10. :style="{ backgroundImage: `url(${bgImage || '../../static/me/theme3.jpg'})`, marginBottom: labelBoxHeight < 45 ? '-80rpx' : '-40rpx' }">
  11. <view class="header-box" :style="headerBoxStyle">
  12. <view class="reserveASeat"></view>
  13. <view class="benner-box">
  14. <view class="setUp-box">
  15. <view class="my-box">我的</view>
  16. <view class="settingBtn-box">
  17. <image @click="clickShare()" src="@/static/me/fenxiang.png" mode=""></image>
  18. <image src="@/static/me/shezhi.png" mode="" @click="navigateToSettings">
  19. </image>
  20. </view>
  21. </view>
  22. <view class="profilePicture-box">
  23. <CircleAvatar class="avator" @click="goPage('/pages/my/editInfo')" :src="myinfo.avator">
  24. </CircleAvatar>
  25. <view class="profilePicture-box-right" @click="goPage('/pages/my/creativeExpert')">
  26. <view class="one-omit">{{ myinfo.nickname }}</view>
  27. <image v-if="myinfo.my_level || myinfo.my_level == 0"
  28. :src="`../../static/icon/level_${myinfo.my_level}.png`" mode="widthFix"
  29. class="level-icon" />
  30. </view>
  31. </view>
  32. <view class="intro_row" @click="goPage('/pages/my/editInfo')">
  33. <block v-if="myinfo.content == ''">
  34. <text class="intro_text two-omit">添加简介</text>
  35. <image src="@/static/me/xiugai.png" mode="widthFix" class="add_icon">
  36. </image>
  37. </block>
  38. <uv-text color="#fff" v-else :text="formatText(myinfo.content)" class="intro_text two-omit">
  39. </uv-text>
  40. </view>
  41. <view class="label-box" id="labelBox" @click="goPage('/pages/my/editInfo')">
  42. <view class="label-item sex-item">
  43. <image src="../../static/icon/wd_icon_nv.png" mode="widthFix" v-if="myinfo.sex_id == 2">
  44. </image>
  45. <image src="../../static/icon/wd_icon_nan.png" mode="widthFix" v-else></image>
  46. </view>
  47. <view class="label-item" v-for="(item, index) in aihao_tags" :key="index + item">
  48. {{ item }}
  49. </view>
  50. </view>
  51. <view class="follow_info" @click="navigateToFollow">
  52. <view class="follow-box">
  53. <view class="num">{{ scientificCounting(myinfo.num_attention) }}</view>
  54. <view class="label">关注</view>
  55. </view>
  56. <!-- <view class="separator"></view> -->
  57. <view class="follow-box">
  58. <view class="num">{{ scientificCounting(myinfo.num_fans) }}</view>
  59. <view class="label">粉丝</view>
  60. </view>
  61. <!-- <view class="separator"></view> -->
  62. <view class="follow-box">
  63. <view class="num">{{ scientificCounting(myinfo.num_like) }}</view>
  64. <view class="label">获赞</view>
  65. </view>
  66. </view>
  67. <view class="bom-box">
  68. <view class="bom-item bom-item1 scale-tap" @click="goPage('/pages/my/wallet')">
  69. <view class="bom-item-title">钱包</view>
  70. <view class="bom-item-subtitle">查看我的钱包</view>
  71. </view>
  72. <view class="bom-item bom-item2 scale-tap">
  73. <view class="bom-item-title" @click="initiateFundraising()">发起募集</view>
  74. <view class="bom-item-subtitle">查看我的众筹</view>
  75. </view>
  76. <view class="bom-item bom-item3 scale-tap" @click="goPage('/pages/crowdFunding/orderList')">
  77. <view class="bom-item-title">订单</view>
  78. <view class="bom-item-subtitle">查看我的订单</view>
  79. </view>
  80. </view>
  81. </view>
  82. <view class="card-box" v-if="false">
  83. <view class="card-top">
  84. <view class="top-box">
  85. 1
  86. </view>
  87. <view class="userinfo-box" @click="goPage('/pages/my/editInfo')">
  88. <view class="userinfo-left">
  89. <CircleAvatar class="avator" :src="myinfo.avator"></CircleAvatar>
  90. </view>
  91. <view class="userinfo-right">
  92. <view class="nickname">
  93. <text class="one-omit">{{ myinfo.nickname }}</text>
  94. <view class="level">Lv{{ myinfo.my_level }}</view>
  95. </view>
  96. <view class="label">
  97. </view>
  98. </view>
  99. </view>
  100. <view class="line"></view>
  101. <view class="bom">
  102. <view class="points-box">
  103. <view class="points" @click="isRecharge ? goPage('/pages/vip/M_purchase') : ''">
  104. <image src="@/static/icon/wd_icon_coin.png" mode=""></image>
  105. <text>{{ myinfo.num_gmm | formatNumberToK }}</text>
  106. <image class="money-add" v-if="isRecharge" src="/static/icon/coin_add.png"
  107. mode="aspectFit"></image>
  108. </view>
  109. <view class="points"
  110. @click="isRecharge ? goPage('/pages/my/job?type=recharge') : ''">
  111. <image src="@/static/icon/coin_cd.png" mode=""></image>
  112. <text>{{ myinfo.num_gmd | formatNumberToK }}</text>
  113. <image class="money-add" v-if="isRecharge" src="/static/icon/coin_add.png"
  114. mode="aspectFit"></image>
  115. </view>
  116. </view>
  117. </view>
  118. </view>
  119. <!-- <view class="card-bom" v-if="isRecharge" @click="goPage('/pages/vip/index')"> -->
  120. </view>
  121. </view>
  122. </view>
  123. <view class="myinfo">
  124. <view class="vip-box" @click="isRecharge ? goPage('/pages/vip/index') : ''">
  125. <view class="content-box">
  126. <image v-if="false" src="@/static/me/icon-vip2.png" mode=""></image>
  127. <image v-else-if="0" src="@/static/me/icon-vip1.png" mode=""></image>
  128. <image v-else src="@/static/me/icon-vip0.png" mode=""></image>
  129. <text v-if="myinfo.is_vip == 0">开启专属会员权益</text>
  130. <text v-else style="font-size: 28rpx;">会员权益生效中 <text
  131. style="font-size: 24rpx; color: rgba(172 ,249 ,52, .5);"> ({{ myinfo.vip_date }})
  132. </text>
  133. </text>
  134. </view>
  135. <!-- <view class=""> -->
  136. <!-- <image v-if="isRecharge" src="@/static/me/wd_icon_jiantou.png" mode="aspectFit"></image> -->
  137. <view class="vip-btn">
  138. 会员中心
  139. </view>
  140. <!-- </view> -->
  141. </view>
  142. <!-- <view class="line"></view> -->
  143. <view class="tablist">
  144. <view class="item" :class="{ active: firstLevelNavActive === 0 }"
  145. @click="firstLevelNavActiveSwitch(0)">我的作品
  146. <view class="indicator-triangle"> </view>
  147. </view>
  148. <view class="item" :class="{ active: firstLevelNavActive === 1 }"
  149. @click="firstLevelNavActiveSwitch(1)">我的帖子
  150. <view class="indicator-triangle"> </view>
  151. </view>
  152. </view>
  153. <!-- 作品列表 -->
  154. <template v-if="firstLevelNavActive == 0">
  155. <view class="line"></view>
  156. <view class="subtitle">
  157. <view class="item" :class="{ active: activeTab === 0 }" @click="switchTab(0)">
  158. 作品
  159. </view>
  160. <view class="item" :class="{ active: activeTab === 1 }" @click="switchTab(1)">
  161. 生成中
  162. </view>
  163. </view>
  164. <view class="numlist1" v-if="activeTab === 0" style="margin-top: 15rpx">
  165. <WorkItem v-for="(item, index) in worksList" :secrecy="true" :subtitle="true" :key="index"
  166. :item="item" @click="goWork(item)" />
  167. <!-- 修改空状态显示条件 -->
  168. <view v-if="isDataLoaded && worksList.length === 0" class="empty-state">
  169. <image src="@/static/icon/xx_img_zanwuxiaoxi.png" mode="aspectFit" class="empty-image">
  170. </image>
  171. <text class="empty-text">暂无作品</text>
  172. <text class="empty-subtext">快来创作你的第一个作品吧~</text>
  173. </view>
  174. </view>
  175. <view class="numlist2" v-if="activeTab === 1" style="margin-top: 15rpx">
  176. <view class="item" v-for="(item, index) in worksList" :key="index"
  177. style="margin-bottom: 28rpx;">
  178. <view class="num" @click="goWork(item)"
  179. :class="{ 'clickable': item.status !== 3 && item.status !== 4 }">
  180. <WorkItem :item="item" style="margin-bottom: 12rpx" />
  181. <image class="incomplete-bg" v-if="item.status != 9"
  182. src="@/static/me/wd_bg_zhizuozhong.png"></image>
  183. <view class="maskLayer"></view>
  184. <!-- 当activeTab为1时显示队列状态 -->
  185. <view class="queue-status">
  186. <!-- 排队中 -->
  187. <view v-if="item.status === 1" class="status-text">
  188. <image class="state-img" src="@/static/me/wd_icon_paiduizhong.png"></image>
  189. </view>
  190. <!-- 生成失败 -->
  191. <view v-if="item.status === 3 || item.status === 4" class="status-text">
  192. <image class="state-img" src="@/static/me/wd_icon_zhizuoshibai.png"></image>
  193. </view>
  194. <!-- 制作中 -->
  195. <view v-else-if="item.status < 9" class="status-text">
  196. <image class="state-img" src="@/static/me/wd_icon_zhizuozhong.png"></image>
  197. </view>
  198. <!-- 创作完成 -->
  199. <view v-else-if="item.status === 9" class="status-text">
  200. <image class="state-img" src="@/static/me/wd_icon_chuangzuowancheng.png">
  201. </image>
  202. </view>
  203. </view>
  204. <view class="name one-omit" style="
  205. font-family: 'PingFang SC-Medium';
  206. font-weight: 500;
  207. font-size: 28rpx;
  208. color: #1a4d2e;
  209. max-width: 40vw;
  210. ">
  211. {{ item.title || item.description || "作品" + index }}
  212. </view>
  213. <!-- 显示任务类型标签 -->
  214. <view class="task-type-tag" style="position: absolute; left: 14rpx;top: 14rpx;">
  215. <image style="width: 120rpx; height: 36rpx" v-if="item.task_type === 1"
  216. src="@/static/me/wd_icon_lingganchuangzuo.png"></image>
  217. <image style="width: 82rpx; height: 36rpx" v-else-if="item.task_type === 2"
  218. src="@/static/me/wd_icon_yinyue.png"></image>
  219. <!-- <text v-if="item.task_type === 1">灵感创作</text>
  220. <text v-else-if="item.task_type === 2">音乐</text> -->
  221. </view>
  222. </view>
  223. </view>
  224. <!-- 修改空状态显示条件 -->
  225. <view v-if="isDataLoaded && worksList.length === 0" class="empty-state">
  226. <image src="@/static/icon/xx_img_zanwuxiaoxi.png" mode="aspectFit" class="empty-image">
  227. </image>
  228. <text class="empty-text">暂无生成中的作品</text>
  229. <text class="empty-subtext">快去创作新作品吧~</text>
  230. </view>
  231. </view>
  232. </template>
  233. <template v-else>
  234. <view class="numlist2" style="margin-top: 30rpx">
  235. <view class="item" v-for="(item, index) in worksList" :key="index" style="margin-bottom: 15rpx">
  236. <view class="num" @click="goWork2(item)"
  237. :class="{ 'clickable': item.status !== 3 && item.status !== 4 }">
  238. <WorkItem :item="item" style="margin-bottom: 20rpx" />
  239. <view class="incomplete-bg" style="background: #f8f9fa"></view>
  240. <image class="incomplete-bg" v-if="item.status != 1"
  241. src="@/static/me/wd_bg_zhizuozhong.png"></image>
  242. <image class="incomplete-bg2" v-else-if="item.status == 1" :src="item.image"
  243. mode="aspectFill" style="max-height: 520rpx;"></image>
  244. <view class="maskLayer" v-if="item.status != 1"></view>
  245. <!-- 当activeTab为1时显示队列状态 -->
  246. <view class="queue-status">
  247. <!-- 已发布 -->
  248. <view v-if="item.status == 1" class="status-text">
  249. </view>
  250. <!-- 待审核 -->
  251. <view v-if="item.status == 2 || item.status === 4" class="status-text">
  252. <image class="state-img" src="@/static/me/wd_icon_shenhezhong.png"></image>
  253. </view>
  254. <!-- 审核失败 -->
  255. <view v-else-if="item.status == 3" class="status-text">
  256. <image class="state-img" src="@/static/me/wd_icon_fabushibai.png"></image>
  257. </view>
  258. </view>
  259. <view class="name one-omit" style="
  260. font-family: 'PingFang SC-Medium';
  261. font-weight: 500;
  262. font-size: 28rpx;
  263. color: #1a4d2e;
  264. max-width: 40vw;
  265. ">
  266. {{ item.title || item.description || "作品" + index }}
  267. </view>
  268. </view>
  269. </view>
  270. <!-- 修改空状态显示条件 -->
  271. <view v-if="isDataLoaded && worksList.length === 0" class="empty-state">
  272. <image src="@/static/icon/xx_img_zanwuxiaoxi.png" mode="aspectFit" class="empty-image">
  273. </image>
  274. <text class="empty-text">暂无帖子</text>
  275. <text class="empty-subtext">快来发布你的第一个帖子吧~</text>
  276. </view>
  277. </view>
  278. </template>
  279. <!-- 加载更多提示 -->
  280. <!-- <view class="loading-more" v-if="isLoading">加载中...</view>
  281. <view class="no-more" v-if="!hasMore && worksList.length > 0">没有更多作品了</view>
  282. <view class="no-more" v-if="!hasMore && worksList.length === 0">暂无作品</view> -->
  283. </view>
  284. <view class="blankHeight"></view>
  285. </view>
  286. <view class="reserveASeatBom"></view>
  287. <!-- 确认框 -->
  288. <CustomConfirm ref="customConfirm"></CustomConfirm>
  289. <!-- 提示框 -->
  290. <DialogBox ref="DialogBox"></DialogBox>
  291. <tabbar-view :tabbars="tabbars" :currentIndex="4" ref="tabbar"></tabbar-view>
  292. <!-- SharePopup组件 -->
  293. <SharePopup :visible="showShare" :userId="userId" :share-title="shareTitle" :share-desc="shareDesc"
  294. :share-img="shareImg" view="makeDetail" @close="showShare = false" />
  295. <DialogBox ref="DialogBox"></DialogBox>
  296. </view>
  297. </template>
  298. <script>
  299. import tabbarView from "@/components/tabbar/tabbar.vue";
  300. import tabbar from "@/mixins/tabbar";
  301. import CustomConfirm from "@/components/custome-confirm/customeConfirm.vue";
  302. import CircleAvatar from "@/components/CircleAvatar/CircleAvatar.vue";
  303. import meCard from "@/components/meCard/meCard.vue";
  304. import WorkItem from "@/components/WorkItem/WorkItem.vue";
  305. import {
  306. mapState
  307. } from 'vuex'
  308. import {
  309. scientificCounting
  310. } from "@/common/util.js";
  311. import {
  312. RgbQuant
  313. } from '@/common/RgbQuant.js';
  314. export default {
  315. components: {
  316. tabbarView,
  317. CustomConfirm,
  318. CircleAvatar,
  319. meCard,
  320. WorkItem,
  321. },
  322. mixins: [tabbar],
  323. data() {
  324. return {
  325. bgImage: '',
  326. title: "",
  327. sel: 1,
  328. firstLevelNavActive: 0,
  329. labelBoxHeight: 0,
  330. myinfo: {
  331. avator: "../../static/logo.png",
  332. nickname: "",
  333. join_name: "",
  334. num_1: 0,
  335. num_2: 0,
  336. num_3: 0,
  337. num_4: 0,
  338. is_login: "no",
  339. num_history: 0,
  340. num_collection: 0,
  341. },
  342. aihao_tags: [],
  343. menu_list: [],
  344. data_list: [],
  345. activeTab: 0,
  346. offset: 0,
  347. hasMore: true,
  348. isLoading: false,
  349. isDataLoaded: false,
  350. worksList: [],
  351. showShare: false,
  352. shareTitle: "",
  353. shareDesc: "",
  354. shareImg: "",
  355. userId: 0,
  356. headerBoxStyle: {
  357. background: 'linear-gradient(360deg, #16210E 0%, rgba(55,73,36,0) 100%)'
  358. },
  359. };
  360. },
  361. onLoad(e) {
  362. // setTimeout(function() {
  363. // uni.setNavigationBarColor({
  364. // frontColor: '#ffffff',
  365. // backgroundColor: '#00000000',
  366. // animation: {
  367. // duration: 400,
  368. // timingFunc: 'easeIn'
  369. // }
  370. // })
  371. // }, 200);
  372. uni.$on('switchToMyPage', (data) => {
  373. if (data.type === 'article') {
  374. this.firstLevelNavActiveSwitch(1);
  375. } else if (data.type === 'generatingInProgress') {
  376. this.firstLevelNavActiveSwitch(0)
  377. this.switchTab(1);
  378. } else {
  379. this.firstLevelNavActiveSwitch(0)
  380. this.switchTab(0);
  381. }
  382. });
  383. },
  384. onUnload() {
  385. // 移除事件监听
  386. uni.$off('switchToMyPage');
  387. },
  388. computed: {
  389. ...mapState('switchingModule', ['isRecharge'])
  390. },
  391. onShow() {
  392. uni.$emit("check_login", () => {});
  393. this.offset = 0;
  394. this.hasMore = true;
  395. this.worksList = [];
  396. this.loadInfo();
  397. // 使用nextTick确保DOM已更新
  398. this.$nextTick(() => {
  399. this.getLabelBoxHeight();
  400. });
  401. // 检查全局变量,如果需要切换到生成中标签
  402. if (getApp().globalData.needSwitchToGenerating) {
  403. setTimeout(() => {
  404. this.switchTab(1);
  405. // 重置全局变量
  406. getApp().globalData.needSwitchToGenerating = false;
  407. }, 300);
  408. } else {
  409. this.loadWorksList();
  410. }
  411. },
  412. onReachBottom() {
  413. if (this.hasMore && !this.isLoading) {
  414. this.loadMoreWorks();
  415. }
  416. },
  417. methods: {
  418. clickShare(item) {
  419. this.showShare = true;
  420. },
  421. async showConfirm() {
  422. let that = this;
  423. this.$refs["customConfirm"]
  424. .confirm({
  425. title: "确认解绑",
  426. content: "解绑微信账号后将无法继续使用它登录该App账号?",
  427. DialogType: "inquiry",
  428. btn1: "再考虑一下",
  429. btn2: "确认解绑",
  430. animation: 0,
  431. })
  432. .then((res) => {});
  433. },
  434. onBack() {},
  435. chkSel() {
  436. if (this.sel == 1) {
  437. this.sel = 0;
  438. } else {
  439. this.sel = 1;
  440. }
  441. },
  442. goPage(page) {
  443. console.log(999);
  444. uni.navigateTo({
  445. url: page,
  446. });
  447. },
  448. initiateFundraising() {
  449. if (this.myinfo.my_level < 3) {
  450. this.$refs["DialogBox"]
  451. .confirm({
  452. title: "提示",
  453. content: "您当前的等级为" + this.myinfo.my_level + "级,需要达到3级才能发起募集",
  454. DialogType: "inquiry",
  455. btn1: "取消",
  456. btn2: "去查看等级",
  457. animation: 0,
  458. })
  459. .then((res) => {
  460. this.goPage('/pages/my/creativeExpert')
  461. }, (res) => {});
  462. return;
  463. }
  464. this.goPage('/pages/my/initiateCrowdfunding')
  465. },
  466. async calculateThemeColor(imageUrl) {
  467. if (!imageUrl) {
  468. // 如果没有图片,则使用默认样式
  469. this.headerBoxStyle = {
  470. background: 'linear-gradient(to bottom, rgba(0, 0, 0, 0.5), transparent)'
  471. };
  472. return;
  473. }
  474. console.log('开始计算主题色, imageUrl:', imageUrl);
  475. const canvasId = 'themeCanvas';
  476. const ctx = uni.createCanvasContext(canvasId, this);
  477. uni.getImageInfo({
  478. src: imageUrl,
  479. success: (imageInfo) => {
  480. console.log('图片信息获取成功:', imageInfo);
  481. const canvasWidth = 100; // 缩小图片以加快处理速度
  482. const canvasHeight = Math.floor(canvasWidth * (imageInfo.height / imageInfo
  483. .width));
  484. // 绘制图片到canvas
  485. ctx.drawImage(imageInfo.path, 0, 0, canvasWidth, canvasHeight);
  486. ctx.draw(false, () => {
  487. console.log('Canvas 绘制完成');
  488. // 获取像素数据
  489. uni.canvasGetImageData({
  490. canvasId: canvasId,
  491. x: 0,
  492. y: 0,
  493. width: canvasWidth,
  494. height: canvasHeight,
  495. success: (res) => {
  496. console.log('像素数据获取成功');
  497. const pixels = res.data;
  498. // 使用 RgbQuant 提取主要颜色
  499. const quant = new RgbQuant({
  500. colors: 16, // 提取16种主要颜色
  501. method: 2, // 使用 WuQuant 算法
  502. });
  503. quant.sample(pixels);
  504. const palette = quant.quantize();
  505. if (quant.vboxes && quant.vboxes.length > 0) {
  506. let dominantColor = null;
  507. let maxPopulation = 0;
  508. // 找到像素数最多的颜色区域
  509. quant.vboxes.forEach(vbox => {
  510. const population = vbox.size(quant
  511. .histogram);
  512. if (population > maxPopulation) {
  513. maxPopulation = population;
  514. dominantColor = vbox.color(
  515. quant.histogram);
  516. }
  517. });
  518. if (dominantColor) {
  519. const [r, g, b] = dominantColor.map(
  520. value => Math.min(255, Math.max(0,
  521. value)));
  522. const themeColor =
  523. `rgba(${r}, ${g}, ${b}, 0.5)`;
  524. console.log('计算出的主题色 (Dominant):',
  525. themeColor);
  526. // 更新 header-box 的背景样式
  527. this.headerBoxStyle = {
  528. background: `linear-gradient(to bottom, ${themeColor}, transparent)`
  529. };
  530. }
  531. }
  532. },
  533. fail: (err) => {
  534. console.error('获取像素数据失败:', err);
  535. }
  536. });
  537. });
  538. },
  539. fail: (err) => {
  540. console.error('获取图片信息失败:', err);
  541. }
  542. });
  543. },
  544. async loadInfo() {
  545. console.log({
  546. uuid: getApp().globalData.uuid,
  547. skey: getApp().globalData.skey,
  548. });
  549. uni.request({
  550. url: this.$apiHost + "/User/getinfo",
  551. data: {
  552. uuid: getApp().globalData.uuid,
  553. skey: getApp().globalData.skey,
  554. },
  555. header: {
  556. "content-type": "application/json",
  557. sign: getApp().globalData.headerSign,
  558. },
  559. success: (res) => {
  560. console.log("----:", JSON.parse(JSON.stringify(res.data)));
  561. if (res.data) {
  562. this.shareTitle = res.data.nickname
  563. this.shareDesc = res.data.content
  564. this.shareImg = res.data.avator
  565. this.userId = res.data.user_id
  566. }
  567. if (res.data.need_login == "yes") {
  568. // getApp().globalData.skey = "";
  569. // getApp().globalData.uuid = "";
  570. uni.removeStorageSync("wapptoken");
  571. uni.redirectTo({
  572. url: "/pages/login/login",
  573. });
  574. return;
  575. }
  576. if (res.data.aihao) {
  577. this.aihao_tags = res.data.aihao.split(",");
  578. }
  579. this.myinfo = res.data;
  580. getApp().globalData.user_id = res.data.user_id;
  581. // this.bgImage = res.data.bgimg;
  582. // 在获取到背景图片后,计算主题色
  583. // this.calculateThemeColor(this.bgImage);
  584. },
  585. complete: (com) => {
  586. // uni.hideLoading();
  587. },
  588. fail: (e) => {
  589. console.log("----e:", e);
  590. },
  591. });
  592. uni.request({
  593. url: this.$apiHost + "/Member/getinfoData",
  594. data: {
  595. uuid: getApp().globalData.uuid,
  596. skey: getApp().globalData.skey,
  597. },
  598. header: {
  599. "content-type": "application/json",
  600. sign: getApp().globalData.headerSign,
  601. },
  602. success: async (res) => {
  603. console.log("----:", JSON.parse(JSON.stringify(res.data)));
  604. if (res.data) {
  605. this.bgImage = res.data.bgimg;
  606. if (this.bgImage) {
  607. // 计算主题色并更新蒙版背景
  608. // const gradient = await this.calculateThemeColor(this.bgImage);
  609. const gradient =
  610. `linear-gradient(to bottom,transparent, rgba(0, 0, 0, .8))`;
  611. this.headerBoxStyle = {
  612. background: gradient
  613. };
  614. }
  615. }
  616. },
  617. complete: (com) => {
  618. // uni.hideLoading();
  619. },
  620. fail: (e) => {
  621. console.log("----e:", e);
  622. },
  623. });
  624. },
  625. onLogout() {
  626. let that = this;
  627. this.$refs["DialogBox"]
  628. .confirm({
  629. title: "提示",
  630. content: "确定退出吗?",
  631. DialogType: "inquiry",
  632. btn1: "取消",
  633. btn2: "退出",
  634. animation: 0,
  635. })
  636. .then((res) => {
  637. uni.request({
  638. url: that.$apiHost + "/My/logout",
  639. data: {
  640. uuid: getApp().globalData.uuid,
  641. skey: getApp().globalData.skey,
  642. },
  643. header: {
  644. "content-type": "application/json",
  645. sign: getApp().globalData.headerSign,
  646. },
  647. success: (res) => {
  648. console.log("----:", res.data);
  649. // getApp().globalData.skey = "";
  650. // getApp().globalData.uuid = "";
  651. uni.removeStorageSync("wapptoken");
  652. uni.redirectTo({
  653. url: "/pages/login/login",
  654. });
  655. },
  656. complete: (com) => {
  657. // uni.hideLoading();
  658. },
  659. fail: (e) => {
  660. console.log("----e:", e);
  661. },
  662. });
  663. });
  664. },
  665. switchTab(index) {
  666. this.activeTab = index;
  667. this.offset = 0;
  668. this.hasMore = true;
  669. this.worksList = [];
  670. this.loadWorksList();
  671. },
  672. loadWorksList() {
  673. if (this.isLoading) return;
  674. this.isLoading = true;
  675. this.isDataLoaded = false;
  676. // 根据activeTab选择不同的API
  677. let apiUrl = "";
  678. if (this.firstLevelNavActive == 0) {
  679. if (this.activeTab === 0) {
  680. apiUrl = "/Work/getlist";
  681. } else {
  682. apiUrl = "/WorkAI/getMyQueueList";
  683. }
  684. } else if (this.firstLevelNavActive == 1) {
  685. apiUrl = "/Article/getlist";
  686. }
  687. uni.request({
  688. url: this.$apiHost + apiUrl,
  689. data: {
  690. uuid: getApp().globalData.uuid,
  691. skey: getApp().globalData.skey,
  692. type: "my",
  693. offset: this.offset,
  694. status: this.activeTab === 0 ? 1 : undefined,
  695. },
  696. header: {
  697. "content-type": "application/json",
  698. sign: getApp().globalData.headerSign,
  699. },
  700. success: (res) => {
  701. console.log("列表数据:", JSON.parse(JSON.stringify(res.data)));
  702. if (res.data.success == "yes" && res.data.list) {
  703. if (res.data.list.length > 0) {
  704. this.worksList = [...this.worksList, ...res.data.list];
  705. this.offset += res.data.list.length;
  706. }
  707. if (res.data.list.length < 20) {
  708. this.hasMore = false;
  709. }
  710. } else {
  711. this.hasMore = false;
  712. this.worksList = [];
  713. }
  714. if (this.activeTab === 0) {
  715. this.updateDataList();
  716. }
  717. console.log("作品列表数据:", this.worksList);
  718. },
  719. complete: () => {
  720. this.isLoading = false;
  721. this.isDataLoaded = true;
  722. },
  723. fail: (e) => {
  724. console.log("请求列表失败:", e);
  725. this.isLoading = false;
  726. this.isDataLoaded = true;
  727. this.worksList = [];
  728. },
  729. });
  730. },
  731. firstLevelNavActiveSwitch(n) {
  732. this.firstLevelNavActive = n;
  733. this.offset = 0;
  734. this.hasMore = true;
  735. this.worksList = [];
  736. if (this.firstLevelNavActive == 0) {
  737. this.activeTab = 0;
  738. }
  739. this.loadWorksList();
  740. },
  741. loadMoreWorks() {
  742. if (this.hasMore && !this.isLoading) {
  743. this.loadWorksList();
  744. }
  745. },
  746. updateDataList() {
  747. this.data_list = this.worksList.map((item) => {
  748. return {
  749. url: item.images || item.img_url || item.url || "../../static/logo.png",
  750. title: item.title || item.description || "作品",
  751. id: item.id,
  752. };
  753. });
  754. },
  755. goWork(item) {
  756. uni.$emit("check_login", () => {});
  757. // , //任务状态(1:排队中,3:生成失败,4:生成失败,9:创作完成)
  758. if (this.activeTab == 0) {
  759. uni.navigateTo({
  760. // url: "/pages/index/workDetail?id=" + item.id,
  761. url: "/pages/makedetail/makeDetail?id=" +
  762. item.queue_id +
  763. "&queueId=" +
  764. item.id,
  765. });
  766. } else {
  767. if (item.status >= 9) {
  768. uni.navigateTo({
  769. url: "/pages/makedetail/makeDetail?id=" + item.id,
  770. });
  771. }
  772. if (item.status < 9 && item.status != 3 && item.status != 4) {
  773. // <!-- <text v-if="item.task_type === 1">灵感创作</text>
  774. // <text v-else-if="item.task_type === 2">音乐</text> -->
  775. var url = "";
  776. if (item.task_type === 1) {
  777. url = "/makedetail/makeImgDetail";
  778. }
  779. if (item.task_type === 2) {
  780. url = "/makedetail/makeMusicDetail";
  781. }
  782. if (url) {
  783. uni.navigateTo({
  784. url: "/pages" + url + "?id=" + item.id,
  785. });
  786. }
  787. }
  788. }
  789. },
  790. goWork2(item) {
  791. uni.navigateTo({
  792. // url: "/pages/index/workDetail?id=" + item.id,
  793. url: "/pages/index/articleDetail?id=" + item.id,
  794. });
  795. },
  796. navigateToSettings() {
  797. uni.$emit("check_login", () => {
  798. uni.navigateTo({
  799. url: "/pages/my/setting",
  800. });
  801. });
  802. },
  803. navigateToFollow() {
  804. uni.navigateTo({
  805. url: "/pages/my/follow",
  806. });
  807. },
  808. formatText(text) {
  809. if (!text) return '';
  810. return text.length > 20 ? text.substring(0, 20) + '...' : text;
  811. },
  812. scientificCounting(num) {
  813. if (!num) {
  814. return 0;
  815. }
  816. if (num < 1000) {
  817. return num;
  818. } else if (num < 1000000) {
  819. return (num / 1000).toFixed(1) + 'k';
  820. } else if (num < 1000000000) {
  821. return (num / 1000000).toFixed(1) + 'M';
  822. } else {
  823. return (num / 1000000000).toFixed(1) + 'B';
  824. }
  825. },
  826. // 获取label-box高度的方法
  827. getLabelBoxHeight() {
  828. setTimeout(() => {
  829. const query = uni.createSelectorQuery();
  830. query.select('#labelBox').boundingClientRect(data => {
  831. if (data) {
  832. this.labelBoxHeight = data.height;
  833. console.log('label-box高度:', this.labelBoxHeight);
  834. }
  835. }).exec();
  836. }, 100);
  837. },
  838. },
  839. };
  840. </script>
  841. <style scoped lang="scss">
  842. @import "my.scss";
  843. .empty-state {
  844. display: flex;
  845. flex-direction: column;
  846. align-items: center;
  847. justify-content: center;
  848. padding: 60rpx 0;
  849. margin-top: 40rpx;
  850. background: #FFFFFF;
  851. border-radius: 20rpx;
  852. width: 710rpx;
  853. .empty-image {
  854. width: 240rpx;
  855. height: 240rpx;
  856. margin-bottom: 30rpx;
  857. }
  858. .empty-text {
  859. font-size: 32rpx;
  860. color: #333333;
  861. margin-bottom: 16rpx;
  862. font-weight: 500;
  863. }
  864. .empty-subtext {
  865. font-size: 28rpx;
  866. color: #999999;
  867. }
  868. }
  869. </style>