Skip to content

Commit

Permalink
[add]新增collapseCard组件
Browse files Browse the repository at this point in the history
  • Loading branch information
chenxianhuii committed Feb 18, 2025
1 parent 5343c69 commit f8c94fc
Show file tree
Hide file tree
Showing 6 changed files with 413 additions and 78 deletions.
159 changes: 159 additions & 0 deletions vue3/packages/common/components/collapse-card/collapseCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<template>
<div class="sm-component-collapse-card" :style="getTextColorStyle">
<div
v-if="iconClass"
:class="{
['sm-component-collapse-card__icon']: true,
['is-' + position]: true,
[`is-click-${isShow ? 'out' : 'in'}`]: true,
['is-not-header']: !headerName,
['icon-box-shadow']: !isShow
}"
:style="[collapseCardHeaderBgStyle, headingTextColorStyle]"
@click="iconClicked"
>
<!-- <i :style="iconStyle" :class="{ [iconClass]: true, ['is-auto-rotate']: autoRotate }" /> -->
<SwitcherOutlined />
</div>
<transition name="sm-component-zoom-in" @after-leave="toggleTransition('leave')" @enter="toggleTransition('enter')">
<div
v-show="isShow"
:class="{
['sm-component-collapse-card__content']: true,
['is-not-header']: !headerName,
['is-' + position]: true,
['is-icon']: iconClass
}"
:style="getCardStyle"
>
<div
v-if="headerName"
:class="{'sm-component-collapse-card__header': true, 'with-split-line': splitLine, ['is-' + position]: true}"
:style="[collapseCardHeaderBgStyle, headingTextColorStyle]"
>
<span class="sm-component-collapse-card__header-name">{{ headerName }}</span>
</div>
<div :style="getCardStyle" class="sm-component-collapse-card__body">
<slot></slot>
</div>
</div>
</transition>
</div>
</template>

<script setup>
// import Theme from 'vue-iclient/src/common/_mixin/Theme';
import { ref, computed, watch, onMounted, onBeforeMount, nextTick } from 'vue';
import { SwitcherOutlined } from '@ant-design/icons-vue';
const props = defineProps({
iconPosition: {
type: String,
default: 'top-left'
},
iconClass: {
type: String
},
autoRotate: {
type: Boolean,
default: false
},
headerName: {
type: String
},
collapsed: {
type: Boolean,
default: false
},
splitLine: {
type: Boolean,
default: true
}
});
const isShow = ref(true);
const transform = ref(null);
// 计算属性
const getCardStyle = computed(() => {
const style = { background: 'transparent' };
// return !props.iconClass && !props.headerName ? style : collapseCardBackgroundStyle;
return !props.iconClass && !props.headerName ? style : {};
});
const iconStyle = computed(() => {
return {
transform: transform.value
};
});
const position = computed(() => props.iconPosition);
const rotateDeg = computed(() => {
return {
'top-right': ['rotate(-45deg)', 'rotate(135deg)'],
'top-left': ['rotate(-135deg)', 'rotate(45deg)'],
'bottom-left': ['rotate(135deg)', 'rotate(-45deg)'],
'bottom-right': ['rotate(45deg)', 'rotate(-135deg)']
};
});
const hasHeaderRotateDeg = computed(() => {
return {
'top-right': ['rotate(-45deg)', 'rotate(135deg)'],
'top-left': ['rotate(-135deg)', 'rotate(45deg)'],
'bottom-left': ['rotate(-135deg)', 'rotate(45deg)'],
'bottom-right': ['rotate(-45deg)', 'rotate(135deg)']
};
});
// watch 监听
watch(() => props.iconClass, (newVal, oldVal) => {
if (newVal && !oldVal) {
isShow.value = !props.collapsed;
toggleTransition(props.collapsed ? 'leave' : 'enter');
} else if (!newVal) {
// 如果iconClass 为空 则默认显示内容
isShow.value = true;
}
});
watch(() => props.iconPosition, () => {
resetIconTransform();
});
if (props.iconClass) {
isShow.value = !props.collapsed;
}
resetIconTransform();
onMounted(() => {
toggleTransition(props.collapsed ? 'leave' : 'enter');
});
function iconClicked() {
isShow.value = !isShow.value;
resetIconTransform();
emit('content-show-state', isShow.value);
};
function toggleTransition(type) {
nextTick(() => {
const iconDom = document.querySelector('.sm-component-collapse-card__icon');
if (iconDom) {
iconDom.style.position = type === 'leave' ? 'relative' : 'absolute';
}
});
};
function resetIconTransform() {
let rotateDegObj = props.headerName ? hasHeaderRotateDeg.value : rotateDeg.value;
if (props.autoRotate) {
transform.value = rotateDegObj[position.value][isShow.value ? 1 : 0];
}
};
const emit = defineEmits(['content-show-state']);
</script>

<style lang="scss"></style>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@supermapgis/common/theme-chalk/collapseCard.scss'
176 changes: 176 additions & 0 deletions vue3/packages/common/theme-chalk/collapseCard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
@use './mixins/mixins.scss' as *;
@use './base/theme.scss' as *;

@include b(collapse-card) {
$collapse-card-prefix: &;

position: relative;
overflow: visible;
font-size: 12px;
color: $text-color;
.icon-box-shadow {
box-shadow: 0 3px 13px 0px $shadow-color;
}
@include e(icon) {
z-index: 100;
background: $collapse-card-header-bg;
color: $heading-color;
cursor: pointer;
box-sizing: border-box;
font-size: 16px;
width: 32px;
height: 32px;
line-height: 32px;
text-align: center;
&:hover {
background: #ffffff;
border-color: $hover-color !important;
color: $hover-color !important;
}
> i {
display: block;
}
@include when(not-header) {
@include when(bottom-right) {
bottom: 0;
top: unset;
}
@include when(bottom-left) {
bottom: 0;
top: unset;
}
}
@include when(click-in) {
border-radius: 4px;
@include when(top-right) {
float: right;
}
@include when(bottom-right) {
float: right;
}
@include when(top-left) {
float: left !important;
}
@include when(bottom-left) {
float: left !important;
}
}
@include when(click-out) {
border: none;
background: transparent !important;
}
@include when(top-left) {
top: 0;
left: 0;
& .sm-component-collapse-card__component-icon.is-auto-rotate {
transform: rotate(45deg);
}
}
@include when(bottom-left) {
top: 0;
left: 0;
& .sm-component-collapse-card__component-icon.is-auto-rotate {
transform: rotate(45deg);
}
}
@include when(top-right) {
top: 0;
right: 0;
& .sm-component-collapse-card__component-icon.is-auto-rotate {
transform: rotate(135deg);
}
}
@include when(bottom-right) {
top: 0;
right: 0;
& .sm-component-collapse-card__component-icon.is-auto-rotate {
transform: rotate(135deg);
}
}
}

@include e(header) {
height: 32px;
line-height: 32px;
padding-left: 8px;
box-shadow: 0px 1px 0px 0px $shadow-color;
color: $heading-color;
background: $collapse-card-header-bg;
border-radius: 4px 4px 0 0;
&.with-split-line {
border-bottom: 1px solid $collapse-card-split-line;
}
+ #{$collapse-card-prefix}__body {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@include when(top-right) {
padding-right: 30px;
}
@include when(bottom-right) {
padding-right: 30px;
}
@include when(top-left) {
padding-left: 30px;
}
@include when(bottom-left) {
padding-left: 30px;
}
}
@include e(content) {
box-shadow: 0 3px 13px 0px $shadow-color;
background: $collapse-card-bg;
position: relative;
border-radius: 4px;
&.sm-component-zoom-in-enter-active {
animation: zoom-in .5s;
}
&.sm-component-zoom-in-leave-active {
animation: zoom-in .5s reverse;
}
@keyframes zoom-in {
0% {
transform: scale(0);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
@include when(top-left) {
transform-origin: top left;
@include when(icon) {
& > .sm-component-collapse-card__header {
padding-left: 38px;
}
}
}
@include when(bottom-left) {
transform-origin: top left;
@include when(icon) {
& > .sm-component-collapse-card__header {
padding-left: 38px;
}
}
}
@include when(not-header) {
@include when(bottom-right) {
transform-origin: bottom right;
}
@include when(bottom-left) {
transform-origin: bottom left;
}
}
@include when(bottom-right) {
transform-origin: top right;
}
@include when(top-right) {
transform-origin: top right;
}
}
@include e(body) {
height: 100%;
border-radius: 4px;
}
}
Loading

0 comments on commit f8c94fc

Please sign in to comment.