Browse Source

feat: 优化模型卡片展示,添加背景色和状态图标

pull/64/head
chenjiale 1 month ago
parent
commit
f88400e17d
  1. 179
      src/views/model/list/ModelCard.vue

179
src/views/model/list/ModelCard.vue

@ -37,14 +37,26 @@ const modelCardList = ref<Array<ModelItem>>([])
const lastQuery = ref<ModelQueryParams | null>(null)
const colors = ['#8dc63f', '#dbb09e']
const statusStr = ['未下装', '已下装']
const icons = ['material-symbols:lock-open-right-outline', 'material-symbols:lock-outline']
const statusIcons = ['material-symbols:lock-open', 'material-symbols:lock']
const buildQuery = (value: any): ModelQueryParams => ({
function colorToBg(hex: string, alpha = 0.5) {
const raw = (hex || '').replace('#', '')
if (raw.length !== 6)
return 'rgba(0,0,0,0.5)'
const r = Number.parseInt(raw.slice(0, 2), 16)
const g = Number.parseInt(raw.slice(2, 4), 16)
const b = Number.parseInt(raw.slice(4, 6), 16)
return `rgba(${r}, ${g}, ${b}, ${alpha})`
}
function buildQuery(value: any): ModelQueryParams {
return {
unitId: value?.unit,
typeId: value?.type,
systemId: value?.system,
name: value?.name,
})
}
}
async function loadModelList(value: any) {
const queryParams = buildQuery(value)
@ -61,7 +73,7 @@ async function loadModelList(value: any) {
id: modelCard.id,
title: modelCard.name,
version: modelCard.version,
icon: icons[statusIndex],
icon: statusIcons[statusIndex],
value: 1,
total: 1,
color: colors[statusIndex],
@ -69,14 +81,10 @@ async function loadModelList(value: any) {
creator: modelCard.creator,
createTime: modelCard.createTime,
description: modelCard.name,
headStyle: {
backgroundColor: colors[statusIndex],
fontSize: '20px',
},
bodyStyle: {
borderColor: colors[statusIndex],
borderWidth: '1px',
},
headStyle: {},
bodyStyle: {},
statusColor: colors[statusIndex],
cardBg: colorToBg(colors[statusIndex]),
}
cardList.push(card)
}
@ -100,23 +108,40 @@ async function confirmDelete(id: number | string) {
<template>
<div class="enter-y">
<div class="grid gap-4 md:grid-cols-4">
<div class="card-grid">
<template v-for="item in modelCardList" :key="item.title">
<Dropdown :trigger="['contextmenu']">
<Card
size="small"
:loading="loading"
:title="item.title"
:hoverable="true"
:body-style="item.bodyStyle"
:head-style="item.headStyle"
class="model-card"
:style="{ backgroundColor: item.cardBg }"
@click="changeModel(item.id, item.version)"
>
<template #extra>
<Icon :icon="item.icon" :size="30" color="white" />
</template>
<div class="grid p-2 px-5 md:grid-cols-3">
<span>创建人: {{ item.creator }}</span><span>创建时间: {{ item.createTime }}</span><span>模型状态: {{ item.status }}</span>
<div class="card-top">
<div class="card-title">
{{ item.title }}
</div>
<div class="card-tags">
<span class="status-icon" :style="{ color: item.statusColor }">
<Icon :icon="item.icon" :size="20" />
</span>
</div>
</div>
<div class="card-meta">
<span class="meta-item">
<Icon icon="ic:baseline-person" :size="16" class="meta-icon" />
{{ item.creator || '未知' }}
</span>
<span class="meta-item">
<Icon icon="solar:calendar-bold" :size="16" class="meta-icon" />
{{ item.createTime || '--' }}
</span>
</div>
<div class="card-footer">
<span class="footer-text">版本</span>
<span class="footer-text strong">{{ item.version || 'v-test' }}</span>
</div>
</Card>
<template #overlay>
@ -143,11 +168,115 @@ async function confirmDelete(id: number | string) {
</div>
</template>
<style>
.icon-card {
<style scoped>
.card-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 20px;
}
.model-card {
padding: 12px;
border: 1px solid rgb(0 0 0 / 2%);
border-radius: 12px;
box-shadow: 0 6px 18px rgb(0 0 0 / 6%);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.model-card:hover {
box-shadow: 0 12px 28px rgb(0 0 0 / 10%);
transform: translateY(-2px);
}
.card-top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.card-title {
padding-right: 8px;
overflow: hidden;
font-size: 18px;
font-weight: 600;
line-height: 1.4;
color: #1f2937;
text-overflow: ellipsis;
word-break: keep-all;
white-space: nowrap;
}
.card-tags {
display: inline-flex;
gap: 8px;
align-items: center;
}
.status-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
background-color: rgb(0 0 0 / 3%);
border-radius: 8px;
}
.card-meta {
display: flex;
gap: 8px;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
font-size: 12px;
color: #6b7280;
}
.meta-item {
display: inline-flex;
gap: 6px;
align-items: center;
min-width: 0;
}
.meta-icon {
color: #9ca3af;
}
.card-footer {
display: flex;
gap: 8px;
align-items: center;
padding-top: 10px;
font-size: 13px;
color: #4b5563;
border-top: 1px dashed #e5e7eb;
}
.footer-text.strong {
font-weight: 600;
}
.footer-divider {
flex: 1;
height: 1px;
border-top: 1px dashed #e5e7eb;
}
.icon-card {
display: flex;
align-items: center;
justify-content: center;
background-color: #f2f2f2;
}
min-height: 180px;
background-color: #f3f4f6;
border: 1px dashed #d1d5db;
border-radius: 12px;
transition: border-color 0.2s ease, background 0.2s ease;
}
.icon-card:hover {
background-color: #eef2ff;
border-color: #4c7af0;
}
</style>

Loading…
Cancel
Save