diff --git a/src/assets/scss/atom.scss b/src/assets/scss/atom.scss
new file mode 100644
index 000000000..05083e79b
--- /dev/null
+++ b/src/assets/scss/atom.scss
@@ -0,0 +1,473 @@
+/* Simple Atomic CSS Classes
+ Note: This is a lightweight implementation without third-party libraries.
+ As the project is older and has simple usage, we've implemented some basic atomic classes ourselves.
+ These classes provide commonly used styles that can be quickly combined to improve development efficiency.
+*/
+
+/* Flexbox */
+.flex {
+ display: flex;
+}
+.flex-col {
+ flex-direction: column;
+}
+.items-center {
+ align-items: center;
+}
+.justify-between {
+ justify-content: space-between;
+}
+
+/* Spacing */
+/* Rem to px conversion (1rem = 16px):
+ * 0.25rem = 4px
+ * 0.5rem = 8px
+ * 0.75rem = 12px
+ * 1rem = 16px
+ * 1.25rem = 20px
+ * 1.5rem = 24px
+ * 2rem = 32px
+ */
+/* Margin */
+.m-0 {
+ margin: 0;
+}
+.m-1 {
+ margin: 0.25rem;
+}
+.m-2 {
+ margin: 0.5rem;
+}
+.m-3 {
+ margin: 0.75rem;
+}
+.m-4 {
+ margin: 1rem;
+}
+.m-5 {
+ margin: 1.25rem;
+}
+.m-6 {
+ margin: 1.5rem;
+}
+.m-8 {
+ margin: 2rem;
+}
+
+/* Padding */
+.p-0 {
+ padding: 0;
+}
+.p-1 {
+ padding: 0.25rem;
+}
+.p-2 {
+ padding: 0.5rem;
+}
+.p-3 {
+ padding: 0.75rem;
+}
+.p-4 {
+ padding: 1rem;
+}
+.p-5 {
+ padding: 1.25rem;
+}
+.p-6 {
+ padding: 1.5rem;
+}
+.p-8 {
+ padding: 2rem;
+}
+
+/* Margin Top */
+.mt-0 {
+ margin-top: 0;
+}
+.mt-1 {
+ margin-top: 0.25rem;
+}
+.mt-2 {
+ margin-top: 0.5rem;
+}
+.mt-3 {
+ margin-top: 0.75rem;
+}
+.mt-4 {
+ margin-top: 1rem;
+}
+.mt-5 {
+ margin-top: 1.25rem;
+}
+.mt-6 {
+ margin-top: 1.5rem;
+}
+.mt-8 {
+ margin-top: 2rem;
+}
+
+/* Padding Top */
+.pt-0 {
+ padding-top: 0;
+}
+.pt-1 {
+ padding-top: 0.25rem;
+}
+.pt-2 {
+ padding-top: 0.5rem;
+}
+.pt-3 {
+ padding-top: 0.75rem;
+}
+.pt-4 {
+ padding-top: 1rem;
+}
+.pt-5 {
+ padding-top: 1.25rem;
+}
+.pt-6 {
+ padding-top: 1.5rem;
+}
+.pt-8 {
+ padding-top: 2rem;
+}
+
+/* Margin Bottom */
+.mb-0 {
+ margin-bottom: 0;
+}
+.mb-1 {
+ margin-bottom: 0.25rem;
+}
+.mb-2 {
+ margin-bottom: 0.5rem;
+}
+.mb-3 {
+ margin-bottom: 0.75rem;
+}
+.mb-4 {
+ margin-bottom: 1rem;
+}
+.mb-5 {
+ margin-bottom: 1.25rem;
+}
+.mb-6 {
+ margin-bottom: 1.5rem;
+}
+.mb-8 {
+ margin-bottom: 2rem;
+}
+
+/* Padding Bottom */
+.pb-0 {
+ padding-bottom: 0;
+}
+.pb-1 {
+ padding-bottom: 0.25rem;
+}
+.pb-2 {
+ padding-bottom: 0.5rem;
+}
+.pb-3 {
+ padding-bottom: 0.75rem;
+}
+.pb-4 {
+ padding-bottom: 1rem;
+}
+.pb-5 {
+ padding-bottom: 1.25rem;
+}
+
+/* Margin Left */
+.ml-0 {
+ margin-left: 0;
+}
+.ml-1 {
+ margin-left: 0.25rem;
+}
+.ml-2 {
+ margin-left: 0.5rem;
+}
+.ml-3 {
+ margin-left: 0.75rem;
+}
+.ml-4 {
+ margin-left: 1rem;
+}
+.ml-5 {
+ margin-left: 1.25rem;
+}
+.ml-6 {
+ margin-left: 1.5rem;
+}
+.ml-8 {
+ margin-left: 2rem;
+}
+
+/* Padding Left */
+.pl-0 {
+ padding-left: 0;
+}
+.pl-1 {
+ padding-left: 0.25rem;
+}
+.pl-2 {
+ padding-left: 0.5rem;
+}
+.pl-3 {
+ padding-left: 0.75rem;
+}
+.pl-4 {
+ padding-left: 1rem;
+}
+.pl-5 {
+ padding-left: 1.25rem;
+}
+.pl-6 {
+ padding-left: 1.5rem;
+}
+
+/* Margin Right */
+.mr-0 {
+ margin-right: 0;
+}
+.mr-1 {
+ margin-right: 0.25rem;
+}
+.mr-2 {
+ margin-right: 0.5rem;
+}
+.mr-3 {
+ margin-right: 0.75rem;
+}
+.mr-4 {
+ margin-right: 1rem;
+}
+.mr-5 {
+ margin-right: 1.25rem;
+}
+.mr-6 {
+ margin-right: 1.5rem;
+}
+.mr-8 {
+ margin-right: 2rem;
+}
+
+/* Padding Right */
+.pr-0 {
+ padding-right: 0;
+}
+.pr-1 {
+ padding-right: 0.25rem;
+}
+.pr-2 {
+ padding-right: 0.5rem;
+}
+.pr-3 {
+ padding-right: 0.75rem;
+}
+.pr-4 {
+ padding-right: 1rem;
+}
+.pr-5 {
+ padding-right: 1.25rem;
+}
+.pr-6 {
+ padding-right: 1.5rem;
+}
+.pr-8 {
+ padding-right: 2rem;
+}
+
+/* Margin X (left and right) */
+.mx-0 {
+ margin-left: 0;
+ margin-right: 0;
+}
+.mx-1 {
+ margin-left: 0.25rem;
+ margin-right: 0.25rem;
+}
+.mx-2 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+}
+.mx-3 {
+ margin-left: 0.75rem;
+ margin-right: 0.75rem;
+}
+.mx-4 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+}
+.mx-5 {
+ margin-left: 1.25rem;
+ margin-right: 1.25rem;
+}
+.mx-6 {
+ margin-left: 1.5rem;
+ margin-right: 1.5rem;
+}
+.mx-8 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+}
+
+/* Padding X (left and right) */
+.px-0 {
+ padding-left: 0;
+ padding-right: 0;
+}
+.px-1 {
+ padding-left: 0.25rem;
+ padding-right: 0.25rem;
+}
+.px-2 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+.px-3 {
+ padding-left: 0.75rem;
+ padding-right: 0.75rem;
+}
+.px-4 {
+ padding-left: 1rem;
+ padding-right: 1rem;
+}
+.px-5 {
+ padding-left: 1.25rem;
+ padding-right: 1.25rem;
+}
+
+/* Margin Y (top and bottom) */
+.my-0 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+.my-1 {
+ margin-top: 0.25rem;
+ margin-bottom: 0.25rem;
+}
+.my-2 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+.my-3 {
+ margin-top: 0.75rem;
+ margin-bottom: 0.75rem;
+}
+.my-4 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+}
+.my-5 {
+ margin-top: 1.25rem;
+ margin-bottom: 1.25rem;
+}
+.my-6 {
+ margin-top: 1.5rem;
+ margin-bottom: 1.5rem;
+}
+.my-8 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+}
+
+/* Padding Y (top and bottom) */
+.py-0 {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+.py-1 {
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+}
+.py-2 {
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+}
+.py-3 {
+ padding-top: 0.75rem;
+ padding-bottom: 0.75rem;
+}
+.py-4 {
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+}
+.py-5 {
+ padding-top: 1.25rem;
+ padding-bottom: 1.25rem;
+}
+
+/* Typography */
+.text-sm {
+ font-size: 0.875rem;
+}
+.text-lg {
+ font-size: 1.125rem;
+}
+.font-bold {
+ font-weight: 700;
+}
+.text-center {
+ text-align: center;
+}
+
+/* Colors (using CSS variables for consistency) */
+.text-primary {
+ color: var(--color-main-green);
+}
+.bg-secondary {
+ background-color: var(--color-background-secondary);
+}
+
+/* Border */
+.rounded {
+ border-radius: 0.25rem;
+}
+.border {
+ border-width: 1px;
+}
+.border-primary {
+ border-color: var(--color-main-green);
+}
+
+/* Display */
+.hidden {
+ display: none;
+}
+.block {
+ display: block;
+}
+
+/* Width and Height */
+.w-full {
+ width: 100%;
+}
+.h-8 {
+ height: 2rem;
+}
+
+/* Positioning */
+.relative {
+ position: relative;
+}
+.absolute {
+ position: absolute;
+}
+
+/* Cursor */
+.cursor-pointer {
+ cursor: pointer;
+}
+
+/* Opacity */
+.opacity-50 {
+ opacity: 0.5;
+}
+
+/* Transitions */
+.transition {
+ transition-property: all;
+ transition-duration: 300ms;
+}
diff --git a/src/assets/scss/base.scss b/src/assets/scss/base.scss
index d3b0e2f0c..b72290f90 100644
--- a/src/assets/scss/base.scss
+++ b/src/assets/scss/base.scss
@@ -1,5 +1,6 @@
@import './variable.scss';
@import './mixins.scss';
+@import './atom.scss';
html,
body,
@@ -153,3 +154,16 @@ textarea {
padding: 0 24px;
cursor: pointer;
}
+
+// Tabs
+.el-tabs {
+ .el-tabs__item {
+ color: var(--color-text-title);
+ &.is-active {
+ color: var(--color-main-green);
+ }
+ }
+ .el-tabs__nav-wrap::after {
+ background-color: var(--color-border-default);
+ }
+}
diff --git a/src/lang/viewer.ts b/src/lang/viewer.ts
index a2df3ed60..3278f11fa 100644
--- a/src/lang/viewer.ts
+++ b/src/lang/viewer.ts
@@ -6,4 +6,18 @@ export default {
ja: 'ビューア',
hu: 'Megjelenítő',
},
+ topicsTree: {
+ zh: '主题树',
+ en: 'Topics Tree',
+ tr: 'Konular Ağacı',
+ ja: 'トピックツリー',
+ hu: 'Témafa',
+ },
+ filterDesc: {
+ zh: '输入关键字进行过滤',
+ en: 'Input keyword to filter',
+ tr: 'Filtrelemek için anahtar kelimeyi girin',
+ ja: 'フィルタリングするためにキーワードを入力してください',
+ hu: 'Adja meg a kulcsszót a szűréshez',
+ },
}
diff --git a/src/utils/topicTree.ts b/src/utils/topicTree.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/views/script/index.vue b/src/views/script/index.vue
index 0a018427f..a164e73db 100644
--- a/src/views/script/index.vue
+++ b/src/views/script/index.vue
@@ -589,15 +589,6 @@ message Person {
margin-left: 5px;
}
}
- .script-view-tabs {
- .el-tabs__item {
- color: var(--color-text-title);
-
- &.is-active {
- color: var(--color-main-green);
- }
- }
- }
.script-view-header {
@include flex-space-between;
@@ -668,8 +659,5 @@ message Person {
padding-bottom: 10px;
}
@include editor-lang-type;
- .el-tabs__nav-wrap::after {
- background-color: var(--color-border-default);
- }
}
diff --git a/src/views/viewer/TopicTree.vue b/src/views/viewer/TopicTree.vue
index 73d9b594a..4811340a3 100644
--- a/src/views/viewer/TopicTree.vue
+++ b/src/views/viewer/TopicTree.vue
@@ -1,17 +1,98 @@
-