mdk-skills 2.3.7 → 2.3.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.
@@ -0,0 +1 @@
1
+ .status-bar[data-v-bc9519f9]{background:#fff;border-bottom:1px solid #e5e7eb;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 24px;display:flex}.status-item[data-v-bc9519f9]{color:#555;align-items:center;gap:6px;font-size:13px;display:flex}.status-item.clickable[data-v-bc9519f9]{cursor:pointer}.status-item.clickable[data-v-bc9519f9]:hover{color:#2080f0}.status-divider[data-v-bc9519f9]{background:#e0e0e0;width:1px;height:20px}[data-theme=dark] .status-bar{background:#1a1a2e;border-bottom-color:#333}[data-theme=dark] .status-item{color:#aaa}[data-theme=dark] .status-divider{background:#333}*{box-sizing:border-box;margin:0;padding:0}html,body,#app{background:#f5f7fa;height:100%}body{overflow-y:auto}*{scrollbar-width:none;-ms-overflow-style:none}::-webkit-scrollbar{display:none}.app-layout{flex-direction:column;min-height:100vh;padding-top:56px;display:flex}.app-header{z-index:100;background:#fff;border-bottom:1px solid #e5e7eb;align-items:center;height:56px;padding:0 24px;display:flex;position:fixed;top:0;left:0;right:0}.header-inner{justify-content:space-between;align-items:center;width:100%;display:flex}.header-left{align-items:center;gap:32px;display:flex}.logo{color:#1a1a1a;white-space:nowrap;font-size:18px;font-weight:700}.app-content{flex:1;width:100%;max-width:1000px;margin:0 auto;padding:24px}.markdown-content{color:#333;word-wrap:break-word;font-size:14px;line-height:1.7}.markdown-content h1{border-bottom:1px solid #eee;margin:20px 0 12px;padding-bottom:8px;font-size:22px;font-weight:700}.markdown-content h2{border-bottom:1px solid #eee;margin:18px 0 10px;padding-bottom:6px;font-size:18px;font-weight:700}.markdown-content h3{margin:16px 0 8px;font-size:16px;font-weight:600}.markdown-content h4{margin:14px 0 6px;font-size:14px;font-weight:600}.markdown-content h5,.markdown-content h6{margin:12px 0 6px;font-size:13px;font-weight:600}.markdown-content p{margin:8px 0}.markdown-content ul,.markdown-content ol{margin:8px 0;padding-left:24px}.markdown-content li{margin:4px 0}.markdown-content blockquote{color:#555;background:#f0f7ff;border-left:4px solid #2080f0;margin:10px 0;padding:8px 16px}.markdown-content blockquote p{margin:4px 0}.markdown-content a{color:#2080f0;text-decoration:none}.markdown-content a:hover{text-decoration:underline}.markdown-content hr{border:none;border-top:1px solid #e0e0e0;margin:16px 0}.markdown-content table{border-collapse:collapse;width:100%;margin:12px 0;font-size:13px}.markdown-content th,.markdown-content td{text-align:left;border:1px solid #e0e0e0;padding:8px 12px}.markdown-content th{background:#f5f7fa;font-weight:600}.markdown-content tr:nth-child(2n) td{background:#fafafa}.markdown-content img{border-radius:4px;max-width:100%;margin:8px 0}.markdown-content code{color:#d63384;background:#f0f0f0;border-radius:3px;padding:2px 6px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:13px}.markdown-content pre{border:1px solid #e8e8e8;border-radius:6px;margin:12px 0;padding:0;position:relative;overflow:hidden}.markdown-content pre code{color:#333;tab-size:2;background:#f8f9fa;padding:14px 16px;font-size:13px;line-height:1.5;display:block;overflow-x:auto}.markdown-content pre .copy-btn{color:#999;cursor:pointer;opacity:0;background:#fff;border:1px solid #e0e0e0;border-radius:4px;padding:3px 8px;font-size:11px;transition:opacity .2s;position:absolute;top:6px;right:6px}.readme-fold{border:1px solid #e5e7eb;border-radius:6px;margin-bottom:20px;overflow:hidden}.fold-header{cursor:pointer;-webkit-user-select:none;user-select:none;background:#fafafa;align-items:center;gap:6px;padding:10px 16px;font-size:14px;font-weight:600;display:flex}.fold-header:hover{background:#f0f0f0}.fold-arrow{color:#999;font-size:11px;transition:transform .2s}.fold-arrow.open{transform:rotate(90deg)}.fold-body{padding:0 16px 16px}.markdown-content pre:hover .copy-btn{opacity:1}.markdown-content pre .copy-btn:hover{color:#2080f0;border-color:#2080f0}.header-right{align-items:center;gap:8px;display:flex}[data-theme=dark] html,[data-theme=dark] body,[data-theme=dark] #app{background:#1a1a2e}[data-theme=dark] .app-header{background:#1a1a2e;border-bottom-color:#333}[data-theme=dark] .app-content{background:0 0}[data-theme=dark] .readme-fold{border-color:#333}[data-theme=dark] .fold-header{color:#e0e0e0;background:#252538}[data-theme=dark] .fold-header:hover{background:#2a2a40}[data-theme=dark] .fold-body{background:#1e1e32}[data-theme=dark] .fold-arrow{color:#888}[data-theme=dark] .markdown-content{color:#ccc}[data-theme=dark] .markdown-content h1,[data-theme=dark] .markdown-content h2{color:#eee;border-bottom-color:#333}[data-theme=dark] .markdown-content h3,[data-theme=dark] .markdown-content h4{color:#eee}[data-theme=dark] .markdown-content code{color:#e06c9f;background:#2a2a40}[data-theme=dark] .markdown-content pre{border-color:#333}[data-theme=dark] .markdown-content pre code{color:#d4d4d4;background:#1e1e2e}[data-theme=dark] .markdown-content blockquote{color:#bbb;background:#252538;border-left-color:#4a6cf7}[data-theme=dark] .markdown-content a{color:#6a8cff}[data-theme=dark] .markdown-content th{background:#252538}[data-theme=dark] .markdown-content td{border-color:#333}[data-theme=dark] .markdown-content tr:nth-child(2n) td{background:#222238}[data-theme=dark] .markdown-content hr{border-top-color:#333}[data-theme=dark] .markdown-content img{filter:brightness(.85)}[data-theme=dark] .page-header h2{color:#e0e0e0}[data-theme=dark] .scene-desc{color:#aaa}.fade-enter-active,.fade-leave-active{transition:opacity .9s,transform .9s}.fade-enter-from{opacity:0;transform:translateY(6px)}.fade-leave-to{opacity:0}.skill-card[data-v-f2c0de50]{cursor:pointer;margin-bottom:12px;transition:box-shadow .2s}.skill-card[data-v-f2c0de50]:hover{box-shadow:0 2px 8px #00000014}.skill-meta[data-v-f2c0de50]{align-items:center;gap:8px;margin-bottom:8px;display:flex}.skill-version[data-v-f2c0de50]{color:#888;font-family:monospace;font-size:12px}.skill-desc[data-v-f2c0de50]{color:#666;text-overflow:ellipsis;white-space:nowrap;margin:0;font-size:13px;overflow:hidden}.modal-overlay[data-v-ac8adc41]{z-index:2000;background:#00000073;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.modal-card[data-v-ac8adc41]{background:#fff;border-radius:8px;flex-direction:column;width:90%;max-height:85vh;display:flex;box-shadow:0 8px 32px #0000001f}.modal-header[data-v-ac8adc41]{justify-content:space-between;align-items:center;padding:14px 20px 0;display:flex}.modal-title[data-v-ac8adc41]{color:#333;font-size:16px;font-weight:600}.modal-close[data-v-ac8adc41]{color:#999;cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;font-size:20px;line-height:1;transition:background .15s,color .15s;display:flex}.modal-close[data-v-ac8adc41]:hover{color:#333;background:#f0f0f0}.modal-body[data-v-ac8adc41]{padding:0;overflow-y:auto}.modal-footer[data-v-ac8adc41]{border-top:1px solid #f0f0f0;justify-content:flex-end;gap:8px;padding:12px 20px 16px;display:flex}.modal-fade-enter-active[data-v-ac8adc41]{transition:opacity .2s}.modal-fade-leave-active[data-v-ac8adc41]{transition:opacity .15s}.modal-fade-enter-from[data-v-ac8adc41],.modal-fade-leave-to[data-v-ac8adc41]{opacity:0}.dashboard[data-v-264ec45c]{overflow-anchor:auto}.page-header[data-v-264ec45c]{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin-bottom:4px;display:flex}.page-header h2[data-v-264ec45c]{font-size:20px;font-weight:600}.header-actions[data-v-264ec45c]{align-items:center;gap:8px;display:flex}.tag-filter[data-v-264ec45c]{flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:16px;display:flex}.detail-status[data-v-264ec45c]{justify-content:center;padding:40px 0;display:flex}.detail-body[data-v-264ec45c]{max-height:65vh;padding:16px 24px;overflow-y:auto}.edit-panel[data-v-264ec45c]{margin-bottom:4px}.edit-row[data-v-264ec45c]{align-items:flex-start;gap:10px;margin-bottom:10px;display:flex}.edit-label[data-v-264ec45c]{color:#888;flex-shrink:0;width:50px;font-size:13px;line-height:30px}.update-count-hint[data-v-264ec45c]{color:#e68a00;margin-left:8px;font-family:monospace;font-size:12px}.pull-modal-body[data-v-264ec45c]{min-height:100px}.pull-section[data-v-264ec45c]{margin-top:12px}.pull-input-row[data-v-264ec45c]{gap:8px;margin-bottom:8px;display:flex}.pull-input-row .n-input[data-v-264ec45c]{flex:1}.pull-error[data-v-264ec45c]{margin-bottom:8px}.pull-result[data-v-264ec45c]{margin-top:8px}.pull-result-line[data-v-264ec45c]{flex-wrap:wrap;align-items:center;gap:4px;margin-bottom:8px;font-size:13px;display:flex}.pull-result-label[data-v-264ec45c]{color:#888;flex-shrink:0}.pull-result-hint[data-v-264ec45c]{color:#999;font-size:12px}.install-panel[data-v-264ec45c]{background:#00000005;border-radius:6px;margin-top:12px;padding:12px}.install-panel-label[data-v-264ec45c]{color:#666;margin-bottom:8px;font-size:13px}.install-check-list[data-v-264ec45c]{margin-bottom:10px}.install-btn[data-v-264ec45c]{float:right}.edit-actions[data-v-264ec45c]{justify-content:flex-end;gap:8px;display:flex}.skill-group[data-v-264ec45c]{margin-bottom:4px}.group-header[data-v-264ec45c]{cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:4px;align-items:center;gap:8px;padding:8px 4px;display:flex}.group-header[data-v-264ec45c]:hover{background:#00000008}.fold-arrow[data-v-264ec45c]{color:#999;flex-shrink:0;font-size:10px;transition:transform .2s}.fold-arrow.open[data-v-264ec45c]{transform:rotate(90deg)}.group-label[data-v-264ec45c]{color:inherit;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;font-weight:600;overflow:hidden}.group-count[data-v-264ec45c]{color:#999;flex-shrink:0;font-size:12px}.group-update-btn[data-v-264ec45c]{flex-shrink:0}.group-body[data-v-264ec45c]{padding-left:4px}.source-info[data-v-264ec45c]{margin-bottom:4px}.source-row[data-v-264ec45c]{align-items:center;gap:10px;margin-bottom:6px;font-size:13px;display:flex}.source-label[data-v-264ec45c]{color:#888;flex-shrink:0;width:70px}.source-value[data-v-264ec45c]{word-break:break-all}.local-tag[data-v-264ec45c]{color:#2e7d32;background:#e8f5e9;border-radius:3px;padding:1px 8px;font-size:12px;display:inline-block}.path-text[data-v-264ec45c]{color:#666;font-family:monospace;font-size:12px}.source-actions[data-v-264ec45c]{gap:8px;margin-top:8px;display:flex}.local-hint[data-v-264ec45c]{color:#999;background:#00000005;border-radius:4px;margin-top:8px;padding:8px;font-size:12px;line-height:1.5}.siblings-body[data-v-264ec45c]{min-height:60px}.siblings-desc[data-v-264ec45c]{margin-bottom:12px;font-size:13px;line-height:1.6}.siblings-list[data-v-264ec45c]{flex-direction:column;gap:8px;margin-bottom:16px;display:flex}.siblings-actions[data-v-264ec45c]{justify-content:flex-end;gap:8px;display:flex}.batch-modal-body[data-v-264ec45c]{min-height:60px}.batch-desc[data-v-264ec45c]{margin-bottom:16px;font-size:13px;line-height:1.6}.batch-actions[data-v-264ec45c]{justify-content:flex-end;gap:8px;display:flex}.batch-executing[data-v-264ec45c]{color:#666;justify-content:center;align-items:center;gap:12px;padding:24px 0;font-size:13px;display:flex}.batch-result[data-v-264ec45c]{margin-bottom:16px}.batch-result-line[data-v-264ec45c]{flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:10px;font-size:13px;display:flex}.batch-result-label[data-v-264ec45c]{color:#888;flex-shrink:0}.page-header[data-v-e51b3dfc]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.page-header h2[data-v-e51b3dfc]{font-size:20px;font-weight:600}.scene-grid[data-v-e51b3dfc]{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px;margin:2px;display:grid}.scene-card[data-v-e51b3dfc]{transition:box-shadow .2s}.scene-card.active[data-v-e51b3dfc]{box-shadow:0 0 0 2px #2080f0}.scene-desc[data-v-e51b3dfc]{color:#666;margin:0;font-size:13px}.scene-footer[data-v-e51b3dfc]{justify-content:space-between;align-items:center;display:flex}.hint-text[data-v-e51b3dfc]{color:#999;font-size:12px}.modal-skill-groups[data-v-e51b3dfc]{max-height:50vh;overflow-y:auto}.skill-group[data-v-e51b3dfc]{margin-bottom:2px}.skill-group-header[data-v-e51b3dfc]{cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:4px;align-items:center;gap:6px;padding:6px 4px;font-size:13px;display:flex}.skill-group-header[data-v-e51b3dfc]:hover{background:#00000008}.fold-arrow[data-v-e51b3dfc]{color:#999;flex-shrink:0;font-size:10px;transition:transform .2s}.fold-arrow.open[data-v-e51b3dfc]{transform:rotate(90deg)}.skill-group-label[data-v-e51b3dfc]{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-weight:600;overflow:hidden}.skill-group-count[data-v-e51b3dfc]{color:#999;flex-shrink:0;font-size:12px}.skill-group-body[data-v-e51b3dfc]{padding:4px 0 4px 16px}.page-header[data-v-c7da8635]{margin-bottom:20px}.page-header h2[data-v-c7da8635]{font-size:20px;font-weight:600}.section[data-v-c7da8635]{margin-bottom:20px}.init-alert[data-v-c7da8635]{margin-bottom:12px}.missing-list[data-v-c7da8635]{flex-direction:column;gap:4px;display:flex}.missing-item[data-v-c7da8635]{font-size:13px;line-height:1.6}.missing-item code[data-v-c7da8635]{background:#0000000f;border-radius:3px;padding:1px 6px;font-size:12px}.skill-tag[data-v-c7da8635]{margin:1px 2px;display:inline-block}.missing-hint[data-v-c7da8635]{opacity:.7;margin-top:4px;font-size:12px}.source-status[data-v-c7da8635]{margin-bottom:16px}.source-actions[data-v-c7da8635]{flex-direction:column;gap:12px;display:flex}.action-buttons[data-v-c7da8635]{gap:8px;display:flex}.healthy-text[data-v-c7da8635]{color:#18a058;font-size:13px}.issue-text[data-v-c7da8635]{color:#d03050;font-size:13px}.readme-dialog-desc[data-v-c7da8635]{color:#555;margin-bottom:16px;font-size:14px}.readme-checkbox[data-v-c7da8635]{align-items:flex-start;margin-bottom:12px;display:flex}.readme-checkbox-content[data-v-c7da8635]{flex-direction:column;gap:2px;display:flex}.readme-checkbox-title[data-v-c7da8635]{font-size:14px;font-weight:500}.readme-checkbox-desc[data-v-c7da8635]{color:#999;font-size:12px}.page-header[data-v-97d38fe1]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.page-header h2[data-v-97d38fe1]{font-size:20px;font-weight:600}.fade-enter-active[data-v-97d38fe1],.fade-leave-active[data-v-97d38fe1]{transition:opacity .2s}.fade-enter-from[data-v-97d38fe1],.fade-leave-to[data-v-97d38fe1]{opacity:0}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>mdk-skills 管理面板</title>
7
- <script type="module" crossorigin src="/assets/index-BpCWcoAd.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-D0ouuycs.css">
7
+ <script type="module" crossorigin src="/assets/index-B8vLmLEm.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-xXELhuZi.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="app"></div>
@@ -10,6 +10,9 @@
10
10
  <div class="modal-body">
11
11
  <slot />
12
12
  </div>
13
+ <div v-if="$slots.footer" class="modal-footer">
14
+ <slot name="footer" />
15
+ </div>
13
16
  </div>
14
17
  </div>
15
18
  </Transition>
@@ -36,8 +39,9 @@ function onMaskClick() {
36
39
  if (props.maskClosable) close();
37
40
  }
38
41
 
39
- // Escape 关闭
42
+ // Escape 关闭 + body scroll lock
40
43
  let escHandler = null;
44
+ let prevOverflow = null;
41
45
  watch(
42
46
  () => props.show,
43
47
  (v) => {
@@ -46,10 +50,15 @@ watch(
46
50
  escHandler = null;
47
51
  }
48
52
  if (v) {
53
+ prevOverflow = document.body.style.overflow;
54
+ document.body.style.overflow = "hidden";
49
55
  escHandler = (e) => {
50
56
  if (e.key === "Escape") close();
51
57
  };
52
58
  document.addEventListener("keydown", escHandler);
59
+ } else {
60
+ document.body.style.overflow = prevOverflow || "";
61
+ prevOverflow = null;
53
62
  }
54
63
  },
55
64
  { immediate: true },
@@ -57,6 +66,7 @@ watch(
57
66
 
58
67
  onUnmounted(() => {
59
68
  if (escHandler) document.removeEventListener("keydown", escHandler);
69
+ if (prevOverflow !== null) document.body.style.overflow = prevOverflow || "";
60
70
  });
61
71
  </script>
62
72
 
@@ -120,6 +130,14 @@ onUnmounted(() => {
120
130
  overflow-y: auto;
121
131
  }
122
132
 
133
+ .modal-footer {
134
+ display: flex;
135
+ justify-content: flex-end;
136
+ gap: 8px;
137
+ padding: 12px 20px 16px;
138
+ border-top: 1px solid #f0f0f0;
139
+ }
140
+
123
141
  /* fade 过渡 */
124
142
  .modal-fade-enter-active {
125
143
  transition: opacity 0.2s ease;
@@ -102,21 +102,30 @@
102
102
  </n-spin>
103
103
 
104
104
  <!-- 自定义勾选弹窗 -->
105
- <n-modal
106
- v-model:show="showCustom"
105
+ <ModalComp
106
+ :show="showCustom"
107
107
  title="自定义技能组合"
108
- preset="card"
109
- style="width: 480px"
108
+ width="520px"
109
+ @update:show="(v) => { if (!v) showCustom = false }"
110
110
  >
111
111
  <n-checkbox-group v-model:value="customSelected">
112
- <n-space vertical>
113
- <n-checkbox
114
- v-for="skill in allSkills"
115
- :key="skill.name"
116
- :value="skill.name"
117
- :label="skill.name"
118
- />
119
- </n-space>
112
+ <div class="modal-skill-groups">
113
+ <div v-for="group in groupedSkills" :key="group.key" class="skill-group">
114
+ <div class="skill-group-header" @click="toggleGroup(group.key)">
115
+ <span class="fold-arrow" :class="{ open: groupOpen[group.key] }">▶</span>
116
+ <span class="skill-group-label">{{ group.type === 'remote' ? group.url : '本地技能' }}</span>
117
+ <span class="skill-group-count">{{ group.skills.length }}</span>
118
+ </div>
119
+ <div v-show="groupOpen[group.key]" class="skill-group-body">
120
+ <n-checkbox
121
+ v-for="skill in group.skills"
122
+ :key="skill.name"
123
+ :value="skill.name"
124
+ :label="skill.name"
125
+ />
126
+ </div>
127
+ </div>
128
+ </div>
120
129
  </n-checkbox-group>
121
130
  <template #footer>
122
131
  <n-button
@@ -127,15 +136,15 @@
127
136
  确认安装
128
137
  </n-button>
129
138
  </template>
130
- </n-modal>
139
+ </ModalComp>
131
140
 
132
141
  <!-- 编辑弹窗 -->
133
- <n-modal
134
- v-model:show="showEditor"
142
+ <ModalComp
143
+ :show="showEditor"
135
144
  :title="editingProfile ? '编辑场景' : '新建场景'"
136
- preset="card"
137
- style="width: 520px"
145
+ width="560px"
138
146
  :mask-closable="false"
147
+ @update:show="(v) => { if (!v) showEditor = false }"
139
148
  >
140
149
  <n-form :model="formData" label-placement="top">
141
150
  <n-form-item label="场景名称" required>
@@ -156,14 +165,23 @@
156
165
  <n-divider />
157
166
  <n-form-item label="包含的技能">
158
167
  <n-checkbox-group v-model:value="formData.skills">
159
- <n-space vertical>
160
- <n-checkbox
161
- v-for="skill in allSkills"
162
- :key="skill.name"
163
- :value="skill.name"
164
- :label="skill.name"
165
- />
166
- </n-space>
168
+ <div class="modal-skill-groups">
169
+ <div v-for="group in groupedSkills" :key="group.key" class="skill-group">
170
+ <div class="skill-group-header" @click="toggleGroup(group.key)">
171
+ <span class="fold-arrow" :class="{ open: groupOpen[group.key] }">▶</span>
172
+ <span class="skill-group-label">{{ group.type === 'remote' ? group.url : '本地技能' }}</span>
173
+ <span class="skill-group-count">{{ group.skills.length }}</span>
174
+ </div>
175
+ <div v-show="groupOpen[group.key]" class="skill-group-body">
176
+ <n-checkbox
177
+ v-for="skill in group.skills"
178
+ :key="skill.name"
179
+ :value="skill.name"
180
+ :label="skill.name"
181
+ />
182
+ </div>
183
+ </div>
184
+ </div>
167
185
  </n-checkbox-group>
168
186
  </n-form-item>
169
187
  <n-divider />
@@ -184,14 +202,12 @@
184
202
  </n-form-item>
185
203
  </n-form>
186
204
  <template #footer>
187
- <n-space justify="end">
188
- <n-button @click="showEditor = false">取消</n-button>
189
- <n-button type="primary" :loading="saving" @click="onSave">
190
- 保存
191
- </n-button>
192
- </n-space>
205
+ <n-button @click="showEditor = false">取消</n-button>
206
+ <n-button type="primary" :loading="saving" @click="onSave">
207
+ 保存
208
+ </n-button>
193
209
  </template>
194
- </n-modal>
210
+ </ModalComp>
195
211
  </div>
196
212
  </template>
197
213
 
@@ -202,6 +218,7 @@ import { NIcon } from "naive-ui";
202
218
  import { AddOutline, PencilOutline, TrashOutline } from "@vicons/ionicons5";
203
219
  import { marked } from "marked";
204
220
  import hljs from "highlight.js";
221
+ import ModalComp from "../components/ModalComp.vue";
205
222
  import {
206
223
  getProfiles,
207
224
  applyProfile,
@@ -268,9 +285,41 @@ const formData = ref({
268
285
  always_apply: [],
269
286
  });
270
287
 
288
+ // 技能分组折叠
289
+ const groupOpen = ref({});
290
+ function toggleGroup(key) {
291
+ groupOpen.value[key] = !groupOpen.value[key];
292
+ }
293
+
271
294
  // 过滤掉不可见的场景(如已有内置)
272
295
  const filteredProfiles = computed(() => profiles.value);
273
296
 
297
+ // 技能按源分组
298
+ const groupedSkills = computed(() => {
299
+ const groups = {};
300
+ for (const skill of allSkills.value) {
301
+ const isRemote = skill.source?.type === "remote";
302
+ const key = isRemote ? skill.source.url : "__local__";
303
+ if (!groups[key]) {
304
+ groups[key] = {
305
+ key,
306
+ type: isRemote ? "remote" : "local",
307
+ url: skill.source?.url || "",
308
+ skills: [],
309
+ };
310
+ }
311
+ groups[key].skills.push(skill);
312
+ }
313
+ for (const key of Object.keys(groups)) {
314
+ if (groupOpen.value[key] === undefined) groupOpen.value[key] = true;
315
+ }
316
+ return Object.values(groups).sort((a, b) => {
317
+ if (a.type === "remote" && b.type === "local") return -1;
318
+ if (a.type === "local" && b.type === "remote") return 1;
319
+ return 0;
320
+ });
321
+ });
322
+
274
323
  function stripFrontmatter(text) {
275
324
  if (!text) return text;
276
325
  return text.replace(/^---[\s\S]*?---\s*/, "");
@@ -471,4 +520,59 @@ onMounted(() => {
471
520
  font-size: 12px;
472
521
  color: #999;
473
522
  }
523
+
524
+ /* 技能分组 */
525
+ .modal-skill-groups {
526
+ max-height: 50vh;
527
+ overflow-y: auto;
528
+ }
529
+
530
+ .skill-group {
531
+ margin-bottom: 2px;
532
+ }
533
+
534
+ .skill-group-header {
535
+ display: flex;
536
+ align-items: center;
537
+ gap: 6px;
538
+ padding: 6px 4px;
539
+ cursor: pointer;
540
+ border-radius: 4px;
541
+ user-select: none;
542
+ font-size: 13px;
543
+ }
544
+
545
+ .skill-group-header:hover {
546
+ background: rgba(0, 0, 0, 0.03);
547
+ }
548
+
549
+ .fold-arrow {
550
+ font-size: 10px;
551
+ transition: transform 0.2s;
552
+ color: #999;
553
+ flex-shrink: 0;
554
+ }
555
+
556
+ .fold-arrow.open {
557
+ transform: rotate(90deg);
558
+ }
559
+
560
+ .skill-group-label {
561
+ font-weight: 600;
562
+ overflow: hidden;
563
+ text-overflow: ellipsis;
564
+ white-space: nowrap;
565
+ flex: 1;
566
+ min-width: 0;
567
+ }
568
+
569
+ .skill-group-count {
570
+ color: #999;
571
+ font-size: 12px;
572
+ flex-shrink: 0;
573
+ }
574
+
575
+ .skill-group-body {
576
+ padding: 4px 0 4px 16px;
577
+ }
474
578
  </style>
@@ -102,12 +102,12 @@
102
102
  </n-card>
103
103
 
104
104
  <!-- 创建 README.md 对话框 -->
105
- <n-modal
106
- v-model:show="showReadmeDialog"
105
+ <ModalComp
106
+ :show="showReadmeDialog"
107
107
  title="创建文档"
108
- preset="card"
109
- style="width: 520px"
108
+ width="520px"
110
109
  :mask-closable="false"
110
+ @update:show="(v) => { if (!v) showReadmeDialog = false }"
111
111
  >
112
112
  <div class="readme-dialog-desc">检测到缺少以下文档,是否创建?</div>
113
113
 
@@ -137,14 +137,12 @@
137
137
  </n-form>
138
138
 
139
139
  <template #footer>
140
- <n-space justify="end">
141
- <n-button @click="showReadmeDialog = false">跳过</n-button>
142
- <n-button type="primary" :loading="creatingReadme" @click="onCreateReadme">
143
- 创建
144
- </n-button>
145
- </n-space>
140
+ <n-button @click="showReadmeDialog = false">跳过</n-button>
141
+ <n-button type="primary" :loading="creatingReadme" @click="onCreateReadme">
142
+ 创建
143
+ </n-button>
146
144
  </template>
147
- </n-modal>
145
+ </ModalComp>
148
146
 
149
147
  <!-- 健康检查 -->
150
148
  <n-card title="健康检查" size="small" class="section">
@@ -179,6 +177,7 @@
179
177
  <script setup>
180
178
  import { ref, computed, onMounted } from "vue";
181
179
  import { useMessage } from "naive-ui";
180
+ import ModalComp from "../components/ModalComp.vue";
182
181
  import {
183
182
  CheckmarkCircleOutline,
184
183
  CloseCircleOutline,
@@ -1 +0,0 @@
1
- .status-bar[data-v-bc9519f9]{background:#fff;border-bottom:1px solid #e5e7eb;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 24px;display:flex}.status-item[data-v-bc9519f9]{color:#555;align-items:center;gap:6px;font-size:13px;display:flex}.status-item.clickable[data-v-bc9519f9]{cursor:pointer}.status-item.clickable[data-v-bc9519f9]:hover{color:#2080f0}.status-divider[data-v-bc9519f9]{background:#e0e0e0;width:1px;height:20px}[data-theme=dark] .status-bar{background:#1a1a2e;border-bottom-color:#333}[data-theme=dark] .status-item{color:#aaa}[data-theme=dark] .status-divider{background:#333}*{box-sizing:border-box;margin:0;padding:0}html,body,#app{background:#f5f7fa;height:100%}body{overflow-y:auto}*{scrollbar-width:none;-ms-overflow-style:none}::-webkit-scrollbar{display:none}.app-layout{flex-direction:column;min-height:100vh;padding-top:56px;display:flex}.app-header{z-index:100;background:#fff;border-bottom:1px solid #e5e7eb;align-items:center;height:56px;padding:0 24px;display:flex;position:fixed;top:0;left:0;right:0}.header-inner{justify-content:space-between;align-items:center;width:100%;display:flex}.header-left{align-items:center;gap:32px;display:flex}.logo{color:#1a1a1a;white-space:nowrap;font-size:18px;font-weight:700}.app-content{flex:1;width:100%;max-width:1000px;margin:0 auto;padding:24px}.markdown-content{color:#333;word-wrap:break-word;font-size:14px;line-height:1.7}.markdown-content h1{border-bottom:1px solid #eee;margin:20px 0 12px;padding-bottom:8px;font-size:22px;font-weight:700}.markdown-content h2{border-bottom:1px solid #eee;margin:18px 0 10px;padding-bottom:6px;font-size:18px;font-weight:700}.markdown-content h3{margin:16px 0 8px;font-size:16px;font-weight:600}.markdown-content h4{margin:14px 0 6px;font-size:14px;font-weight:600}.markdown-content h5,.markdown-content h6{margin:12px 0 6px;font-size:13px;font-weight:600}.markdown-content p{margin:8px 0}.markdown-content ul,.markdown-content ol{margin:8px 0;padding-left:24px}.markdown-content li{margin:4px 0}.markdown-content blockquote{color:#555;background:#f0f7ff;border-left:4px solid #2080f0;margin:10px 0;padding:8px 16px}.markdown-content blockquote p{margin:4px 0}.markdown-content a{color:#2080f0;text-decoration:none}.markdown-content a:hover{text-decoration:underline}.markdown-content hr{border:none;border-top:1px solid #e0e0e0;margin:16px 0}.markdown-content table{border-collapse:collapse;width:100%;margin:12px 0;font-size:13px}.markdown-content th,.markdown-content td{text-align:left;border:1px solid #e0e0e0;padding:8px 12px}.markdown-content th{background:#f5f7fa;font-weight:600}.markdown-content tr:nth-child(2n) td{background:#fafafa}.markdown-content img{border-radius:4px;max-width:100%;margin:8px 0}.markdown-content code{color:#d63384;background:#f0f0f0;border-radius:3px;padding:2px 6px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:13px}.markdown-content pre{border:1px solid #e8e8e8;border-radius:6px;margin:12px 0;padding:0;position:relative;overflow:hidden}.markdown-content pre code{color:#333;tab-size:2;background:#f8f9fa;padding:14px 16px;font-size:13px;line-height:1.5;display:block;overflow-x:auto}.markdown-content pre .copy-btn{color:#999;cursor:pointer;opacity:0;background:#fff;border:1px solid #e0e0e0;border-radius:4px;padding:3px 8px;font-size:11px;transition:opacity .2s;position:absolute;top:6px;right:6px}.readme-fold{border:1px solid #e5e7eb;border-radius:6px;margin-bottom:20px;overflow:hidden}.fold-header{cursor:pointer;-webkit-user-select:none;user-select:none;background:#fafafa;align-items:center;gap:6px;padding:10px 16px;font-size:14px;font-weight:600;display:flex}.fold-header:hover{background:#f0f0f0}.fold-arrow{color:#999;font-size:11px;transition:transform .2s}.fold-arrow.open{transform:rotate(90deg)}.fold-body{padding:0 16px 16px}.markdown-content pre:hover .copy-btn{opacity:1}.markdown-content pre .copy-btn:hover{color:#2080f0;border-color:#2080f0}.header-right{align-items:center;gap:8px;display:flex}[data-theme=dark] html,[data-theme=dark] body,[data-theme=dark] #app{background:#1a1a2e}[data-theme=dark] .app-header{background:#1a1a2e;border-bottom-color:#333}[data-theme=dark] .app-content{background:0 0}[data-theme=dark] .readme-fold{border-color:#333}[data-theme=dark] .fold-header{color:#e0e0e0;background:#252538}[data-theme=dark] .fold-header:hover{background:#2a2a40}[data-theme=dark] .fold-body{background:#1e1e32}[data-theme=dark] .fold-arrow{color:#888}[data-theme=dark] .markdown-content{color:#ccc}[data-theme=dark] .markdown-content h1,[data-theme=dark] .markdown-content h2{color:#eee;border-bottom-color:#333}[data-theme=dark] .markdown-content h3,[data-theme=dark] .markdown-content h4{color:#eee}[data-theme=dark] .markdown-content code{color:#e06c9f;background:#2a2a40}[data-theme=dark] .markdown-content pre{border-color:#333}[data-theme=dark] .markdown-content pre code{color:#d4d4d4;background:#1e1e2e}[data-theme=dark] .markdown-content blockquote{color:#bbb;background:#252538;border-left-color:#4a6cf7}[data-theme=dark] .markdown-content a{color:#6a8cff}[data-theme=dark] .markdown-content th{background:#252538}[data-theme=dark] .markdown-content td{border-color:#333}[data-theme=dark] .markdown-content tr:nth-child(2n) td{background:#222238}[data-theme=dark] .markdown-content hr{border-top-color:#333}[data-theme=dark] .markdown-content img{filter:brightness(.85)}[data-theme=dark] .page-header h2{color:#e0e0e0}[data-theme=dark] .scene-desc{color:#aaa}.fade-enter-active,.fade-leave-active{transition:opacity .9s,transform .9s}.fade-enter-from{opacity:0;transform:translateY(6px)}.fade-leave-to{opacity:0}.skill-card[data-v-f2c0de50]{cursor:pointer;margin-bottom:12px;transition:box-shadow .2s}.skill-card[data-v-f2c0de50]:hover{box-shadow:0 2px 8px #00000014}.skill-meta[data-v-f2c0de50]{align-items:center;gap:8px;margin-bottom:8px;display:flex}.skill-version[data-v-f2c0de50]{color:#888;font-family:monospace;font-size:12px}.skill-desc[data-v-f2c0de50]{color:#666;text-overflow:ellipsis;white-space:nowrap;margin:0;font-size:13px;overflow:hidden}.modal-overlay[data-v-5922eeb2]{z-index:2000;background:#00000073;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.modal-card[data-v-5922eeb2]{background:#fff;border-radius:8px;flex-direction:column;width:90%;max-height:85vh;display:flex;box-shadow:0 8px 32px #0000001f}.modal-header[data-v-5922eeb2]{justify-content:space-between;align-items:center;padding:14px 20px 0;display:flex}.modal-title[data-v-5922eeb2]{color:#333;font-size:16px;font-weight:600}.modal-close[data-v-5922eeb2]{color:#999;cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;font-size:20px;line-height:1;transition:background .15s,color .15s;display:flex}.modal-close[data-v-5922eeb2]:hover{color:#333;background:#f0f0f0}.modal-body[data-v-5922eeb2]{padding:0;overflow-y:auto}.modal-fade-enter-active[data-v-5922eeb2]{transition:opacity .2s}.modal-fade-leave-active[data-v-5922eeb2]{transition:opacity .15s}.modal-fade-enter-from[data-v-5922eeb2],.modal-fade-leave-to[data-v-5922eeb2]{opacity:0}.dashboard[data-v-264ec45c]{overflow-anchor:auto}.page-header[data-v-264ec45c]{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin-bottom:4px;display:flex}.page-header h2[data-v-264ec45c]{font-size:20px;font-weight:600}.header-actions[data-v-264ec45c]{align-items:center;gap:8px;display:flex}.tag-filter[data-v-264ec45c]{flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:16px;display:flex}.detail-status[data-v-264ec45c]{justify-content:center;padding:40px 0;display:flex}.detail-body[data-v-264ec45c]{max-height:65vh;padding:16px 24px;overflow-y:auto}.edit-panel[data-v-264ec45c]{margin-bottom:4px}.edit-row[data-v-264ec45c]{align-items:flex-start;gap:10px;margin-bottom:10px;display:flex}.edit-label[data-v-264ec45c]{color:#888;flex-shrink:0;width:50px;font-size:13px;line-height:30px}.update-count-hint[data-v-264ec45c]{color:#e68a00;margin-left:8px;font-family:monospace;font-size:12px}.pull-modal-body[data-v-264ec45c]{min-height:100px}.pull-section[data-v-264ec45c]{margin-top:12px}.pull-input-row[data-v-264ec45c]{gap:8px;margin-bottom:8px;display:flex}.pull-input-row .n-input[data-v-264ec45c]{flex:1}.pull-error[data-v-264ec45c]{margin-bottom:8px}.pull-result[data-v-264ec45c]{margin-top:8px}.pull-result-line[data-v-264ec45c]{flex-wrap:wrap;align-items:center;gap:4px;margin-bottom:8px;font-size:13px;display:flex}.pull-result-label[data-v-264ec45c]{color:#888;flex-shrink:0}.pull-result-hint[data-v-264ec45c]{color:#999;font-size:12px}.install-panel[data-v-264ec45c]{background:#00000005;border-radius:6px;margin-top:12px;padding:12px}.install-panel-label[data-v-264ec45c]{color:#666;margin-bottom:8px;font-size:13px}.install-check-list[data-v-264ec45c]{margin-bottom:10px}.install-btn[data-v-264ec45c]{float:right}.edit-actions[data-v-264ec45c]{justify-content:flex-end;gap:8px;display:flex}.skill-group[data-v-264ec45c]{margin-bottom:4px}.group-header[data-v-264ec45c]{cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:4px;align-items:center;gap:8px;padding:8px 4px;display:flex}.group-header[data-v-264ec45c]:hover{background:#00000008}.fold-arrow[data-v-264ec45c]{color:#999;flex-shrink:0;font-size:10px;transition:transform .2s}.fold-arrow.open[data-v-264ec45c]{transform:rotate(90deg)}.group-label[data-v-264ec45c]{color:inherit;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;font-weight:600;overflow:hidden}.group-count[data-v-264ec45c]{color:#999;flex-shrink:0;font-size:12px}.group-update-btn[data-v-264ec45c]{flex-shrink:0}.group-body[data-v-264ec45c]{padding-left:4px}.source-info[data-v-264ec45c]{margin-bottom:4px}.source-row[data-v-264ec45c]{align-items:center;gap:10px;margin-bottom:6px;font-size:13px;display:flex}.source-label[data-v-264ec45c]{color:#888;flex-shrink:0;width:70px}.source-value[data-v-264ec45c]{word-break:break-all}.local-tag[data-v-264ec45c]{color:#2e7d32;background:#e8f5e9;border-radius:3px;padding:1px 8px;font-size:12px;display:inline-block}.path-text[data-v-264ec45c]{color:#666;font-family:monospace;font-size:12px}.source-actions[data-v-264ec45c]{gap:8px;margin-top:8px;display:flex}.local-hint[data-v-264ec45c]{color:#999;background:#00000005;border-radius:4px;margin-top:8px;padding:8px;font-size:12px;line-height:1.5}.siblings-body[data-v-264ec45c]{min-height:60px}.siblings-desc[data-v-264ec45c]{margin-bottom:12px;font-size:13px;line-height:1.6}.siblings-list[data-v-264ec45c]{flex-direction:column;gap:8px;margin-bottom:16px;display:flex}.siblings-actions[data-v-264ec45c]{justify-content:flex-end;gap:8px;display:flex}.batch-modal-body[data-v-264ec45c]{min-height:60px}.batch-desc[data-v-264ec45c]{margin-bottom:16px;font-size:13px;line-height:1.6}.batch-actions[data-v-264ec45c]{justify-content:flex-end;gap:8px;display:flex}.batch-executing[data-v-264ec45c]{color:#666;justify-content:center;align-items:center;gap:12px;padding:24px 0;font-size:13px;display:flex}.batch-result[data-v-264ec45c]{margin-bottom:16px}.batch-result-line[data-v-264ec45c]{flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:10px;font-size:13px;display:flex}.batch-result-label[data-v-264ec45c]{color:#888;flex-shrink:0}.page-header[data-v-1736a530]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.page-header h2[data-v-1736a530]{font-size:20px;font-weight:600}.scene-grid[data-v-1736a530]{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px;margin:2px;display:grid}.scene-card[data-v-1736a530]{transition:box-shadow .2s}.scene-card.active[data-v-1736a530]{box-shadow:0 0 0 2px #2080f0}.scene-desc[data-v-1736a530]{color:#666;margin:0;font-size:13px}.scene-footer[data-v-1736a530]{justify-content:space-between;align-items:center;display:flex}.hint-text[data-v-1736a530]{color:#999;font-size:12px}.page-header[data-v-5f659620]{margin-bottom:20px}.page-header h2[data-v-5f659620]{font-size:20px;font-weight:600}.section[data-v-5f659620]{margin-bottom:20px}.init-alert[data-v-5f659620]{margin-bottom:12px}.missing-list[data-v-5f659620]{flex-direction:column;gap:4px;display:flex}.missing-item[data-v-5f659620]{font-size:13px;line-height:1.6}.missing-item code[data-v-5f659620]{background:#0000000f;border-radius:3px;padding:1px 6px;font-size:12px}.skill-tag[data-v-5f659620]{margin:1px 2px;display:inline-block}.missing-hint[data-v-5f659620]{opacity:.7;margin-top:4px;font-size:12px}.source-status[data-v-5f659620]{margin-bottom:16px}.source-actions[data-v-5f659620]{flex-direction:column;gap:12px;display:flex}.action-buttons[data-v-5f659620]{gap:8px;display:flex}.healthy-text[data-v-5f659620]{color:#18a058;font-size:13px}.issue-text[data-v-5f659620]{color:#d03050;font-size:13px}.readme-dialog-desc[data-v-5f659620]{color:#555;margin-bottom:16px;font-size:14px}.readme-checkbox[data-v-5f659620]{align-items:flex-start;margin-bottom:12px;display:flex}.readme-checkbox-content[data-v-5f659620]{flex-direction:column;gap:2px;display:flex}.readme-checkbox-title[data-v-5f659620]{font-size:14px;font-weight:500}.readme-checkbox-desc[data-v-5f659620]{color:#999;font-size:12px}.page-header[data-v-97d38fe1]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.page-header h2[data-v-97d38fe1]{font-size:20px;font-weight:600}.fade-enter-active[data-v-97d38fe1],.fade-leave-active[data-v-97d38fe1]{transition:opacity .2s}.fade-enter-from[data-v-97d38fe1],.fade-leave-to[data-v-97d38fe1]{opacity:0}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}