personIndex.vue 8.79 KB
<template>
  <div class="person-index-page">
    <div class="header-wrapper">
      <div class="info">
        <van-row>
          <van-col>
            <van-image v-if="userInfo.avatar" round width="50" height="50" :src="userInfo.avatar"
              style="padding-right: 1rem;" />
            <van-image v-else round width="50" height="50" :src="icon_avatar" style="padding-right: 1rem;" />
          </van-col>
          <van-col class="text-wrapper" span="18">
            <div>
              <div class="username">{{ userInfo.name }}</div>
              <div v-if="!userInfo.is_follow" class="toggle-user" @click="followUser()">
                <van-icon name="plus" />&nbsp;关注
              </div>
              <div v-else class="toggle-user" @click="followUser()">&nbsp;取消关注</div>
            </div>
            <div class="address">{{ userInfo.kg_name }}</div>
          </van-col>
        </van-row>
      </div>

      <div class="sub-data">
        <van-row>
          <van-col span="11" offset="1" class="un-tap-color">
            <p>获赞</p>
            <p>{{ userInfo.like_num }}</p>
          </van-col>
          <van-col span="1" class="divide">|</van-col>
          <van-col span="11" class="un-tap-color">
            <p>粉丝</p>
            <p>{{ userInfo.fans_num }}</p>
          </van-col>
        </van-row>
      </div>
    </div>
    <div class="list-title">
      <van-row>
        <van-col span="6">
          <div class="title">发布作品</div>
        </van-col>
        <van-col span="12" offset="6" style="text-align: right; color: #626262;">
          <div style="padding-top: 0.5rem;">{{ userInfo.prod_num }}个作品</div>
        </van-col>
      </van-row>
    </div>
    <div>
      <!-- <template v-for="item in userInfo.prod" :key="item">
        <video-card :item="item" />
      </template> -->
      <van-list v-model:loading="loading" :finished="finished" :finished-text="finishedTextStatus ? '没有更多了' : ''"
        @load="onLoad">
        <template v-for="item in prod" :key="item">
          <video-card :item="item" />
        </template>
      </van-list>
      <div style="height: 8rem;" />
    </div>
    <div v-if="donateInfo" class="donate-bar">
      <div class="text">
        <span style="font-size: 0.85rem; color: #999999;">收到小红花&nbsp;</span>
        <van-icon :name="icon_flower" color="#c5c5c5" size="1.25rem" style="margin: 0 auto;" />
        <span>&nbsp;{{ userInfo.donate_num }}</span>
      </div>
      <div class="button">
        <my-button type="primary" @on-click="toDonate">为TA助力</my-button>
      </div>
    </div>
  </div>
  <van-empty v-if="emptyStatus" class="custom-image" :image="no_image" description="暂无作品信息" />


  <donate-flower :show-popup="showDonate" :item="donateInfo" @on-close="closeDonate" />
</template>

<script setup>
import { ref, onActivated, onMounted } from 'vue'
import { useRoute, onBeforeRouteLeave } from 'vue-router'
import { storeToRefs } from 'pinia'
import { MyButton, VideoCard, DonateFlower } from '@/utils/generateModules'
import { icon_avatar, no_image, icon_flower } from '@/utils/generateIcons.js'
import { _, Toast } from '@/utils/generatePackage.js'
import { addPages, store } from '@/hooks/useKeepAlive'
import { perfInfoAPI, addFollowAPI } from '@/api/C/perf.js'
import { useScrollTop } from '@/composables';
import { prepareDonateAPI } from '@/api/C/donate.js'
import { sharePage } from '@/composables/useShare.js'

const { resetScrollTop } = useScrollTop(); // 页面滚动恢复
resetScrollTop('scrollTopPerson');

const $route = useRoute();

const userInfo = ref({});
// 因为不能让空图标提前出来的写法
const emptyStatus = ref(false);

const donateInfo = ref({})
onMounted(async () => {
  // 获取表演者信息
  // const { data } = await perfInfoAPI({ perf_id: $route.query.perf_id });
  // if (!data.prod.length) {
  //   emptyStatus.value = true;
  // } else {
  //   _.each(data.prod, (item) => {
  //     item.type = 'read-only' // 特殊标识,判断入口 为keepAlive使用
  //   })
  //   userInfo.value = data;
  //   emptyStatus.value = false;
  // }
  const donateData = await prepareDonateAPI({ perf_id: $route.query.perf_id });
  donateInfo.value = donateData.data;
});

/******** ******/

// 绑定页面数据
// tslint:disable-next-line: variable-name
const prod = ref([]);
const limit = ref(30)
const offset = ref(0)

// 处理书籍下作品列表
const loading = ref(false);
const finished = ref(false);

// 因为不能让空图标提前出来的写法
const finishedTextStatus = ref(false);

/**
 * 向下滚动查询数据
 */
const onLoad = async () => {
  // 异步更新数据
  const { data, code } = await perfInfoAPI({ perf_id: $route.query.perf_id, limit: limit.value, offset: offset.value })
  if (code === 1) {
    _.each(data.prod, (item) => {
      item.type = 'read-only' // 特殊标识,判断入口 为keepAlive使用
    })
    userInfo.value = data;
    prod.value = _.concat(prod.value, data.prod);
    prod.value = _.uniqBy(prod.value, 'id');
    offset.value = prod.value.length;
    loading.value = false;
    // 数据全部加载完成
    if (prod.value.length === data.prod_num) {
      // 加载状态结束
      finished.value = true;
    }
    // 空数据提示
    if (!prod.value.length) {
      finishedTextStatus.value = false;
    }
    emptyStatus.value = Object.is(prod.value.length, 0);
  }
};

/******** ********/
// 弹出捐赠弹框模块
const showDonate = ref(false);

const toDonate = () => {
  showDonate.value = true;
}

const closeDonate = (v) => {
  showDonate.value = v;
}

// 关注个人用户
const followUser = async () => {
  const { msg } = await addFollowAPI({ perf_id: $route.query.perf_id });
  if (msg === 'add follow OK') {
    userInfo.value.is_follow = 1
    Toast.success('关注成功')
  } else {
    userInfo.value.is_follow = 0
    Toast.success('取消关注')
  }
};

/****************** keepAlive 模块 *******************/

// TAG: keepAlive 缓存页面
// addPages()

// onActivated(() => { // keepAlive 重置后执行回调
//   // TAG: pinia应用,动态刷新数据
//   // 处理数据未刷新数据显示问题
//   const { video_detail } = storeToRefs(store);
//   // 如果作品信息有变化及时修正
//   const arr = ref([]);
//   _.each(userInfo.value.prod, (item) => {
//     if (item.id === video_detail.value.id) {
//       item = video_detail.value
//     }
//     arr.value.push(item);
//   })
//   // 触发更新
//   userInfo.value.prod = arr.value;
//   // 滚动恢复
//   resetScrollTop('scrollTopPerson');
// });

onBeforeRouteLeave(() => {
  store.changeScrollTopPerson(window.scrollY)
})

/*********************************************************/

setTimeout(() => {
  // TAG:微信分享
  sharePage({ title: `${userInfo.value.name}-${userInfo.value.kg_name}`, imgUrl: userInfo.value.avatar });
}, 500);
</script>

<style lang="less" scoped>
.person-index-page {
  .header-wrapper {
    // background: linear-gradient(310deg, #FDD347 0%, #FFED6D 100%);
    // background: @base-color;
    // background: #CFF;
    // background-image: url('@images/bg@2x.png');
    background-image: url('http://gyzs.onwall.cn/bg%402x.png');
    background-size: cover;

    .info {
      padding: 2rem;
      padding-right: 0;

      .text-wrapper {
        line-height: 1.5;

        .username {
          display: inline-block;
          overflow: auto;
          font-size: 1.15rem;
          color: #222222;
        }

        .toggle-user {
          float: right;
          font-size: 0.8rem;
          background-color: @base-font-color;
          border-radius: 15px;
          padding: 5px 10px;
          color: @base-color;
        }
      }

      .address {
        font-size: 0.85rem;
        color: #999999;
      }
    }

    .sub-data {
      text-align: center;
      overflow: auto;
      padding-bottom: 1rem;

      .un-tap-color {
        color: #666666;
      }

      .tap-color {
        color: #713610;
      }

      .divide {
        line-height: 2.5;
        color: #999999;
        font-size: 1rem;
      }
    }
  }

  .list-title {
    padding: 0 1rem;
    background-color: #F7F7F7;

    .title {
      color: #222222;
      font-size: 1.1rem;
      border-bottom: 2px solid @base-color;
      padding: 0.5rem;
      text-align: center;
    }
  }

  .donate-bar {
    z-index: 999;
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    box-sizing: content-box;
    background-color: white;
    padding: 1rem;
    box-shadow: 0px -2px 4px 0px rgba(0, 0, 0, 0.07);

    .text {
      display: flex;
      // flex-direction: column;
      justify-content: center;
      // flex: 1;
      color: #713610;
      text-align: center;
    }

    .button {
      display: flex;
      flex-direction: column;
      justify-content: center;
      flex: 1;
      padding: 0 0.5rem;
    }
  }
}
</style>