LOADING

加载过慢请开启缓存 浏览器默认开启

好看的卡片设计

好看的卡片

  • 简介卡片

@\components\myAside.vue

<-template->  
    <-div v-if="asideshow.user" class="card-content1 shadow-box background-opacity"->
        <-el-avatar style="margin-top: 20px" class="user-avatar" :size="120" :src="userInfo.userPic"-><-/el-avatar->
        <-div class="web-name"->{{ userInfo.username }}<-/div->
        <-div class="web-info"->
          <-div class="blog-info-box"->
            <-span->昵称<-/span->
            <-span class="blog-info-num"->{{ userInfo.nickname }}<-/span->
          <-/div->
          <-div class="blog-info-box"->
            <-span->名称<-/span->
            <-span class="blog-info-num"->{{ userInfo.username }}<-/span->
          <-/div->
          <-div class="blog-info-box"->
            <-span->身份<-/span->
            <-span class="blog-info-num"->{{ userInfo.identity }}<-/span->
          <-/div->
        <-/div->
        <-a class="collection-btn"->
          <-i class="el-icon-star-off" style="margin-right: 2px"-><-/i->{{ userInfo.email }}
        <-/a->
      <-/div->
<-/template->

style

<-style scoped->
    .card-content1 {
        background: linear-gradient(-45deg, #e8d8b9, #eccec5, #a3e9eb, #bdbdf0, #eec1ea);
        background-size: 400% 400%;
        animation: gradientBG 10s ease infinite;
        display: flex;
        flex-direction: column;
        align-items: center;
        border-radius: 10px;
        position: relative;
        overflow: hidden;
    }

    .card-content1 :not(:first-child) {
        z-index: 10;
    }

    .web-name {
      font-size: 30px;
      font-weight: bold;
      margin: 20px 0;
    }

    .web-info {
      width: 80%;
      display: flex;
      flex-direction: row;
      justify-content: space-around;
    }

    .blog-info-box {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: space-around;
    }

    .blog-info-num {
      margin-top: 12px;
    }

    .collection-btn {
      position: relative;
      margin-top: 12px;
      background: var(--lightGreen);
      cursor: pointer;
      width: 65%;
      height: 35px;
      border-radius: 1rem;
      text-align: center;
      line-height: 35px;
      color: var(--white);
      overflow: hidden;
      z-index: 1;
      margin-bottom: 25px;
    }

    .collection-btn::before {
      background: var(--gradualRed);
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      content: "";
      transform: scaleX(0);
      transform-origin: 0;
      transition: transform 0.5s ease-out;
      transition-timing-function: cubic-bezier(0.45, 1.64, 0.47, 0.66);
      border-radius: 1rem;
      z-index: -1;
    }

    .collection-btn:hover::before {
      transform: scaleX(1);
    }

    .shadow-box {
        box-shadow: 0 1px 20px -6px var(--borderColor);
        transition: all 0.3s ease;
    }

    .shadow-box:hover {
        box-shadow: 0 5px 10px 5px var(--borderHoverColor);
    }

<-/style->
  • 博客卡片

@\components\common\ResourceCardList.vue

<-template->
  <-div class="card-container" v-if="resourcePathList.length"->
    <-div v-for="(resourcePath, index) in resourcePathList"
         :key="index"
         class="card-item shadow-box wow"
         @click="clickResourcePath(resourcePath)"->
      <-div class="card-image"->
        <-el-image class="my-el-image"
                  v-once
                  lazy
                  :src="resourcePath.cover"
                  fit="cover"->
          <-template #error->
            <-div class="image-slot myCenter" style="background-color: var(--lightGreen)"->
              <-div class="error-text"->
                <-div->遇事不决,可问春风<-/div->
              <-/div->
            <-/div->
          <-/template->
        <-/el-image->
      <-/div->
      <-div class="card-body"->
        <-div class="card-title"->
          <-span v-if="resourcePath.recommendStatus"->
            🔥
          <-/span->
          {{ resourcePath.title }}
        <-/div->
        <-div class="card-desc"->
          {{ resourcePath.introduction }}
        <-/div->
        <-div class="card-time"->
          <-svg viewBox="0 0 1024 1024" width="14" height="14" style="vertical-align: -2px;"->
            <-path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#409EFF"-><-/path->
            <-path
              d="M654.222222 256c-17.066667 0-28.444444 11.377778-28.444444 28.444444v56.888889c0 17.066667 11.377778 28.444444 28.444444 28.444445s28.444444-11.377778 28.444445-28.444445v-56.888889c0-17.066667-11.377778-28.444444-28.444445-28.444444zM369.777778 256c-17.066667 0-28.444444 11.377778-28.444445 28.444444v56.888889c0 17.066667 11.377778 28.444444 28.444445 28.444445s28.444444-11.377778 28.444444-28.444445v-56.888889c0-17.066667-11.377778-28.444444-28.444444-28.444444z"
              fill="#FFFFFF"-><-/path->
            <-path
              d="M725.333333 312.888889H711.111111v28.444444c0 31.288889-25.6 56.888889-56.888889 56.888889s-56.888889-25.6-56.888889-56.888889v-28.444444h-170.666666v28.444444c0 31.288889-25.6 56.888889-56.888889 56.888889s-56.888889-25.6-56.888889-56.888889v-28.444444h-14.222222c-22.755556 0-42.666667 19.911111-42.666667 42.666667v341.333333c0 22.755556 19.911111 42.666667 42.666667 42.666667h426.666666c22.755556 0 42.666667-19.911111 42.666667-42.666667v-341.333333c0-22.755556-19.911111-42.666667-42.666667-42.666667zM426.666667 654.222222h-56.888889c-17.066667 0-28.444444-11.377778-28.444445-28.444444s11.377778-28.444444 28.444445-28.444445h56.888889c17.066667 0 28.444444 11.377778 28.444444 28.444445s-11.377778 28.444444-28.444444 28.444444z m227.555555 0h-56.888889c-17.066667 0-28.444444-11.377778-28.444444-28.444444s11.377778-28.444444 28.444444-28.444445h56.888889c17.066667 0 28.444444 11.377778 28.444445 28.444445s-11.377778 28.444444-28.444445 28.444444z m0-113.777778h-56.888889c-17.066667 0-28.444444-11.377778-28.444444-28.444444s11.377778-28.444444 28.444444-28.444444h56.888889c17.066667 0 28.444444 11.377778 28.444445 28.444444s-11.377778 28.444444-28.444445 28.444444z"
              fill="#FFFFFF"-><-/path->
          <-/svg->
          发布于 {{ getDateDiff(resourcePath.createTime) }}
        <-/div->
      <-/div->
    <-/div->
  <-/div->
<-/template->

<-script setup->
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  resourcePathList: {
    type: Array,
    required: true
  }
});

const emit = defineEmits(['clickResourcePath']);

function clickResourcePath(resourcePath) {
  emit("clickResourcePath", resourcePath.id);
}

function getDateDiff(date) {
  const now = new Date();
  const past = new Date(date);
  const diff = now - past;

  const seconds = Math.floor(diff / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);
  const months = Math.floor(days / 30);
  const years = Math.floor(days / 365);

  if (years -> 0) {
    return `${years}年前`;
  } else if (months -> 0) {
    return `${months}个月前`;
  } else if (days -> 0) {
    return `${days}天前`;
  } else if (hours -> 0) {
    return `${hours}小时前`;
  } else if (minutes -> 0) {
    return `${minutes}分钟前`;
  } else {
    return `刚刚`;
  }
}



<-/script->

<-style scoped->

  .card-container {
    display: flex;
    flex-wrap: wrap;
  }

  .card-item {
    position: relative;
    border-radius: 10px;
    background: rgba(255, 255, 255, .88);
    overflow: hidden;
    margin: 10px;
    height: 300px;
    flex-shrink: 0;
    width: calc(100% / 3 - 20px);
    cursor: pointer;
    animation: zoomIn 0.8s ease-in-out;
  }

  .card-image {
    width: 100%;
    height: 180px;
  }

  .card-image ->->-> .el-image__inner {
    transition: all 1s;
  }

  .card-image ->->-> .el-image__inner:hover {
    transform: scale(1.2);
  }

  .card-body {
    padding: 10px 20px;
  }

  .card-title {
    font-size: 18px;
    font-weight: 600;
    margin-bottom: 10px;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    transition: all .2s ease-in-out;
  }

  .card-title:hover {
    color: var(--lightGreen);
  }

  .card-desc {
    font-size: 14px;
    line-height: 1.5;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    letter-spacing: 1px;
  }

  .card-time {
    position: absolute;
    bottom: 10px;
    font-size: 12px;
    color: var(--greyFont);
  }

  @media screen and (max-width: 700px) {
    .card-item {
      width: calc(100% / 2 - 20px);
    }
  }

  @media screen and (max-width: 500px) {
    .card-item {
      width: calc(100% - 20px);
    }
  }

<-/style->

@\stores\patients.js

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { DPatientsService } from '@/api/bind.js'  // 假设你的服务文件路径是 @/services/apiService


const usePatientsInfoStore = defineStore('patients', () =-> {
    const infos = ref([])

    // 获取用户信息并更新 store
    const fetchInfos = async () =-> {

        infos.value = []
        try {
            const response = await DPatientsService()
            console.log('API Response:', response)  // 调试输出
            if (response.code === 0) {  // 确保响应成功
                infos.value = response.data
                console.log('Fetched Infos:', infos.value)  // 调试输出
            }
            else {
                console.error('Error fetching patients info:', response.message)
            }
        } catch (error) {
            console.log('Its OK')
        }
    }

    const setInfo = (newInfos) =-> {
        infos.value = newInfos
    }

    const removeInfo = () =-> {
        infos.value = []
    }

    const clearUserData = () =-> {
        infos.value = []
    }

    return { infos, setInfo, removeInfo, fetchInfos, clearUserData }
}, { persist: true })

export default usePatientsInfoStore

@\components\user.vue

<-template->    
    <-div v-if="userInfo.identity === 'patient'"->
      <-ResourceCardList :resourcePathList="resourcePathList" @clickResourcePath="handleResourceClick" /->
    <-/div->
<-/template-> 

<-script setup->
import ResourceCardList from '@/components/common/ResourceCardList.vue';

const resourcePathList = computed(() =-> {
  return filesInfo.value.map((info, index) =-> ({
    cover: info.url || 'https://aircraft-1111.oss-cn-beijing.aliyuncs.com/mr_train_1001_middle_slice.jpg',
    title: info.fileName,
    introduction: '一个 nii 图像',
    recommendStatus: true,
    createTime: '2024-08-15T00:00:00Z',
    url: '/demo',
    id: info.id
  }))
})

async function handleResourceClick(id) {
  console.log('Clicked image id:', id);

  imageStore.setImgId(id);   // 设置图片ID

  await imageStore.fetchImages(id);  // 等待获取图片完成

  router.push('/demo');  // 获取图片后跳转到/demo路由
}

<-/script->
  • 列表卡片

@\components\common\userCard.vue

<-template->
  <-div class="card-content shadow-box-mini" @click="handleClick"->
    <-div->
      <-el-avatar :size="avatarSize" :src="avatarSrc"-><-/el-avatar->
    <-/div->
    <-div class="card-right"->
      <-div class="card-title"->{{ title }}<-/div->
      <-div class="card-desc"->{{ description }}<-/div->
    <-/div->
  <-/div->
<-/template->

<-script setup->
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  avatarSize: {
    type: Number,
    default: 100
  },
  avatarSrc: {
    type: String,
    required: true
  },
  title: {
    type: String,
    default: '时光相册'
  },
  description: {
    type: String,
    default: '📸记录美好瞬间'
  },
  clickValue: {
    type: Number,
    default: 2
  }
});

const emit = defineEmits();

function handleClick() {
  emit('card-click', props.clickValue);
}
<-/script->

<-style scoped->
.card-content {
  display: flex;
  padding: 25px;
  margin: 25px 0;
  border-radius: 20px;
  width: 100%;
  cursor: pointer;
  transition: all 0.3s;
  background: var(--background);
}

.card-content:hover {
  /* Add hover effects if needed */
}

.card-right {
  margin-left: 20px;
}

.card-title {
  font-size: 1.6rem;
  letter-spacing: 0.2rem;
  line-height: 3.5rem;
  font-weight: 700;
}

.card-desc {
  font-size: 1.1rem;
  letter-spacing: 0.2rem;
  color: #777777;
}
<-/style->

@\components\cardList.vue

<-template->
  <-div class="card-list"->
    <-CardComponent
      v-for="(card, index) in cards"
      :key="index"
      :avatarSrc="card.avatarSrc"
      :title="card.title"
      :description="card.description"
      @card-click="handleCardClick(card.id)"
    /->
  <-/div->
<-/template->

<-script setup->
import { defineProps, defineEmits } from 'vue';
import CardComponent from '@/components/common/userCard.vue'; // 确保路径正确

const props = defineProps({
  cards: {
    type: Array,
    required: true
  }
});

const emit = defineEmits();

function handleCardClick(id) {
  emit('card-click', id);
}
<-/script->

<-style scoped->
.card-list {
  display: flex;
  flex-direction: column;
  width: 100%;
}
<-/style->

@\components\user.vue

<-template->
   <-CardList
    v-if="userInfo.identity === 'doctor'"
    :cards="cardData"
    @card-click="handleCardClick"
    /->
<-/template->

<-script setup->

import CardList from '@/components/CardList.vue';
const cardData = computed(() =-> {
  return patientsInfos.value.map((info, index) =-> ({
    id: info.id,
    avatarSrc: info.userPic || IU,  // 这里假设所有卡片使用相同的图片
    title: `${info.username} (${info.nickname})`,
    description: `📸Comment : ${info.comment}`
  }))
})

function handleCardClick(id) {
  console.log('Card clicked with ID:', id);
  findPatientInfo(id)
  dialogVisible.value = true; // 显示弹窗
  console.log("dialogVisible : " + dialogVisible.value)
  getFilesName();
}
<-/script->