98 lines
1.8 KiB
Vue
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>
|