index.vue 16 KB

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