index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. <template>
  2. <view class="container" :data-theme="theme">
  3. <!-- :style="userInfo.avatar?{ backgroundImage: `url(${userInfo.avatar})` }: ''" -->
  4. <!-- #ifdef MP || APP -->
  5. <NavBar navTitle="个人主页" :isBackgroundColor="false" iconColor='#fff'></NavBar>
  6. <!-- #endif -->
  7. <view class="header">
  8. <view class="header-bg" :style="{'background-image': userInfo.avatar}">
  9. <img :src="userInfo.avatar" alt="">
  10. <view class="header-bg-mc"></view>
  11. </view>
  12. <view class="user_wrapper acea-row">
  13. <image v-if="userInfo.userLevelIcon" class="level_icon" :src="userInfo.userLevelIcon" alt="">
  14. <view class="acea-row row-middle">
  15. <image :src="userInfo.avatar || urlDomain+'crmebimage/presets/morenT.png'" class="picture">
  16. </image>
  17. <view class="user_text">
  18. <view class="name acea-row">
  19. <text>{{userInfo.isLogoff ? "用户已注销": (userInfo.nickname || '')}}</text>
  20. </view>
  21. <!-- <view v-if="userInfo.id" class="user_id">ID: {{userInfo.id || ''}}</view> -->
  22. <view class="flex-between-center mt-16" @click="onEdit('school')">
  23. <view class="user_id">学校: {{school || '暂无'}}</view>
  24. <text v-show="userInfo.id==uid" class="ml10 iconfont icon-fabuzhongcao"></text>
  25. </view>
  26. </view>
  27. </view>
  28. <view v-if="id && id!=uid" @click.stop="followAuthor">
  29. <button v-if="!userInfo.isConcerned" class="follow_btn focus">
  30. <text class="iconfont icon-jiahao2"></text>关注
  31. </button>
  32. <button v-else class="follow_btn focused">已关注</button>
  33. </view>
  34. <view v-if="userInfo.id==uid">
  35. <navigator hover-class="none" :url="`/pages/discover/discover_release/index?dazi=${dazi}`"
  36. class="follow_btn focus bg-color">
  37. 去发布
  38. </navigator>
  39. </view>
  40. </view>
  41. <view class="acea-row plant_info" @click="onEdit('signature')">
  42. <view v-if="!userInfo.signature && userInfo.id==uid">点击可编辑个性签名</view>
  43. <view class="" v-if="userInfo.signature" style="width: 92%;">
  44. <view class="acea-row" v-if="userInfo.isMore || userInfo.signature.length<=30">
  45. <text class="signature">{{userInfo.signature}}</text>
  46. <text v-if="userInfo.isMore" class="more" @click.stop="moreTap">收起</text>
  47. </view>
  48. <view v-else class="acea-row">
  49. <text class="info signature">{{userInfo.signature.slice(0,23)}}...</text>
  50. <text class="more" @click.stop="moreTap"> 展开</text>
  51. </view>
  52. </view>
  53. <text v-show="userInfo.id==uid" class="ml10 iconfont icon-fabuzhongcao"></text>
  54. </view>
  55. <view class="plant_info" style="padding-bottom: 30rpx;">
  56. <view class="count_wrapper acea-row">
  57. <navigator :url="!id ? '/pages/discover/discover_follow/index?type=follow' : ''" class="item"
  58. hover-class="none">
  59. <text class="mr10">{{userInfo.concernedNum}}</text> 关注
  60. </navigator>
  61. <navigator :url="!id ? '/pages/discover/discover_follow/index?type=fans' : ''" class="item"
  62. hover-class="none">
  63. <text class="mr10">{{userInfo.fansNum}}</text> 粉丝
  64. </navigator>
  65. <view class="item">
  66. <text class="mr10">{{userInfo.likeNum}}</text> 获赞
  67. </view>
  68. </view>
  69. </view>
  70. <view v-if="!id && isShow" class="tab_count relative">
  71. <text @click.stop="changeTab(0)" :class="tab==0 ? 'on' : ''">{{dazi ? '我的作品' : '作品'}}</text>
  72. <text v-if="!dazi" @click.stop="changeTab(1)" :class="tab==1 ? 'on' : ''">赞过</text>
  73. <text v-if="dazi" @click.stop="changeTab(3)" :class="tab==3 ? 'on' : ''">我加入的</text>
  74. </view>
  75. </view>
  76. <view class="main">
  77. <view class="tab-conts">
  78. <view v-if="list.length > 0" class="goods-wrap flex-1">
  79. <view class="goods">
  80. <WaterfallsFlow v-if="list.length" :wfList="list" :fromType="1" fromTo="home" :column="dazi ? true : false" :isDazi="dazi ? true : false">
  81. </WaterfallsFlow>
  82. </view>
  83. </view>
  84. <view class="empty-boxs noContent" v-if="list.length == 0 && !loading">
  85. <emptyPage title="暂无更多内容~" mTop="13%" :imgSrc="urlDomain+'crmebimage/presets/noguanzhu.png'">
  86. </emptyPage>
  87. </view>
  88. <view class='loadingicon acea-row row-center-wrapper'>
  89. <text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>
  90. <view class="end" :hidden="loading || list.length == 0"><text
  91. :class="loaded ? 'loaded' : ''">{{loadTitle}}</text>
  92. </view>
  93. </view>
  94. </view>
  95. </view>
  96. <uni-popup ref="inputDialog" type="dialog">
  97. <view v-if="isShowSignature" class="tui-modal-custom">
  98. <view class="fs-32 fw-500 lh-44rpx text-center">{{fieldStr == 'signature' ? '编辑简介' : '编辑学校'}}</view>
  99. <view class="mt-24 bg--w111-f5f5f5 rd-16rpx p-24">
  100. <textarea v-if="fieldStr == 'signature'" class="w-full fs-26 h-342" ref="myTextarea" v-model="signature" :focus="focus"
  101. :always-embed="true" :adjust-position="true" cursor-spacing="85rpx"
  102. placeholder="请输入内容" :maxlength="100" name="desc" />
  103. <input v-if="fieldStr == 'school'" class="placeholder" type='text' v-model='school' :focus="focus"
  104. placeholder='请输入学校' placeholder-class='placeholder'></input>
  105. </view>
  106. <view class="flex-between-center mt-40">
  107. <view class="w-244 h-72 rd-36rpx flex-center fs-26 font-color close-btn" @tap="handleInputClose">取消
  108. </view>
  109. <view class="w-244 h-72 rd-36rpx flex-center bg-color text--w111-fff fs-26"
  110. @tap="handleInputConfirm">保存
  111. </view>
  112. </view>
  113. </view>
  114. </uni-popup>
  115. </view>
  116. </template>
  117. <script>
  118. // +----------------------------------------------------------------------
  119. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  120. // +----------------------------------------------------------------------
  121. // | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
  122. // +----------------------------------------------------------------------
  123. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  124. // +----------------------------------------------------------------------
  125. // | Author: CRMEB Team <admin@crmeb.com>
  126. // +----------------------------------------------------------------------
  127. import WaterfallsFlow from '@/components/WaterfallsFlow/WaterfallsFlow.vue'
  128. import WaterfallsFlowItem from '@/components/discoverFlowItem/discoverFlowItem.vue'
  129. import emptyPage from '@/components/emptyPage.vue';
  130. import NavBar from '@/components/navBar.vue';
  131. import {
  132. userHomeApi,
  133. myHomeApi,
  134. authorNoteApi,
  135. myNoteApi,
  136. myLikeListApi,
  137. editSignatureApi,
  138. editSchoolApi
  139. } from '@/api/discover.js';
  140. import { myGameApi, myGameJoinApi } from '@/api/gameDazi.js';
  141. import {
  142. toLogin
  143. } from '@/libs/login.js';
  144. import {
  145. mapGetters
  146. } from "vuex";
  147. import {
  148. discoverFollowAuthor
  149. } from '@/libs/follow.js';
  150. const app = getApp();
  151. let sysHeight = uni.getSystemInfoSync().statusBarHeight;
  152. export default {
  153. components: {
  154. WaterfallsFlow,
  155. WaterfallsFlowItem,
  156. emptyPage,
  157. NavBar
  158. },
  159. data() {
  160. return {
  161. sysHeight: sysHeight,
  162. urlDomain: this.$Cache.get("imgHost"),
  163. theme: app.globalData.theme,
  164. list: [], // 内容列表
  165. loadTitle: '加载更多',
  166. loading: false,
  167. loaded: false,
  168. isShowAuth: false, //是否隐藏授权
  169. isAuto: false, //没有授权的不会自动授权
  170. userInfo: {},
  171. where: {
  172. page: 1,
  173. limit: 10
  174. },
  175. tab: 0,
  176. id: '', //作者id
  177. isShow: false,
  178. focus: false,
  179. isShowSignature: false, // 是否显示简介编辑内容
  180. signature: '', //弹窗中的签名
  181. school: '',
  182. fieldStr: '',
  183. dazi: ''
  184. }
  185. },
  186. created() {},
  187. computed: {
  188. ...mapGetters(['isLogin', 'uid']),
  189. },
  190. watch: {},
  191. onLoad: function(options) {
  192. this.id = options.id ? options.id : '';
  193. this.dazi = options.dazi || '';
  194. console.log(this.dazi)
  195. },
  196. onShow() {
  197. if (this.id) {
  198. this.isShow = false
  199. this.getUserHome(this.id);
  200. this.authorNoteList();
  201. } else {
  202. this.isShow = true
  203. this.getMyHome();
  204. this.myNoteList();
  205. }
  206. },
  207. onReady() {},
  208. mounted: function() {},
  209. methods: {
  210. moreTap() {
  211. this.$set(this.userInfo, 'isMore', !this.userInfo.isMore)
  212. },
  213. //个性签名取消
  214. handleInputClose() {
  215. this.$refs.inputDialog.close()
  216. this.isShowSignature = false;
  217. },
  218. //个性签名保存
  219. handleInputConfirm() {
  220. const api = this.fieldStr == 'signature' ? editSignatureApi({signature: this.signature}) : editSchoolApi({school: this.school});
  221. api.then(res => {
  222. uni.showToast({
  223. title: res.data,
  224. icon: 'none'
  225. })
  226. this.getMyHome();
  227. }).catch(err => {
  228. uni.showToast({
  229. title: err,
  230. icon: 'none'
  231. })
  232. });
  233. // 关闭窗口后,恢复默认内容
  234. this.$refs.inputDialog.close()
  235. this.isShowSignature = false;
  236. },
  237. //编辑个性签名
  238. onEdit(str) {
  239. if (this.userInfo.id == this.uid) {
  240. this.fieldStr = str;
  241. this.isShowSignature = true;
  242. this.signature = this.userInfo.signature;
  243. this.$refs.inputDialog.open();
  244. }
  245. },
  246. //回退页面之后重新加载页面
  247. reFresh() {
  248. this.loading = false;
  249. this.loaded = false;
  250. this.where = {
  251. page: 1,
  252. limit: 10
  253. }
  254. this.list = []
  255. if (this.id) {
  256. this.getUserHome(this.id);
  257. this.authorNoteList();
  258. } else {
  259. this.getMyHome();
  260. this.myNoteList();
  261. }
  262. },
  263. //获取我的用户信息
  264. getMyHome() {
  265. myHomeApi().then(res => {
  266. this.userInfo = res.data;
  267. this.signature = this.userInfo.signature
  268. this.school = this.userInfo.school
  269. this.isMore = false;
  270. }).catch(err => {
  271. uni.showToast({
  272. title: err,
  273. icon: 'none'
  274. })
  275. });
  276. },
  277. //逛逛用户主页
  278. getUserHome(id) {
  279. userHomeApi(id).then(res => {
  280. this.userInfo = res.data
  281. }).catch(err => {
  282. uni.showToast({
  283. title: err,
  284. icon: 'none'
  285. })
  286. });
  287. },
  288. // 关注作者
  289. followAuthor: function() {
  290. if (this.isLogin) {
  291. if (this.userInfo.isLogoff) return;
  292. discoverFollowAuthor(this.id).then(() => {
  293. this.$set(this.userInfo, 'isConcerned', !this.userInfo.isConcerned);
  294. });
  295. } else {
  296. toLogin();
  297. }
  298. },
  299. changeTab(tab) {
  300. this.tab = tab
  301. this.where.page = 1
  302. this.loaded = this.loading = false
  303. this.list = []
  304. if (tab === 0) {
  305. this.myNoteList();
  306. } else if (tab === 3) {
  307. this.myJoinList();
  308. } else {
  309. this.myLikeList();
  310. }
  311. },
  312. // 获取我的点赞作品
  313. myLikeList: function() {
  314. let that = this;
  315. if (that.loaded || that.loading) return;
  316. that.loading = true;
  317. that.loadTitle = '';
  318. myLikeListApi(that.where).then(res => {
  319. let list = res.data.list;
  320. let goods = that.$util.SplitArray(list, that.list);
  321. that.loaded = list.length < that.where.limit;
  322. that.loading = false;
  323. that.loadTitle = that.loaded ? '到底了' : '加载更多';
  324. that.$set(that, 'list', goods);
  325. that.$set(that.where, 'page', that.where.page + 1);
  326. }).catch(err => {
  327. that.loading = false;
  328. uni.showToast({
  329. title: err,
  330. icon: 'none'
  331. })
  332. })
  333. },
  334. // 获取我加入的
  335. myJoinList: function() {
  336. let that = this;
  337. if (that.loaded || that.loading) return;
  338. that.loading = true;
  339. that.loadTitle = '';
  340. myGameJoinApi(that.where).then(res => {
  341. let list = res.data.list;
  342. let goods = that.$util.SplitArray(list, that.list);
  343. that.loaded = list.length < that.where.limit;
  344. that.loading = false;
  345. that.loadTitle = that.loaded ? '到底了' : '加载更多';
  346. that.$set(that, 'list', goods);
  347. that.$set(that.where, 'page', that.where.page + 1);
  348. }).catch(err => {
  349. that.loading = false;
  350. uni.showToast({
  351. title: err,
  352. icon: 'none'
  353. })
  354. })
  355. },
  356. // 获取我的的作品
  357. myNoteList: function() {
  358. let that = this;
  359. if (that.loaded || that.loading) return;
  360. that.loading = true;
  361. that.loadTitle = '';
  362. let api = this.dazi ? myGameApi : myNoteApi;
  363. api(that.where).then(res => {
  364. let list = res.data.list;
  365. let goods = that.$util.SplitArray(list, that.list);
  366. that.loaded = list.length < that.where.limit;
  367. that.loading = false;
  368. that.loadTitle = that.loaded ? '到底了' : '加载更多';
  369. that.$set(that, 'list', goods);
  370. that.$set(that.where, 'page', that.where.page + 1);
  371. }).catch(err => {
  372. that.loading = false;
  373. uni.showToast({
  374. title: err,
  375. icon: 'none'
  376. })
  377. })
  378. },
  379. // 作者的作品
  380. authorNoteList: function() {
  381. let that = this;
  382. if (that.loaded || that.loading) return;
  383. that.loading = true;
  384. that.loadTitle = '';
  385. this.where.authorId = this.id
  386. authorNoteApi(this.where.authorId, that.where).then(res => {
  387. let list = res.data.list;
  388. let goods = that.$util.SplitArray(list, that.list);
  389. that.loaded = list.length < that.where.limit;
  390. that.loading = false;
  391. that.loadTitle = that.loaded ? '到底了' : '加载更多';
  392. that.$set(that, 'list', goods);
  393. that.$set(that.where, 'page', that.where.page + 1);
  394. }).catch(err => {
  395. that.loading = false;
  396. uni.showToast({
  397. title: err,
  398. icon: 'none'
  399. })
  400. })
  401. }
  402. },
  403. onReachBottom() {
  404. if (this.id) {
  405. this.authorNoteList();
  406. } else {
  407. if (this.tab === 0) {
  408. this.myNoteList();
  409. } else {
  410. this.myLikeList();
  411. }
  412. }
  413. },
  414. onPullDownRefresh() {},
  415. // 滚动监听
  416. onPageScroll(e) {
  417. // 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件
  418. uni.$emit('scroll');
  419. }
  420. }
  421. </script>
  422. <style lang="scss" scoped>
  423. .close-btn {
  424. @include coupons_border_color(theme);
  425. }
  426. .tui-modal-custom {
  427. width: 600rpx;
  428. position: relative;
  429. box-sizing: border-box;
  430. padding: 40rpx;
  431. border-radius: 16px;
  432. background-color: #fff;
  433. z-index: 9999;
  434. .h-342 {
  435. min-height: 268rpx;
  436. max-height: 268rpx;
  437. ;
  438. overflow-y: scroll;
  439. }
  440. }
  441. .signature {
  442. overflow: hidden;
  443. display: -webkit-box;
  444. -webkit-line-clamp: 5;
  445. -webkit-box-orient: vertical;
  446. text-overflow: ellipsis;
  447. width: 88%;
  448. }
  449. .goods-wrap {
  450. padding-top: 24rpx;
  451. }
  452. .more {
  453. font-weight: 600;
  454. margin-left: 8rpx;
  455. }
  456. .container {
  457. background: #ffffff;
  458. min-height: 100vh;
  459. }
  460. .header-bg {
  461. position: absolute;
  462. width: 100%;
  463. height: 650rpx;
  464. top: 0;
  465. /* #ifdef MP || APP-PLUS */
  466. z-index: -1;
  467. /* #endif */
  468. /* #ifdef H5 */
  469. z-index: 0;
  470. /* #endif */
  471. z-index: 0;
  472. filter: blur(0);
  473. overflow: hidden;
  474. img {
  475. width: 100%;
  476. height: 100%;
  477. filter: blur(16rpx);
  478. transform: scale(1.5);
  479. }
  480. .header-bg-mc {
  481. position: absolute;
  482. top: 0;
  483. width: 100%;
  484. height: 100%;
  485. background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.1) 39%, rgba(0, 0, 0, 0.7) 100%);
  486. }
  487. }
  488. .header {
  489. width: 750rpx;
  490. padding: 20rpx 0 0;
  491. box-sizing: border-box;
  492. background: linear-gradient(360deg, #72798E 0%, #384857 99%);
  493. opacity: 1;
  494. .tab_count {
  495. text-align: center;
  496. background: #ffffff;
  497. padding: 30rpx 0 15rpx 0;
  498. border-radius: 12px 12px 0 0;
  499. text {
  500. display: inline-block;
  501. font-size: 28rpx;
  502. color: #999999;
  503. margin: 0 30rpx;
  504. position: relative;
  505. padding-bottom: 14rpx;
  506. &.on {
  507. font-size: 32rpx;
  508. color: #282828;
  509. font-weight: bold;
  510. &::after {
  511. content: "";
  512. width: 80%;
  513. height: 5rpx;
  514. @include main_bg_color(theme);
  515. position: absolute;
  516. bottom: 0;
  517. left: 12rpx;
  518. }
  519. .underline {
  520. opacity: 1;
  521. }
  522. }
  523. }
  524. }
  525. .user_wrapper {
  526. align-items: center;
  527. justify-content: space-between;
  528. padding: 0 34rpx;
  529. position: relative;
  530. .level_icon {
  531. position: absolute;
  532. width: 38rpx;
  533. height: 38rpx;
  534. margin: 4rpx 0 0 6rpx;
  535. border: none;
  536. z-index: 11;
  537. bottom: 2rpx;
  538. left: 124rpx;
  539. }
  540. .image,
  541. uni-image,
  542. image {
  543. width: 140rpx;
  544. height: 140rpx;
  545. border-radius: 100%;
  546. border: 4rpx solid #ffffff;
  547. }
  548. .user_text {
  549. margin-left: 30rpx;
  550. color: #FFFFFF;
  551. .name {
  552. font-size: 34rpx;
  553. font-weight: bold;
  554. align-items: center;
  555. }
  556. .user_id {
  557. margin-top: 16rpx;
  558. font-size: 24rpx;
  559. }
  560. }
  561. }
  562. .plant_info {
  563. position: relative;
  564. padding: 0 34rpx;
  565. margin-top: 30rpx;
  566. justify-content: space-between;
  567. color: #ffffff;
  568. font-size: 24rpx;
  569. .count_wrapper {
  570. color: #FFFFFF;
  571. font-size: 24rpx;
  572. .item {
  573. text-align: center;
  574. margin-right: 60rpx;
  575. &:last-child {
  576. margin-right: 0;
  577. }
  578. text {
  579. font-size: 30rpx;
  580. margin-top: 10rpx;
  581. }
  582. }
  583. }
  584. }
  585. .iconfont {
  586. font-size: 24rpx;
  587. margin-right: 12rpx;
  588. }
  589. .follow_btn {
  590. color: #ffffff;
  591. font-size: 26rpx;
  592. display: flex;
  593. align-items: center;
  594. justify-content: center;
  595. width: 146rpx;
  596. height: 62rpx;
  597. @include linear-gradient(theme);
  598. border-radius: 33rpx;
  599. .icon-fabu {
  600. font-size: 24rpx;
  601. }
  602. &.focused {
  603. background: transparent;
  604. color: #FFFFFF;
  605. border: 1px solid #FFFFFF;
  606. }
  607. }
  608. }
  609. .main {
  610. background: #ffffff;
  611. position: relative;
  612. }
  613. .goods {
  614. // display: flex;
  615. // flex-wrap: wrap;
  616. // justify-content: space-between;
  617. // width: 750rpx;
  618. padding: 0 24rpx;
  619. }
  620. .empty {
  621. margin: 130rpx 0 150rpx;
  622. text-align: center;
  623. image,
  624. uni-image {
  625. display: inline-block;
  626. width: 414rpx;
  627. height: 305rpx;
  628. }
  629. text {
  630. display: block;
  631. color: #999999;
  632. font-size: 26rpx;
  633. }
  634. }
  635. .end {
  636. margin-top: 50rpx 0;
  637. text-align: center;
  638. text {
  639. color: #999999;
  640. font-size: 22rpx;
  641. position: relative;
  642. &.loaded {
  643. &::before,
  644. &::after {
  645. content: "";
  646. display: inline-block;
  647. width: 22rpx;
  648. height: 1rpx;
  649. background: #999999;
  650. position: absolute;
  651. top: 18rpx;
  652. opacity: .5;
  653. }
  654. &::before {
  655. left: -30rpx;
  656. }
  657. &::after {
  658. right: -30rpx;
  659. }
  660. }
  661. }
  662. }
  663. </style>