Files
ai-kefu-admin/admin/src/views/config/center/ConfigCard.vue
T

147 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
视觉基线卡壳(spec §4):三行卡头(图标+任务名 → 一句话说明 → 组级信息条)
+ 底部操作条(左 回滚链接 / 右 备注选填+保存——均 slot)+ 底部危险行。
只管布局与样式,不含任何业务逻辑。
-->
<template>
<ElCard shadow="never" class="config-card">
<template #header>
<div class="cc-header">
<div class="cc-title-row">
<ArtSvgIcon v-if="icon" :icon="icon" class="cc-icon" />
<span class="cc-title">{{ title }}</span>
</div>
<p v-if="subtitle" class="cc-subtitle">{{ subtitle }}</p>
<div v-if="info || $slots.info" class="cc-info">
<slot name="info">
<ArtSvgIcon icon="solar:info-circle-line-duotone" class="cc-info-icon" />
<span>{{ info }}</span>
</slot>
</div>
</div>
</template>
<slot />
<div v-if="$slots['footer-left'] || $slots['footer-right']" class="cc-footer">
<div class="cc-footer-left">
<slot name="footer-left" />
</div>
<div class="cc-footer-right">
<slot name="footer-right" />
</div>
</div>
<div v-if="dangerLabel || $slots.danger" class="cc-danger">
<span class="cc-danger-text">{{ dangerLabel }}</span>
<slot name="danger" />
</div>
</ElCard>
</template>
<script setup lang="ts">
defineOptions({ name: 'ConfigCard' })
defineProps<{
/** ArtSvgIcon 图标名(如 solar:palette-round-line-duotone) */
icon?: string
/** 任务名(品牌与外观 / AI 话术 …) */
title: string
/** 一句话「这是干嘛的」 */
subtitle?: string
/** 组级信息条文案(整组保存 · 立即生效 · 可回滚;带 • 字段留空=默认) */
info?: string
/** 危险行文案(与 #danger slot 任一存在即渲染危险行;按钮走 #danger slot) */
dangerLabel?: string
}>()
</script>
<style scoped lang="scss">
.config-card {
:deep(.el-card__header) {
padding: 14px 20px 10px;
}
:deep(.el-card__body) {
padding: 14px 20px;
}
}
.cc-header {
.cc-title-row {
display: flex;
align-items: center;
gap: 8px;
.cc-icon {
font-size: 18px;
color: var(--art-primary, var(--el-color-primary));
}
.cc-title {
font-weight: 600;
font-size: 15px;
color: var(--el-text-color-primary);
}
}
.cc-subtitle {
margin: 2px 0 0;
font-size: 12px;
color: var(--art-gray-500, var(--el-text-color-secondary));
}
.cc-info {
display: flex;
align-items: flex-start;
gap: 6px;
margin-top: 8px;
padding: 7px 12px;
border-radius: 6px;
background: var(--el-fill-color-lighter);
font-size: 12px;
line-height: 1.6;
color: var(--art-gray-500, var(--el-text-color-secondary));
.cc-info-icon {
flex-shrink: 0;
font-size: 14px;
color: var(--art-gray-400, var(--el-text-color-placeholder));
}
}
}
.cc-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: 14px;
padding-top: 12px;
border-top: 1px dashed var(--el-border-color-lighter);
.cc-footer-right {
display: flex;
align-items: center;
gap: 8px;
}
}
.cc-danger {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: 10px;
padding: 7px 12px;
border: 1px solid var(--el-color-danger-light-7);
border-radius: 6px;
background: var(--el-color-danger-light-9);
.cc-danger-text {
font-size: 12px;
color: var(--el-color-danger);
}
}
</style>