@@ -24,7 +24,37 @@ function flattenTree(nodes: TreeNode[], depth = 0): { node: TreeNode; depth: num
2424 return result
2525}
2626
27- const flatTree = computed (() => flattenTree (tree .value ))
27+ const categoryOrder = [' system' , ' agent' , ' memory' , ' wiki' , ' skills' , ' tools' ]
28+
29+ const categories = computed (() => {
30+ const map = new Map <string , TreeNode >()
31+ for (const node of tree .value ) {
32+ if (node .type === ' dir' ) map .set (node .name , node )
33+ }
34+ const order = [... categoryOrder ]
35+ for (const node of tree .value ) {
36+ if (node .type === ' dir' && ! order .includes (node .name )) order .push (node .name )
37+ }
38+ return order
39+ .filter (name => map .has (name ))
40+ .map (name => ({
41+ key: name ,
42+ label: t (` prompts.cat_${name } ` , name ),
43+ node: map .get (name )! ,
44+ }))
45+ })
46+
47+ const collapsedCats = ref (new Set <string >())
48+
49+ function toggleCat(name : string ) {
50+ if (collapsedCats .value .has (name )) collapsedCats .value .delete (name )
51+ else collapsedCats .value .add (name )
52+ collapsedCats .value = new Set (collapsedCats .value )
53+ }
54+
55+ function flattenChildren(parent : TreeNode ) {
56+ return flattenTree (parent .children || [], 0 )
57+ }
2858
2959async function loadTree() {
3060 try {
@@ -132,22 +162,31 @@ onMounted(loadTree)
132162 <!-- Left: file tree -->
133163 <div class =" prompts-tree" >
134164 <div class =" prompts-tree-header" >{{ t('prompts.header') }}</div >
135- <div
136- v-for =" { node, depth } in flatTree"
137- :key =" node.path"
138- class =" tree-item"
139- :class =" {
140- 'tree-dir': node.type === 'dir',
141- 'tree-file': node.type === 'file',
142- 'tree-selected': selectedPath === node.path,
143- }"
144- :style =" { paddingLeft: `${10 + depth * 14}px` }"
145- @click =" node.type === 'dir' ? toggleDir(node.path) : selectFile(node.path)"
146- >
147- <span class =" tree-icon" >{{ node.type === 'dir' ? (collapsed.has(node.path) ? '▶' : '▼') : '·' }}</span >
148- <span class =" tree-name" >{{ node.name }}</span >
149- <span v-if =" node.isOverride" class =" tree-custom-dot" :title =" node.type === 'dir' ? t('prompts.contains_custom') : t('prompts.custom_title')" ></span >
150- </div >
165+ <template v-for =" cat in categories " :key =" cat .key " >
166+ <div class =" tree-category" @click =" toggleCat(cat.key)" >
167+ <span class =" tree-icon" >{{ collapsedCats.has(cat.key) ? '▶' : '▼' }}</span >
168+ <span class =" tree-cat-label" >{{ cat.label }}</span >
169+ <span v-if =" cat.node.isOverride" class =" tree-custom-dot" :title =" t('prompts.contains_custom')" ></span >
170+ </div >
171+ <template v-if =" ! collapsedCats .has (cat .key )" >
172+ <div
173+ v-for =" { node, depth } in flattenChildren(cat.node)"
174+ :key =" node.path"
175+ class =" tree-item"
176+ :class =" {
177+ 'tree-dir': node.type === 'dir',
178+ 'tree-file': node.type === 'file',
179+ 'tree-selected': selectedPath === node.path,
180+ }"
181+ :style =" { paddingLeft: `${14 + depth * 14}px` }"
182+ @click =" node.type === 'dir' ? toggleDir(node.path) : selectFile(node.path)"
183+ >
184+ <span class =" tree-icon" >{{ node.type === 'dir' ? (collapsed.has(node.path) ? '▶' : '▼') : '·' }}</span >
185+ <span class =" tree-name" >{{ node.name }}</span >
186+ <span v-if =" node.isOverride" class =" tree-custom-dot" :title =" node.type === 'dir' ? t('prompts.contains_custom') : t('prompts.custom_title')" ></span >
187+ </div >
188+ </template >
189+ </template >
151190 </div >
152191
153192 <!-- Right: editor -->
@@ -208,6 +247,22 @@ onMounted(loadTree)
208247 letter-spacing : 0.06em ;
209248 border-bottom : 1px solid #e8e6e3 ;
210249}
250+ .tree-category {
251+ display : flex ;
252+ align-items : center ;
253+ gap : 5px ;
254+ padding : 7px 10px 5px ;
255+ font-size : 12px ;
256+ font-weight : 700 ;
257+ color : #4a4a4a ;
258+ cursor : pointer ;
259+ user-select : none ;
260+ border-bottom : 1px solid #ece8e4 ;
261+ margin-top : 2px ;
262+ }
263+ .tree-category :first-child { margin-top : 0 ; }
264+ .tree-category :hover { background : #f0ece8 ; }
265+ .tree-cat-label { flex : 1 ; }
211266.tree-item {
212267 display : flex ;
213268 align-items : center ;
0 commit comments