index.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <template>
  2. <ContentBox
  3. class="go-content-charts"
  4. :class="{ scoped: !getCharts }"
  5. title="组件"
  6. :depth="1"
  7. :backIcon="false"
  8. >
  9. <template #icon>
  10. <n-icon size="14" :depth="2">
  11. <BarChartIcon />
  12. </n-icon>
  13. </template>
  14. <!-- 图表 -->
  15. <aside>
  16. <div class="menu-width-box">
  17. <n-menu
  18. class="menu-width"
  19. v-model:value="selectValue"
  20. :options="menuOptions"
  21. :icon-size="16"
  22. :indent="18"
  23. @update:value="clickItemHandle"
  24. />
  25. <div class="menu-component-box">
  26. <transition name="component-fade" mode="out-in">
  27. <keep-alive>
  28. <component :is="selectNode"></component>
  29. </keep-alive>
  30. </transition>
  31. </div>
  32. </div>
  33. </aside>
  34. </ContentBox>
  35. </template>
  36. <script setup lang="ts">
  37. import { reactive, ref, toRefs } from 'vue'
  38. import { icon } from '@/plugins'
  39. import { renderLang, renderIcon } from '@/utils'
  40. import { ContentBox } from '../ContentBox/index'
  41. import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
  42. import { useDesignStore } from '@/store/modules/designStore/designStore'
  43. import { ChartCommon } from './components/ChartCommon'
  44. import { TableCommon } from './components/TableCommon'
  45. import { TextCommon } from './components/TextCommon'
  46. import { DecorateCommon } from './components/DecorateCommon'
  47. // 图标
  48. const { BarChartIcon } = icon.ionicons5
  49. const {
  50. TableSplitIcon,
  51. RoadmapIcon,
  52. SpellCheckIcon,
  53. GraphicalDataFlowIcon
  54. } = icon.carbon
  55. // 全局颜色
  56. const designStore = useDesignStore()
  57. const themeColor = ref(designStore.getAppTheme)
  58. // 结构控制
  59. const { setItem } = useChartLayoutStore()
  60. const { getCharts } = toRefs(useChartLayoutStore())
  61. // 菜单
  62. const collapsed = ref(false)
  63. const menuOptions = reactive([
  64. {
  65. key: 'ChartCommon',
  66. icon: renderIcon(RoadmapIcon),
  67. label: renderLang('图表'),
  68. node: ChartCommon
  69. },
  70. {
  71. key: 'TextCommon',
  72. icon: renderIcon(SpellCheckIcon),
  73. label: renderLang('信息'),
  74. node: TableCommon
  75. },
  76. {
  77. key: 'TableCommon',
  78. icon: renderIcon(TableSplitIcon),
  79. label: renderLang('表格'),
  80. node: TextCommon
  81. },
  82. {
  83. key: 'DecorateCommon',
  84. icon: renderIcon(GraphicalDataFlowIcon),
  85. label: renderLang('装饰'),
  86. node: DecorateCommon
  87. }
  88. ])
  89. // 记录选中值
  90. let beforeSelect: string = menuOptions[0]['key']
  91. const selectValue = ref<string>(menuOptions[0]['key'])
  92. // 渲染的组件控制
  93. const selectNode = ref(menuOptions[0]['node'])
  94. // 点击 item
  95. const clickItemHandle = <T extends { node: any }>(key: string, item: T) => {
  96. // 处理渲染的 node
  97. selectNode.value = item.node
  98. // 处理折叠
  99. if (beforeSelect === key) {
  100. setItem('charts', !getCharts.value)
  101. } else {
  102. setItem('charts', true)
  103. }
  104. beforeSelect = key
  105. }
  106. </script>
  107. <style lang="scss" scoped>
  108. /* 整体宽度 */
  109. $width: 300px;
  110. /* 列表的宽度 */
  111. $widthScoped: 65px;
  112. /* 此高度与 ContentBox 组件关联*/
  113. $topHeight: 36px;
  114. @include go(content-charts) {
  115. width: $width;
  116. @extend .go-transition;
  117. &.scoped,
  118. .menu-width {
  119. width: $widthScoped;
  120. }
  121. .menu-width-box {
  122. display: flex;
  123. height: calc(100vh - #{$--header-height} - #{$topHeight});
  124. .menu-width {
  125. flex-shrink: 0;
  126. @include filter-bg-color('background-color3');
  127. }
  128. .menu-component-box {
  129. flex-shrink: 0;
  130. width: $width - $widthScoped;
  131. overflow: hidden;
  132. }
  133. }
  134. @include deep() {
  135. .menu-width {
  136. .n-menu-item {
  137. height: auto !important;
  138. &.n-menu-item--selected {
  139. &::after {
  140. content: '';
  141. position: absolute;
  142. left: 2px;
  143. top: 0;
  144. height: 100%;
  145. width: 3px;
  146. background-color: v-bind('themeColor');
  147. border-top-right-radius: 3px;
  148. border-bottom-right-radius: 3px;
  149. }
  150. }
  151. .n-menu-item-content {
  152. display: flex;
  153. flex-direction: column;
  154. padding: 6px 12px !important;
  155. font-size: 12px !important;
  156. }
  157. .n-menu-item-content__icon {
  158. font-size: 18px !important;
  159. margin-right: 0 !important;
  160. }
  161. }
  162. }
  163. }
  164. }
  165. </style>