Browse Source

fix: BsUi新增组件

hanxiaohui 4 months ago
parent
commit
3e681f5af5

+ 41 - 0
src/components/BsUi/SvgIcon/index.vue

@@ -0,0 +1,41 @@
+<!-- SvgIcon.vue -->
+<template>
+  <svg
+    class="svg-icon"
+    :style="{
+      width: size ? (typeof size === 'number' ? `${size}px` : size) : '1em',
+      height: size ? (typeof size === 'number' ? `${size}px` : size) : '1em',
+      color: color,
+    }"
+    aria-hidden="true"
+  >
+    <use :href="'#' + name"></use>
+  </svg>
+</template>
+
+<script setup>
+  import { defineProps } from 'vue';
+
+  const props = defineProps({
+    name: {
+      type: String,
+      required: true,
+    },
+    size: {
+      type: [String, Number],
+      default: '1em',
+    },
+    color: {
+      type: String,
+      default: "currentColor", // 使用 currentColor 继承父级颜色
+    },
+  });
+</script>
+
+<style scoped>
+  .svg-icon {
+    vertical-align: -0.15em;
+    fill: currentColor;
+    overflow: hidden;
+  }
+</style>

+ 123 - 0
src/components/BsUi/TabBar/index.vue

@@ -0,0 +1,123 @@
+<template>
+  <div class="tab-bar">
+    <!-- 区分两种模式:带数量的按钮模式、分段大选项卡模式 -->
+    <div v-if="mode === 'button'" class="tab-group-small">
+      <button
+        v-for="(item, index) in tabList"
+        :key="item.key || index"
+        class="tab-item-small"
+        :class="{ active: currentActive === (item.key || index) }"
+        @click="handleTabClick(item.key || index)"
+      >
+        <span>{{ item.label }}</span>
+        <span v-if="item.count !== undefined && item.count !== null" class="count-badge">({{ item.count }})</span>
+      </button>
+    </div>
+    <div v-else class="tab-group-large">
+      <button
+        v-for="(item, index) in tabList"
+        :key="item.key || index"
+        class="tab-item-large"
+        :class="{ active: currentActive === (item.key || index) }"
+        @click="handleTabClick(item.key || index)"
+      >
+        {{ item.label }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+  import { computed } from 'vue';
+
+  const props = defineProps({
+    // 选项卡数据列表,元素包含 label、count(小标签模式用)、key 等
+    tabList: {
+      type: Array,
+      required: true,
+      default: () => [],
+    },
+    // 模式:button(带数量按钮标签)、capsule(分段选项卡)
+    mode: {
+      type: String,
+      default: 'button  ',
+    },
+    // v-model 绑定的选中值
+    activeKey: {
+      type: [String, Number],
+      default: undefined,
+    },
+  });
+
+  const currentActive = computed({
+    get() {
+      return props.activeKey;
+    },
+    set(value) {
+      emit('update:activeKey', value);
+    },
+  });
+
+  const emit = defineEmits(['update:activeKey']);
+
+  const handleTabClick = (key) => {
+    currentActive.value = key;
+  };
+</script>
+
+<style scoped>
+  .tab-bar {
+    display: flex;
+    align-items: center;
+  }
+
+  /* 小标签模式样式 */
+  .tab-group-small {
+    display: flex;
+    gap: 8px;
+  }
+  .tab-item-small {
+    padding: 3px 12px;
+    border: 1px solid #dcdcdc;
+    border-radius: 4px;
+    background-color: #fff;
+    cursor: pointer;
+    transition: all 0.2s ease;
+    white-space: nowrap;
+  }
+  .tab-item-small.active {
+    background-color: var(--vxe-ui-font-primary-color);
+    color: #fff;
+    border-color: var(--vxe-ui-font-primary-color);
+  }
+  .count-badge {
+    margin-left: 4px;
+    font-size: 0.9em;
+    opacity: 0.8;
+  }
+
+  /* 大选项卡模式样式 */
+  .tab-group-large {
+    display: flex;
+    border-radius: 8px;
+    overflow: hidden;
+    background-color: #f3f3f3;
+    padding: 5px;
+  }
+  .tab-item-large {
+    text-align: center;
+    padding: 5px 25px;
+    font-size: 16px;
+    color: #333;
+    background-color: transparent;
+    border: none;
+    cursor: pointer;
+    transition: background-color 0.2s ease;
+    border-radius: 8px;
+    font-weight: 500;
+  }
+  .tab-item-large.active {
+    background-color:var(--vxe-ui-font-primary-color);
+    color: #fff;
+  }
+</style>

+ 7 - 1
src/components/BsUi/index.js

@@ -14,6 +14,8 @@ import BsEllipsisText from "./EllipsisText/index.vue"
 import BsDicTag from "./DicTag/index.vue"
 import BsLink from "./Link/index.vue"
 import BsCatalog from "./Catalog/index.vue"
+import BsSvgIcon from "./SvgIcon/index.vue"
+import BsTabBar from "/@/components/BsUi/TabBar/index.vue"
 
 const BsUi = {
   install(app) {
@@ -31,6 +33,8 @@ const BsUi = {
     app.component('BsDicTag', BsDicTag);
     app.component('BsLink', BsLink);
     app.component('BsCatalog', BsCatalog);
+    app.component('BsSvgIcon', BsSvgIcon);
+    app.component('BsTabBar', BsTabBar);
   },
 };
 
@@ -56,5 +60,7 @@ export {
   BsEllipsisText,
   BsDicTag,
   BsLink,
-  BsCatalog
+  BsCatalog,
+  BsSvgIcon,
+  BsTabBar
 };