<script lang="ts" setup> import { computed, ref } from 'vue' import { DownOutlined, UpOutlined, } from '@ant-design/icons-vue' import type { NoviceType } from './index.d' import money from '@/assets/images/task/money.png' const { title, list, total } = defineProps({ title: { type: String, }, total: { type: Number, }, list: { type: Array as PropType<NoviceType[]>, default: () => [], }, }) const isExpanded = ref(false)// 伸缩 const singleItemHeight = 45 // 单个项目的高度 const dynamicStyle = computed(() => { let maxHeight if (isExpanded.value) { // 如果展开,那么高度应该是单个项目的高度乘以项目总数 maxHeight = singleItemHeight * list.length } else { // 如果没有展开,那么高度应该是单个项目的高度乘以默认显示的项目个数 maxHeight = 180 } return { 'max-height': `${maxHeight}px`, } }) </script> <template> <div class="nvoice-task-box"> <div class="title"> {{ title }} </div> <div class="nvoice-contant"> <div class="top flex justify-between"> <div class="left"> 全部完成可获得 {{ total }} 点数 </div> <div class="right"> 已完成 1/12 </div> </div> <div class="content" :style="dynamicStyle"> <div class="earn-list-box"> <div v-for="(item, index) in list" :key="index" class="earn-list"> <div class="earn-list-left"> <div class="name"> {{ item.name }} </div> <div v-show="item.status === 1" class="accomplish"> 已获得{{ item.score }}点数 </div> <div v-show="item.status === 0" class="unfinished"> 0/{{ item.score }} </div> </div> <div class="earn-list-right"> <div class="add-dot-box"> <div class="flex items-center"> <img class="add-dot-photo" :src="money" alt=""> <div class="add-dot-num"> +{{ item.score }} </div> </div> <div v-show="item.status === 2" class="add-dot-btn accomplish"> 已完成 </div> <div v-show="item.status === 1" class="add-dot-btn finished"> 领取 </div> <div v-if="item.status === 0" class="add-dot-btn unfinished"> 未完成 </div> </div> </div> </div> </div> </div> <div v-if="list.length > 4" class="shrink" @click="isExpanded = !isExpanded"> <DownOutlined v-if="!isExpanded" /> <UpOutlined v-else /> </div> </div> </div> </template> <style lang="scss" scoped> .nvoice-task-box { width: 95%; .title { font-size: 14px; font-family: PingFang-SC, PingFang-SC; font-weight: bold; color: #000000; line-height: 22px; letter-spacing: 1px; margin: 16px 0; } .nvoice-contant { width: 100%; position: relative; background-color: #edf3ff; border-radius: 15px; padding-bottom: 15px; .top { padding: 12px 40px; .left { font-size: 14px; font-family: PingFangSC, PingFang SC; font-weight: 400; color: #4670e3; letter-spacing: 1px; } .right { font-size: 14px; font-family: PingFangSC, PingFang SC; font-weight: 400; color: #888c90; letter-spacing: 1px; } } .content { width: 95%; background-color: #fff; margin: 0 auto; overflow: hidden; transition: max-height 0.4s ease-in-out; padding: 5px 20px; border-radius: 10px; position: relative; .earn-list-box { width: 100%; padding: 0 10px; .earn-list { width: 100%; display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #ededed; &:last-child { border: 0; } .earn-list-left { display: flex; align-items: center; width: 85%; .name { font-size: 13px; font-family: PingFangSC, PingFang SC; font-weight: 500; color: #000000; letter-spacing: 1px; } .accomplish { font-size: 11px; font-family: PingFangSC, PingFang SC; font-weight: 400; color: #f7b606; padding-left: 10px; } .unfinished { font-size: 11px; font-family: PingFangSC, PingFang SC; font-weight: 400; color: #888c90; padding-left: 10px; } } .earn-list-right { width: 15%; .add-dot-box { width: 100%; display: flex; align-items: center; justify-content: space-between; .add-dot-photo { width: 13px; height: 13px; display: flex; align-items: center; } .add-dot-num { font-size: 12px; font-family: PingFangSC, PingFang SC; font-weight: 400; color: #f7b500; padding-left: 3px; } .add-dot-btn { width: 50px; border-radius: 16px; font-size: 11px; font-family: PingFangSC, PingFang SC; font-weight: 400; line-height: 20px; letter-spacing: 1px; text-align: center; padding: 2px 5px; &.accomplish { background: linear-gradient(90deg, #b5ceff 0%, #a6baff 100%); color: #ffffff; } &.finished { background: linear-gradient(90deg, #6fa3ff 0%, #486dff 100%); color: #ffffff; cursor: pointer; } &.unfinished { background: #ffffff; border: 1px solid #cdcdcd; line-height: 18px; color: #888c90; } } } } } } } .shrink { width: 32px; height: 32px; text-align: center; line-height: 32px; border-radius: 50%; background-color: #fff; text-align: center; box-shadow: 0px 2px 8px 0px rgba(131, 131, 131, 0.5); position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%); } } } </style>