Files
lgp-wx-plus/components/theme/ThemeCardFrame.vue
2026-08-19 08:17:18 +08:00

130 lines
3.1 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.
<template>
<!-- 主题卡片外壳plain / elevated / ornament / canvas-frame effect.card 切换 -->
<view
class="theme-card"
:class="['theme-card--' + mode]"
:style="cardStyle"
>
<view v-if="mode === 'canvas-frame' || mode === 'ornament'" class="theme-card__corners" aria-hidden="true">
<view class="c c-tl" :style="cornerStyle"></view>
<view class="c c-tr" :style="cornerStyle"></view>
<view class="c c-bl" :style="cornerStyle"></view>
<view class="c c-br" :style="cornerStyle"></view>
</view>
<view v-if="mode === 'canvas-frame'" class="theme-card__folio" :style="{ borderColor: accent }"></view>
<view class="theme-card__body">
<slot />
</view>
</view>
</template>
<script>
import { getActiveLayout, getActiveVars } from '@/utils/theme'
export default {
name: 'ThemeCardFrame',
props: {
/** 覆盖 effect.card默认读当前主题 */
card: { type: String, default: '' },
},
computed: {
mode() {
if (this.card) return this.card
const effect = (getActiveLayout().effect) || {}
return effect.card || 'elevated'
},
vars() {
return getActiveVars()
},
accent() {
return this.vars['--color-primary'] || '#C9A227'
},
cardStyle() {
const v = this.vars
const base = {
background: v['--color-surface'] || '#fff',
color: v['--color-text'] || '#111',
borderRadius: v['--radius-md'] || '16rpx',
}
if (this.mode === 'plain') {
return {
...base,
border: `1rpx solid ${v['--color-border'] || '#eee'}`,
boxShadow: 'none',
}
}
if (this.mode === 'elevated') {
return {
...base,
border: `1rpx solid ${v['--color-border'] || '#eee'}`,
boxShadow: v['--shadow-md'] || '0 8rpx 24rpx rgba(0,0,0,0.06)',
}
}
// ornament / canvas-frame
return {
...base,
border: `1rpx solid ${this.accent}`,
boxShadow: this.mode === 'canvas-frame' ? 'none' : (v['--shadow-md'] || 'none'),
}
},
cornerStyle() {
return { borderColor: this.accent }
},
},
}
</script>
<style lang="scss" scoped>
.theme-card {
position: relative;
overflow: hidden;
}
.theme-card__body {
position: relative;
z-index: 1;
}
.theme-card__folio {
pointer-events: none;
position: absolute;
inset: 8rpx;
z-index: 0;
border: 1rpx solid;
opacity: 0.55;
}
.theme-card__corners .c {
position: absolute;
z-index: 2;
width: 20rpx;
height: 20rpx;
border-style: solid;
border-width: 0;
}
.theme-card__corners .c-tl {
top: 8rpx;
left: 8rpx;
border-top-width: 2rpx;
border-left-width: 2rpx;
}
.theme-card__corners .c-tr {
top: 8rpx;
right: 8rpx;
border-top-width: 2rpx;
border-right-width: 2rpx;
}
.theme-card__corners .c-bl {
bottom: 8rpx;
left: 8rpx;
border-bottom-width: 2rpx;
border-left-width: 2rpx;
}
.theme-card__corners .c-br {
right: 8rpx;
bottom: 8rpx;
border-right-width: 2rpx;
border-bottom-width: 2rpx;
}
.theme-card--ornament {
clip-path: polygon(0 0, calc(100% - 16rpx) 0, 100% 16rpx, 100% 100%, 16rpx 100%, 0 calc(100% - 16rpx));
}
</style>