130 lines
3.1 KiB
Vue
130 lines
3.1 KiB
Vue
|
|
<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>
|