officialblock 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/official-block.cjs.js +1 -1
  2. package/dist/official-block.es.js +43 -11
  3. package/dist/official-block.umd.js +1 -1
  4. package/dist/style.css +1 -1
  5. package/package.json +1 -1
  6. package/src/assets/icon-email.svg +3 -0
  7. package/src/components/ArticleList/setting.vue +316 -142
  8. package/src/components/BannerImageWithLink/index.ts +11 -0
  9. package/src/components/BannerImageWithLink/index.vue +323 -0
  10. package/src/components/BannerImageWithLink/setting.vue +344 -0
  11. package/src/components/BannerImageWithLink/type.ts +17 -0
  12. package/src/components/ContactUsList/index.ts +11 -0
  13. package/src/components/ContactUsList/index.vue +369 -0
  14. package/src/components/ContactUsList/setting.vue +497 -0
  15. package/src/components/ContactUsList/type.ts +17 -0
  16. package/src/components/CountDown/index.ts +11 -0
  17. package/src/components/CountDown/index.vue +315 -0
  18. package/src/components/CountDown/setting.vue +302 -0
  19. package/src/components/CountDown/type.ts +17 -0
  20. package/src/components/CustomIframe/index.ts +11 -0
  21. package/src/components/CustomIframe/index.vue +118 -0
  22. package/src/components/CustomIframe/setting.vue +323 -0
  23. package/src/components/CustomIframe/type.ts +17 -0
  24. package/src/components/Operate/index.vue +1 -2
  25. package/src/components/ScrollKeyInfo/index.ts +11 -0
  26. package/src/components/ScrollKeyInfo/index.vue +1345 -0
  27. package/src/components/ScrollKeyInfo/setting.vue +302 -0
  28. package/src/components/ScrollKeyInfo/type.ts +17 -0
  29. package/src/components/TabDefault/components/ComponentSelector/compsData.js +143 -0
  30. package/src/components/TabDefault/components/ComponentSelector/index.vue +188 -0
  31. package/src/components/TabDefault/components/PageContent.vue +207 -0
  32. package/src/components/TabDefault/index.vue +475 -0
  33. package/src/components/TabDefault/setting.vue +581 -0
  34. package/src/components/TabDefault/type.ts +17 -0
  35. package/src/components/TableTwo/index.ts +11 -0
  36. package/src/components/TableTwo/index.vue +232 -0
  37. package/src/components/TableTwo/setting.vue +558 -0
  38. package/src/components/TableTwo/type.ts +17 -0
  39. package/src/components/index.ts +17 -0
  40. package/src/styles/component-isolation.scss +2 -1
  41. package/src/views/components/ArticleListDemo.vue +50 -49
@@ -0,0 +1,207 @@
1
+ <template>
2
+ <div class="page-content">
3
+ <!-- 判断 pageJsonData 是否有数据 -->
4
+ <div v-if="pageJsonData && pageJsonData.length > 0">
5
+ <draggable
6
+ v-model="pageJsonData"
7
+ :component-data="{
8
+ tag: 'div',
9
+ type: 'transition-group',
10
+ name: !drag ? 'flip-list' : null,
11
+ }"
12
+ v-bind="buttonDragOptions"
13
+ :disabled="!shouldShowDragHandle(pageJsonData)"
14
+ @start="drag = true"
15
+ @end="dragEnd"
16
+ item-key="id"
17
+ >
18
+ <template #item="{ element: component, index }">
19
+ <div
20
+ class="item-button draggable-item component-wrapper"
21
+ :class="{ 'sortable-disabled': !shouldShowDragHandle(pageJsonData) }"
22
+ :key="component.id"
23
+ >
24
+ <component
25
+ :is="getComponetnBytype(component.type)"
26
+ :model-value="component"
27
+ @update:model-value="($event) => updateComponentValue(index, $event)"
28
+ />
29
+ <div class="add-btn">
30
+ <a-button type="primary" @click="addComponent(index)">
31
+ <template #icon>
32
+ <icon-plus />
33
+ </template>
34
+ Add Component
35
+ </a-button>
36
+ </div>
37
+ </div>
38
+ </template>
39
+ </draggable>
40
+ <!-- <a-button type="primary" class="add-component-btn" @click="addComponent"> 添加组件 </a-button> -->
41
+
42
+ <!-- <div v-for="(component, index) in pageJsonData" :key="component.id" class="page-item">
43
+ <div class="component-wrapper">
44
+ <component
45
+ :is="getComponetnBytype(component.type)"
46
+ :model-value="component"
47
+ @update:model-value="($event) => updateComponentValue(index, $event)"
48
+ />
49
+ <div class="add-btn">
50
+ <a-button type="primary" @click="addComponent(index)">
51
+ <template #icon>
52
+ <icon-plus />
53
+ </template>
54
+ Add Component
55
+ </a-button>
56
+ </div>
57
+ </div>
58
+ </div> -->
59
+ </div>
60
+
61
+ <div v-else>
62
+ <!-- 使用 Arco Design 的按钮 -->
63
+ <a-button type="primary" class="add-component-btn" @click="addComponent"> 添加组件 </a-button>
64
+ </div>
65
+
66
+ <component-selector v-model:visible="visible" @ok="addComponentToPage" />
67
+ </div>
68
+ </template>
69
+
70
+ <script setup>
71
+ // import * as allPageComponents from "officialblock";
72
+ import { ref, watch, computed, defineAsyncComponent } from "vue";
73
+ import componentSelector from "./ComponentSelector/index.vue";
74
+ import draggable from "vuedraggable";
75
+
76
+ // 拖拽相关状态
77
+ const drag = ref(false);
78
+
79
+ // 接收外部传入的数据
80
+ const props = defineProps({
81
+ data: {
82
+ type: Array,
83
+ default: () => [],
84
+ },
85
+ });
86
+
87
+ const emit = defineEmits(["update"]);
88
+
89
+ // 动态导入components目录下的所有组件
90
+ const modules = import.meta.glob("@/components/*/index.vue", { eager: false });
91
+
92
+ const componentMap = {};
93
+
94
+ // 遍历并注册组件
95
+ // 遍历并注册组件,使用文件夹名称作为组件名
96
+ for (const path in modules) {
97
+ debugger;
98
+ try {
99
+ // 正确提取文件夹名称
100
+ const pathParts = path.split("/");
101
+ const folderName = pathParts[pathParts.length - 2]; // 文件夹名称
102
+ console.log(`注册组件: ${folderName} from ${path}`); // 调试信息
103
+ componentMap[folderName] = defineAsyncComponent(modules[path]);
104
+ } catch (error) {
105
+ console.error("组件注册失败:", path, error);
106
+ }
107
+ }
108
+ const getComponetnBytype = (type) => {
109
+ debugger;
110
+ return componentMap[type];
111
+ };
112
+
113
+ // const componentMap = allPageComponents;
114
+ const visible = ref(false);
115
+ const selectComponentIndex = ref(0);
116
+
117
+ // 响应式数据
118
+ const pageJsonData = ref([...props.data]);
119
+
120
+ // 当外部 modelValue 变化时,同步更新本地数据
121
+ watch(
122
+ () => props.data,
123
+ (newVal) => {
124
+ debugger;
125
+ pageJsonData.value = [...newVal];
126
+ },
127
+ { deep: true }
128
+ );
129
+
130
+ const buttonDragOptions = computed(() => ({
131
+ animation: 200,
132
+ group: "buttons", // 按钮专用分组
133
+ disabled: false,
134
+ ghostClass: "ghost",
135
+ }));
136
+
137
+ // 检查是否应该显示拖拽图标
138
+ const shouldShowDragHandle = (list) => {
139
+ return list && list.length > 1;
140
+ };
141
+
142
+ // 添加组件的方法
143
+ const addComponent = (index = 0) => {
144
+ selectComponentIndex.value = index;
145
+ visible.value = true;
146
+ };
147
+
148
+ const updateComponentValue = (index, value) => {
149
+ pageJsonData.value[index] = value;
150
+ emit("update", [...pageJsonData.value]);
151
+
152
+ console.log("组件更新:", pageJsonData.value);
153
+ };
154
+ const dragEnd = () => {
155
+ drag.value = false;
156
+ emit("update", [...pageJsonData.value]);
157
+ };
158
+
159
+ // 弹框添加
160
+ const addComponentToPage = (json) => {
161
+ visible.value = false; // 手动将新对象转为响应式对象
162
+ pageJsonData.value.splice(selectComponentIndex.value + 1, 0, json);
163
+ emit("update", [...pageJsonData.value]);
164
+ };
165
+ </script>
166
+
167
+ <style lang="scss" scoped>
168
+ .page-content {
169
+ // height: 100%;
170
+ min-height: 500px;
171
+ display: flex;
172
+ flex-direction: column;
173
+ align-items: center;
174
+ justify-content: center;
175
+ padding: 30px 0 50px;
176
+
177
+ // .page-item {
178
+ // min-width: none;
179
+ // height: 100%;
180
+
181
+ .component-wrapper {
182
+ position: relative;
183
+
184
+ &:hover {
185
+ border: 2px solid #409eff;
186
+
187
+ .add-btn {
188
+ display: block;
189
+ }
190
+ }
191
+
192
+ .add-btn {
193
+ display: none;
194
+ position: absolute;
195
+ left: 50%;
196
+ bottom: 0;
197
+ transform: translate(-50%, 50%);
198
+ }
199
+ }
200
+ // }
201
+
202
+ .add-component-btn {
203
+ padding: 12px 24px;
204
+ font-size: 16px;
205
+ }
206
+ }
207
+ </style>
@@ -0,0 +1,475 @@
1
+ <template>
2
+ <div class="tab-default__container bg-neutral-light" @mouseover="isHover = true" @mouseout="isHover = false">
3
+ <div class="container-content-small">
4
+ <div class="tab-default__tab">
5
+ <div class="tab-blue bg-neutral-light">
6
+ <div class="tab-blue__wrapper flex-center">
7
+ <div class="tab-blue__nav justify-content-center">
8
+ <div class="tab-blue__nav__prev" style="display: none"></div>
9
+ <ul class="tab-blue__list px-4">
10
+ <li
11
+ v-for="item in tabItems"
12
+ :id="item.id"
13
+ :key="item.id"
14
+ class="tab-blue__list__item"
15
+ ref="tabItemRefs"
16
+ @click="selectTab(item.id)"
17
+ >
18
+ <button
19
+ type="button"
20
+ class="tab-blue__btn"
21
+ :class="{ 'tab-blue__btn--active': activeItemId === item.id }"
22
+ >
23
+ {{ item.name }}
24
+ </button>
25
+ </li>
26
+ <!-- <span class="tab-blue__strip" style="--strip-width: 103.265625px; --strip-left: 46.875px; --list-scroll-left: 0px; --fix-left: 12px;"></span> -->
27
+ <span class="tab-blue__strip" :style="stripStyle"></span>
28
+ </ul>
29
+
30
+ <div class="tab-blue__nav__next" style="display: none"></div>
31
+ </div>
32
+ <!---->
33
+ <div class="tab-blue__filter mt-5 mt-md-3" style="--width: 338px"><!----></div>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ <div class="tab-default__content">
38
+ <div data-aos="fade-in" data-aos-duration="1500" class="aos-init aos-animate">
39
+ <div v-for="(component, index) in pageJsonData" :key="component.id" class="page-item">
40
+ <div class="component-wrapper">
41
+ <component :is="getComponetnBytype(component.type)" :model-value="component" />
42
+ </div>
43
+ </div>
44
+ </div>
45
+ <!----><!---->
46
+ </div>
47
+ <Operate
48
+ v-if="!modelValue?.readOnly"
49
+ v-model:show="isHover"
50
+ @handle-edit="showSetting = true"
51
+ @handle-delete="handleDelete"
52
+ @handle-copy="handleCopy"
53
+ ></Operate>
54
+ </div>
55
+ <Setting v-model:show="showSetting" :data="modelValue"></Setting>
56
+ </div>
57
+ </template>
58
+
59
+ <script lang="ts" setup>
60
+ import { randomString } from "@/utils/common";
61
+ // import type { TabDefaultProps, TabDefaultEmits, TabDefaultTab } from './type'
62
+ import Setting from "./setting.vue";
63
+ // import TabItem from './tabItem.vue'
64
+ import { ref, computed, onMounted, onUnmounted, nextTick, watch, defineAsyncComponent } from "vue";
65
+ import Operate from "@/components/Operate/index.vue";
66
+
67
+ defineOptions({ name: "TabDefault" });
68
+ // 动态导入components目录下的所有组件
69
+ const modules = import.meta.glob("../../components/*/index.vue", { eager: false });
70
+ const componentMap = {};
71
+
72
+ // 遍历并注册组件
73
+ // 遍历并注册组件,使用文件夹名称作为组件名
74
+ for (const path in modules) {
75
+ try {
76
+ // 正确提取文件夹名称
77
+ const pathParts = path.split("/");
78
+ const folderName = pathParts[pathParts.length - 2]; // 文件夹名称
79
+ console.log(`注册组件: ${folderName} from ${path}`); // 调试信息
80
+ componentMap[folderName] = defineAsyncComponent(modules[path]);
81
+ } catch (error) {
82
+ console.error("组件注册失败:", path, error);
83
+ }
84
+ }
85
+ const getComponetnBytype = (type) => {
86
+ console.log("cehi =========================");
87
+ return componentMap[type];
88
+ };
89
+ const props = defineProps({
90
+ modelValue: {
91
+ type: Object,
92
+ default: () => {},
93
+ },
94
+
95
+ // 是否预览
96
+ isPreview: {
97
+ type: Boolean,
98
+ default: false,
99
+ },
100
+ });
101
+
102
+ const emit = defineEmits(["update:modelValue", "handleDelete", "handleCopy"]);
103
+ // 动画状态
104
+ const animating = ref(false);
105
+ const animationStage = ref(0); // 0: idle, 1: 扩展, 2: 收缩
106
+ const animationFrom = ref(0);
107
+ const animationTo = ref(0);
108
+ const forceUpdateKey = ref(0);
109
+
110
+ // // 切换 Tab
111
+ const activeItemId = ref("");
112
+ const activeIndex = ref(0);
113
+ const tabItemRefs = ref([]);
114
+ function selectTab(id) {
115
+ debugger;
116
+ const idx = tabItemRefs.value?.findIndex((item) => item.id === id);
117
+ if (idx === activeIndex.value || animating.value) return;
118
+ activeItemId.value = id;
119
+ animationFrom.value = activeIndex.value;
120
+ animationTo.value = idx;
121
+ animating.value = true;
122
+ animationStage.value = 1;
123
+
124
+ // 先扩展到覆盖所有tab
125
+ setTimeout(() => {
126
+ animationStage.value = 2;
127
+ activeIndex.value = idx;
128
+
129
+ // 动画完成后重置状态
130
+ setTimeout(() => {
131
+ animating.value = false;
132
+ animationStage.value = 0;
133
+ }, 300);
134
+ }, 300);
135
+ }
136
+
137
+ const showSetting = ref<boolean>(false);
138
+ const isHover = ref<boolean>(false);
139
+
140
+ const activeTabObj = computed(() => props.modelValue?.data.find((tab) => tab.id === props.activeTab));
141
+ const pageJsonData = computed(() => props.modelValue?.data[activeIndex.value]?.componentsDataJson || []);
142
+
143
+ const handleInit = () => {
144
+ if (props.modelValue && props.modelValue.data) return; // 有数据不用初始化
145
+ const data = {
146
+ id: props.modelValue?.id || randomString(),
147
+ type: "TabDefault",
148
+ readOnly: props.modelValue?.readOnly || false,
149
+ containerWidth: "",
150
+ bgColor: "",
151
+ isCenter: "yes",
152
+ data: [
153
+ {
154
+ id: randomString(),
155
+ key: "11111111",
156
+ name: "tab1",
157
+ componentsDataJson: [],
158
+ },
159
+ {
160
+ id: randomString(),
161
+ key: "2222",
162
+ name: "tab2",
163
+ componentsDataJson: [],
164
+ },
165
+ {
166
+ id: randomString(),
167
+ key: "33333",
168
+ name: "tab3",
169
+ componentsDataJson: [],
170
+ },
171
+ ],
172
+ };
173
+ emit("update:modelValue", data);
174
+ activeItemId.value = data.data[0].id;
175
+ pageJsonData.value = [...data.data[0].componentsDataJson];
176
+ };
177
+ const tabItems = computed(() => props.modelValue?.data);
178
+
179
+ handleInit();
180
+
181
+ // 计算滑动条样式
182
+ const stripStyle = computed(() => {
183
+ forceUpdateKey.value;
184
+ if (!tabItemRefs.value.length) return {};
185
+
186
+ let left = 0;
187
+ let width = 0;
188
+
189
+ if (!animating.value) {
190
+ const tab = tabItemRefs.value[activeIndex.value];
191
+ if (!tab) return {};
192
+ const style = window.getComputedStyle(tab);
193
+ left = tab.offsetLeft + parseInt(style.paddingLeft);
194
+ width = tab.clientWidth - parseInt(style.paddingLeft) - parseInt(style.paddingRight);
195
+ } else if (animationStage.value === 1) {
196
+ const from = Math.min(animationFrom.value, animationTo.value);
197
+ const to = Math.max(animationFrom.value, animationTo.value);
198
+ const firstTab = tabItemRefs.value[from];
199
+ const lastTab = tabItemRefs.value[to];
200
+ if (!firstTab || !lastTab) return {};
201
+
202
+ const firstStyle = window.getComputedStyle(firstTab);
203
+ const lastStyle = window.getComputedStyle(lastTab);
204
+
205
+ left = firstTab.offsetLeft + parseInt(firstStyle.paddingLeft);
206
+ width =
207
+ lastTab.offsetLeft +
208
+ lastTab.clientWidth -
209
+ parseInt(lastStyle.paddingRight) -
210
+ (firstTab.offsetLeft + parseInt(firstStyle.paddingLeft));
211
+ } else if (animationStage.value === 2) {
212
+ const tab = tabItemRefs.value[animationTo.value];
213
+ if (!tab) return {};
214
+ const style = window.getComputedStyle(tab);
215
+ left = tab.offsetLeft + parseInt(style.paddingLeft);
216
+ width = tab.clientWidth - parseInt(style.paddingLeft) - parseInt(style.paddingRight);
217
+ }
218
+
219
+ return {
220
+ "--strip-left": `${left}px`,
221
+ "--strip-width": `${width}px`,
222
+ "--tab-strip-color": "#0032a0",
223
+ transition: animating.value ? "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)" : "none",
224
+ };
225
+ });
226
+
227
+ // 添加窗口大小变化监听
228
+ const handleResize = () => {
229
+ // 强制重新计算滑块位置
230
+ if (!animating.value) {
231
+ forceUpdateKey.value++;
232
+ }
233
+ };
234
+ watch(
235
+ tabItems,
236
+ (newVal) => {
237
+ handleResize();
238
+ },
239
+ { deep: true }
240
+ );
241
+
242
+ onMounted(() => {
243
+ window.addEventListener("resize", handleResize);
244
+ // 初始计算
245
+ nextTick(() => {
246
+ activeIndex.value = activeIndex.value;
247
+ });
248
+ });
249
+
250
+ onUnmounted(() => {
251
+ window.removeEventListener("resize", handleResize);
252
+ });
253
+ </script>
254
+
255
+ <style scoped>
256
+ .tab-default__container {
257
+ position: relative;
258
+ width: 100%;
259
+ }
260
+ .tab-blue__wrapper {
261
+ flex-direction: column;
262
+ }
263
+
264
+ .tab-blue__nav {
265
+ display: flex;
266
+ align-items: center;
267
+ width: 100%;
268
+ max-width: 1200px;
269
+ margin: 0 auto;
270
+ position: relative;
271
+ z-index: 1;
272
+ min-height: 38px;
273
+ overflow: hidden;
274
+ }
275
+
276
+ .tab-blue__nav__next,
277
+ .tab-blue__nav__prev {
278
+ position: absolute;
279
+ width: 25px;
280
+ height: 38px;
281
+ box-shadow: 0 4px 4px hsla(0, 0%, 100%, 0.2);
282
+ background-color: #f7f7fa;
283
+ display: flex;
284
+ align-items: center;
285
+ justify-content: center;
286
+ z-index: 1;
287
+ }
288
+
289
+ @media (max-width: 767.98px) {
290
+ .tab-blue__nav__next,
291
+ .tab-blue__nav__prev {
292
+ box-shadow: 0 0 8px rgba(0, 0, 0, 0.22);
293
+ }
294
+ }
295
+
296
+ .tab-blue__nav__next:after,
297
+ .tab-blue__nav__prev:after {
298
+ content: "";
299
+ width: 24px;
300
+ height: 38px;
301
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkgNkwxNSAxMkw5IDE4IiBzdHJva2U9IiMxQTFDMjAiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg==);
302
+ background-position: 50%;
303
+ background-size: cover;
304
+ background-repeat: no-repeat;
305
+ background-color: hsla(0, 0%, 100%, 0);
306
+ }
307
+
308
+ @media (max-width: 1023.98px) {
309
+ .tab-blue__nav__next:after,
310
+ .tab-blue__nav__prev:after {
311
+ width: 14px;
312
+ height: 14px;
313
+ }
314
+ }
315
+
316
+ .tab-blue__nav__prev {
317
+ left: -1px;
318
+ }
319
+
320
+ .tab-blue__nav__prev:after {
321
+ transform: scale(-1);
322
+ }
323
+
324
+ .tab-blue__nav__next {
325
+ right: -1px;
326
+ }
327
+
328
+ .tab-blue__list {
329
+ display: flex;
330
+ align-items: center;
331
+ overflow-x: scroll;
332
+ scroll-behavior: smooth;
333
+ scrollbar-color: transparent;
334
+ scrollbar-width: none;
335
+ }
336
+
337
+ .tab-blue__list::-webkit-scrollbar-track {
338
+ border-radius: 0;
339
+ background-color: transparent;
340
+ }
341
+
342
+ .tab-blue__list::-webkit-scrollbar {
343
+ width: 0;
344
+ height: 0;
345
+ background-color: transparent;
346
+ }
347
+
348
+ .tab-blue__list::-webkit-scrollbar-thumb {
349
+ border-radius: 0;
350
+ background-color: transparent;
351
+ }
352
+
353
+ .tab-blue__list__item {
354
+ padding-right: 4px;
355
+ display: flex;
356
+ text-align: center;
357
+ }
358
+
359
+ @media (max-width: 1023.98px) {
360
+ .tab-blue__list__item {
361
+ padding-right: 0;
362
+ }
363
+ }
364
+
365
+ @media (max-width: 767.98px) {
366
+ .tab-blue__list__item {
367
+ padding-right: 6px;
368
+ }
369
+ }
370
+
371
+ .tab-blue__list__item:first-of-type {
372
+ padding-left: 0;
373
+ }
374
+
375
+ .tab-blue__list__item:last-of-type {
376
+ padding-right: 0;
377
+ }
378
+
379
+ .tab-blue__btn {
380
+ width: auto;
381
+ border: none;
382
+ background: none;
383
+ font-size: 16px;
384
+ font-weight: 400;
385
+ line-height: 1.25;
386
+ letter-spacing: 0.01em;
387
+ white-space: nowrap;
388
+ padding: 8px 20px;
389
+ color: #c0c0c4;
390
+ text-decoration: none;
391
+ transition: color 0.3s ease-in-out;
392
+ outline: none !important;
393
+ }
394
+
395
+ @media (max-width: 1023.98px) {
396
+ .tab-blue__btn {
397
+ font-size: 14px;
398
+ line-height: 1.285;
399
+ letter-spacing: 0.01em;
400
+ }
401
+ }
402
+
403
+ @media (max-width: 767.98px) {
404
+ .tab-blue__btn {
405
+ padding: 4px 10px;
406
+ }
407
+ }
408
+
409
+ .tab-blue__btn:hover {
410
+ color: #0032a0;
411
+ }
412
+
413
+ .tab-blue__btn--active,
414
+ .tab-blue__btn:hover.tab-blue__btn--active {
415
+ color: #fff;
416
+ }
417
+
418
+ .tab-blue__btn {
419
+ border: none !important;
420
+ /* 强制移除边框 */
421
+ box-shadow: none !important;
422
+ /* 移除可能存在的阴影 */
423
+ }
424
+
425
+ .tab-blue__strip {
426
+ position: absolute;
427
+ top: 50%;
428
+ transform: translateY(-50%);
429
+ left: 0;
430
+ left: var(--strip-left, 0);
431
+ width: 0;
432
+ width: var(--strip-width, 0);
433
+ height: 100%;
434
+ background: #0032a0;
435
+ background: var(--tab-strip-color, #0032a0);
436
+ transition: left 0.2s ease-in-out, width 0.2s ease-in-out;
437
+ z-index: -1;
438
+ border-radius: 3px;
439
+ overflow: hidden;
440
+ box-shadow: 0 2px 6px 0 rgba(130, 130, 140, 0.12);
441
+ }
442
+
443
+ @media (max-width: 767.98px) {
444
+ .tab-blue__strip {
445
+ max-height: 26px;
446
+ }
447
+ }
448
+
449
+ .tab-blue__filter {
450
+ display: flex;
451
+ align-items: center;
452
+ justify-content: center;
453
+ max-width: 1200px;
454
+ margin: 0 auto;
455
+ width: 100%;
456
+ width: var(--width, 100%);
457
+ position: relative;
458
+ z-index: 1;
459
+ }
460
+
461
+ .tab-blue__filter__filter,
462
+ .tab-blue__filter__sort {
463
+ width: 50%;
464
+ }
465
+
466
+ .tab-blue__filter__filter:only-child,
467
+ .tab-blue__filter__sort:only-child {
468
+ width: 100%;
469
+ }
470
+
471
+ .tab-blue__filter__filter:last-child,
472
+ .tab-blue__filter__sort:last-child {
473
+ margin-right: 8px;
474
+ }
475
+ </style>