FormGroup.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <template>
  2. <FlexCol
  3. :innerClass="[
  4. 'dynamic-form-group',
  5. {
  6. 'collapsed': collapsed,
  7. 'collapsible': collapsible,
  8. 'plain': plain,
  9. }
  10. ]"
  11. :innerStyle="dynamicFormGroupStyle"
  12. >
  13. <Touchable
  14. v-if="title"
  15. innerClass="title"
  16. direction="row"
  17. :innerStyle="dynamicFormGroupTitleWraperStyle"
  18. @click="collapsible ? collapsed = !collapsed : null"
  19. >
  20. <span :style="dynamicFormGroupTitleStyle">{{ title }}</span>
  21. <FlexRow align="center">
  22. <text :style="dynamicFormGroupTitleStyle" v-show="collapsed">点击展开更多</text>
  23. <Icon
  24. v-if="collapsible"
  25. :size="theme.resolveThemeSize('DynamicFormGroupIconSize', 22)"
  26. icon="arrow-down"
  27. innerClass="collapsible-icon"
  28. />
  29. </FlexRow>
  30. </Touchable>
  31. <Row v-if="!collapsed" :justify="(justify as any)" :gutter="gutter">
  32. <slot />
  33. </Row>
  34. </FlexCol>
  35. </template>
  36. <script lang="ts" setup>
  37. import { computed, ref } from "vue";
  38. import Row from "@/components/layout/grid/Row.vue";
  39. import Icon from "@/components/basic/Icon.vue";
  40. import { useTheme } from "@/components/theme/ThemeDefine";
  41. import FlexRow from "@/components/layout/FlexRow.vue";
  42. import Touchable from "@/components/feedback/Touchable.vue";
  43. import FlexCol from "@/components/layout/FlexCol.vue";
  44. const props = defineProps({
  45. /**
  46. * 标题
  47. */
  48. title: {
  49. type: String,
  50. default: "",
  51. },
  52. /**
  53. * 栅格间隔 px
  54. */
  55. gutter: {
  56. type: Number,
  57. default: null,
  58. },
  59. /**
  60. * flex 布局下的水平排列方式:start end center space-around space-between
  61. */
  62. justify: {
  63. type: String,
  64. default: "start",
  65. },
  66. /**
  67. * 是否可折叠
  68. */
  69. collapsible: {
  70. type: Boolean,
  71. default: false,
  72. },
  73. /**
  74. * 是否为朴素样式
  75. */
  76. plain: {
  77. type: Boolean,
  78. default: false,
  79. },
  80. /**
  81. * 是否默认折叠
  82. */
  83. collapsed: {
  84. type: Boolean,
  85. default: false,
  86. },
  87. });
  88. const theme = useTheme();
  89. const collapsed = ref(props.collapsed);
  90. const dynamicFormGroupStyle = computed(() => ({
  91. backgroundColor: theme.resolveThemeColor('DynamicFormGroupBackgroundColor', 'white'),
  92. borderRadius: theme.resolveThemeSize('DynamicFormGroupBorderRadius', 10),
  93. padding: `${theme.resolveThemeSize('DynamicFormGroupPaddingVertical', 10)} ${theme.resolveThemeSize('DynamicFormGroupPaddingHorizontal', 0)}`,
  94. marginBottom: theme.resolveThemeSize('DynamicFormGroupMarginBottom', 12),
  95. }));
  96. const dynamicFormGroupTitleWraperStyle = computed(() => ({
  97. marginBottom: theme.resolveThemeSize('DynamicFormGroupTitleMarginBottom', 12),
  98. }));
  99. const dynamicFormGroupTitleStyle = computed(() => ({
  100. fontSize: theme.resolveThemeSize('DynamicFormGroupTitleFontSize', 25),
  101. color: theme.resolveThemeColor('DynamicFormGroupTitleColor', 'text.second')
  102. }));
  103. defineOptions({
  104. options: {
  105. virtualHost: true,
  106. inheritAttrs: false,
  107. styleIsolation: 'shared',
  108. }
  109. })
  110. </script>
  111. <style lang="scss">
  112. .dynamic-form-group {
  113. &.collapsed {
  114. .collapsible-icon {
  115. transform: rotate(0deg);
  116. }
  117. }
  118. &.collapsible {
  119. .title {
  120. cursor: pointer;
  121. }
  122. }
  123. .collapsible-icon {
  124. transform: rotate(180deg);
  125. transition: transform 0.3s ease-in-out;
  126. }
  127. .title {
  128. display: flex;
  129. align-items: center;
  130. justify-content: space-between;
  131. .title-right {
  132. display: flex;
  133. flex-direction: row;
  134. align-items: center;
  135. }
  136. }
  137. &.plain {
  138. padding: 0;
  139. background-color: transparent;
  140. }
  141. }
  142. </style>