Files

98 lines
1.8 KiB
Vue

<template>
<view
class="app-card"
:class="{ 'app-card--clickable': clickable, 'app-card--active': isActive && clickable }"
:style="cardStyle"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
@touchcancel="onTouchEnd"
>
<slot></slot>
</view>
</template>
<script>
import themeMixin from '@/mixins/themeMixin.js'
import { THEME_CHANGE_EVENT } from '@/utils/theme'
export default {
name: 'AppCard',
mixins: [themeMixin],
props: {
padding: {
type: Number,
default: 24
},
radius: {
type: Number,
default: 20
},
marginBottom: {
type: Number,
default: 24
},
showShadow: {
type: Boolean,
default: true
},
clickable: {
type: Boolean,
default: false
}
},
data() {
return {
isActive: false
}
},
computed: {
cardStyle() {
const style = {
backgroundColor: this.themeConfig.cardBgColor,
padding: `${this.padding}rpx`,
borderRadius: `${this.radius}rpx`,
marginBottom: `${this.marginBottom}rpx`
}
if (this.showShadow) {
style.boxShadow = `0 4rpx 16rpx ${this.themeConfig.shadowColor || 'rgba(0, 0, 0, 0.08)'}`
}
return style
}
},
created() {
this.syncThemeConfig()
this.watchThemeChange()
},
beforeUnmount() {
if (this.themeChangeHandler) {
uni.$off(THEME_CHANGE_EVENT, this.themeChangeHandler)
}
},
methods: {
onTouchStart() {
if (this.clickable) {
this.isActive = true
}
},
onTouchEnd() {
this.isActive = false
}
}
}
</script>
<style scoped>
.app-card {
box-sizing: border-box;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.app-card--clickable {
cursor: pointer;
}
.app-card--active {
transform: scale(0.98);
}
</style>