sillyspec 3.8.5 → 3.8.6

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 (163) hide show
  1. package/README.md +0 -6
  2. package/docs/.vitepress/config.mts +45 -0
  3. package/docs/.vitepress/dist/404.html +25 -0
  4. package/docs/.vitepress/dist/assets/app.YytxICdd.js +1 -0
  5. package/docs/.vitepress/dist/assets/chunks/framework.Czhw_PXq.js +19 -0
  6. package/docs/.vitepress/dist/assets/chunks/theme.DusTRZQk.js +1 -0
  7. package/docs/.vitepress/dist/assets/index.md.C3VCvtQA.js +1 -0
  8. package/docs/.vitepress/dist/assets/index.md.C3VCvtQA.lean.js +1 -0
  9. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  10. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  11. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  12. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  13. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  14. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  15. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  16. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  17. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  18. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  19. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  20. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  21. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  22. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  23. package/docs/.vitepress/dist/assets/sillyspec_commands.md.CXFFsj08.js +15 -0
  24. package/docs/.vitepress/dist/assets/sillyspec_commands.md.CXFFsj08.lean.js +1 -0
  25. package/docs/.vitepress/dist/assets/sillyspec_dashboard.md.BuPXHqjX.js +4 -0
  26. package/docs/.vitepress/dist/assets/sillyspec_dashboard.md.BuPXHqjX.lean.js +1 -0
  27. package/docs/.vitepress/dist/assets/sillyspec_file-io.md.Cz3x7llx.js +1 -0
  28. package/docs/.vitepress/dist/assets/sillyspec_file-io.md.Cz3x7llx.lean.js +1 -0
  29. package/docs/.vitepress/dist/assets/sillyspec_getting-started.md.ClcvV8k3.js +4 -0
  30. package/docs/.vitepress/dist/assets/sillyspec_getting-started.md.ClcvV8k3.lean.js +1 -0
  31. package/docs/.vitepress/dist/assets/sillyspec_install.md.CKuR2tiT.js +5 -0
  32. package/docs/.vitepress/dist/assets/sillyspec_install.md.CKuR2tiT.lean.js +1 -0
  33. package/docs/.vitepress/dist/assets/sillyspec_lifecycle.md.DY293cR1.js +28 -0
  34. package/docs/.vitepress/dist/assets/sillyspec_lifecycle.md.DY293cR1.lean.js +1 -0
  35. package/docs/.vitepress/dist/assets/sillyspec_structure.md.sVYS4zPs.js +30 -0
  36. package/docs/.vitepress/dist/assets/sillyspec_structure.md.sVYS4zPs.lean.js +1 -0
  37. package/docs/.vitepress/dist/assets/style.DFTx90Kk.css +1 -0
  38. package/docs/.vitepress/dist/hashmap.json +1 -0
  39. package/docs/.vitepress/dist/index.html +28 -0
  40. package/docs/.vitepress/dist/sillyspec/commands.html +42 -0
  41. package/docs/.vitepress/dist/sillyspec/dashboard.html +31 -0
  42. package/docs/.vitepress/dist/sillyspec/file-io.html +28 -0
  43. package/docs/.vitepress/dist/sillyspec/getting-started.html +31 -0
  44. package/docs/.vitepress/dist/sillyspec/install.html +32 -0
  45. package/docs/.vitepress/dist/sillyspec/lifecycle.html +55 -0
  46. package/docs/.vitepress/dist/sillyspec/structure.html +57 -0
  47. package/docs/.vitepress/dist/vp-icons.css +1 -0
  48. package/docs/index.md +34 -0
  49. package/docs/sillyspec/commands.md +218 -0
  50. package/docs/sillyspec/dashboard.md +51 -0
  51. package/docs/sillyspec/file-io.md +34 -0
  52. package/docs/sillyspec/getting-started.md +61 -0
  53. package/docs/sillyspec/install.md +51 -0
  54. package/docs/sillyspec/lifecycle.md +146 -0
  55. package/docs/sillyspec/structure.md +62 -0
  56. package/package.json +11 -9
  57. package/packages/dashboard/dist/assets/index-Bh-GPjKY.css +1 -0
  58. package/packages/dashboard/dist/assets/index-CrCn5Gg6.js +17 -0
  59. package/packages/dashboard/dist/index.html +2 -2
  60. package/packages/dashboard/package-lock.json +0 -220
  61. package/packages/dashboard/package.json +5 -8
  62. package/packages/dashboard/server/index.js +106 -255
  63. package/packages/dashboard/server/parser.js +29 -333
  64. package/packages/dashboard/server/watcher.js +131 -203
  65. package/packages/dashboard/src/App.vue +10 -181
  66. package/packages/dashboard/src/components/ActionBar.vue +42 -26
  67. package/packages/dashboard/src/components/CommandPalette.vue +65 -40
  68. package/packages/dashboard/src/components/DetailPanel.vue +53 -68
  69. package/packages/dashboard/src/components/LogStream.vue +33 -13
  70. package/packages/dashboard/src/components/PipelineStage.vue +8 -8
  71. package/packages/dashboard/src/components/PipelineView.vue +45 -80
  72. package/packages/dashboard/src/components/ProjectList.vue +45 -103
  73. package/packages/dashboard/src/components/StageBadge.vue +13 -13
  74. package/packages/dashboard/src/components/StepCard.vue +15 -15
  75. package/packages/dashboard/src/composables/useDashboard.js +6 -20
  76. package/packages/dashboard/src/composables/useKeyboard.js +4 -6
  77. package/packages/dashboard/src/main.js +1 -4
  78. package/packages/dashboard/src/style.css +17 -17
  79. package/src/index.js +12 -123
  80. package/src/init.js +227 -86
  81. package/src/setup.js +9 -1
  82. package/templates/archive.md +121 -0
  83. package/templates/brainstorm.md +240 -0
  84. package/{.claude/skills/sillyspec-commit/SKILL.md → templates/commit.md} +47 -29
  85. package/templates/continue.md +32 -0
  86. package/templates/execute.md +314 -0
  87. package/templates/explore.md +60 -0
  88. package/templates/export.md +21 -0
  89. package/templates/init.md +61 -0
  90. package/templates/plan.md +157 -0
  91. package/templates/quick.md +135 -0
  92. package/templates/scan-quick.md +49 -0
  93. package/templates/scan.md +172 -0
  94. package/templates/skills/playwright-e2e/SKILL.md +340 -0
  95. package/templates/status.md +75 -0
  96. package/templates/verify.md +253 -0
  97. package/templates/workspace-sync.md +99 -0
  98. package/templates/workspace.md +70 -0
  99. package/.claude/skills/sillyspec-archive/SKILL.md +0 -17
  100. package/.claude/skills/sillyspec-auto/SKILL.md +0 -77
  101. package/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -17
  102. package/.claude/skills/sillyspec-continue/SKILL.md +0 -44
  103. package/.claude/skills/sillyspec-doctor/SKILL.md +0 -22
  104. package/.claude/skills/sillyspec-execute/SKILL.md +0 -17
  105. package/.claude/skills/sillyspec-explore/SKILL.md +0 -96
  106. package/.claude/skills/sillyspec-export/SKILL.md +0 -53
  107. package/.claude/skills/sillyspec-init/SKILL.md +0 -170
  108. package/.claude/skills/sillyspec-plan/SKILL.md +0 -52
  109. package/.claude/skills/sillyspec-propose/SKILL.md +0 -17
  110. package/.claude/skills/sillyspec-quick/SKILL.md +0 -17
  111. package/.claude/skills/sillyspec-resume/SKILL.md +0 -111
  112. package/.claude/skills/sillyspec-scan/SKILL.md +0 -17
  113. package/.claude/skills/sillyspec-state/SKILL.md +0 -54
  114. package/.claude/skills/sillyspec-status/SKILL.md +0 -17
  115. package/.claude/skills/sillyspec-verify/SKILL.md +0 -17
  116. package/.claude/skills/sillyspec-workspace/SKILL.md +0 -149
  117. package/.sillyspec/changes/archive/2026-04-08-derive-state/design.md +0 -97
  118. package/.sillyspec/changes/archive/2026-04-08-derive-state/plan.md +0 -51
  119. package/.sillyspec/changes/archive/2026-04-08-derive-state/proposal.md +0 -29
  120. package/.sillyspec/changes/archive/2026-04-08-derive-state/requirements.md +0 -34
  121. package/.sillyspec/changes/archive/2026-04-08-derive-state/tasks.md +0 -13
  122. package/.sillyspec/changes/archive/2026-04-08-derive-state/verify-result.md +0 -43
  123. package/.sillyspec/changes/auto-mode/design.md +0 -50
  124. package/.sillyspec/changes/auto-mode/proposal.md +0 -19
  125. package/.sillyspec/changes/auto-mode/requirements.md +0 -21
  126. package/.sillyspec/changes/auto-mode/tasks.md +0 -7
  127. package/.sillyspec/changes/brainstorm-archive/2026-04-05-unified-docs-design.md +0 -199
  128. package/.sillyspec/changes/dashboard/design.md.braindraft +0 -206
  129. package/.sillyspec/changes/run-command-design/design.md +0 -1230
  130. package/.sillyspec/changes/unified-docs-design/design.md +0 -199
  131. package/.sillyspec/docs/sillyspec/scan/.gitkeep +0 -0
  132. package/.sillyspec/knowledge/INDEX.md +0 -8
  133. package/.sillyspec/knowledge/uncategorized.md +0 -3
  134. package/.sillyspec/projects/sillyspec.yaml +0 -3
  135. package/packages/dashboard/dist/assets/index-D1EVTLmc.js +0 -7446
  136. package/packages/dashboard/dist/assets/index-DGe8CqeP.css +0 -1
  137. package/packages/dashboard/public/logo.jpg +0 -0
  138. package/packages/dashboard/src/components/DocPreview.vue +0 -160
  139. package/packages/dashboard/src/components/DocTree.vue +0 -58
  140. package/packages/dashboard/src/components/ProjectOverview.vue +0 -178
  141. package/packages/dashboard/src/components/detail/DocsDetail.vue +0 -48
  142. package/packages/dashboard/src/components/detail/GitDetail.vue +0 -61
  143. package/packages/dashboard/src/components/detail/TechDetail.vue +0 -43
  144. package/src/derive.js +0 -147
  145. package/src/migrate.js +0 -117
  146. package/src/progress.js +0 -495
  147. package/src/run.js +0 -640
  148. package/src/stages/archive.js +0 -54
  149. package/src/stages/brainstorm.js +0 -239
  150. package/src/stages/doctor.js +0 -312
  151. package/src/stages/execute.js +0 -259
  152. package/src/stages/index.js +0 -35
  153. package/src/stages/plan.js +0 -259
  154. package/src/stages/propose.js +0 -115
  155. package/src/stages/quick.js +0 -64
  156. package/src/stages/scan.js +0 -141
  157. package/src/stages/status.js +0 -65
  158. package/src/stages/verify.js +0 -135
  159. /package/.sillyspec/{changes/brainstorm-archive → specs}/2026-04-05-dashboard-design.md +0 -0
  160. /package/{packages/dashboard → docs/.vitepress}/dist/favicon.jpg +0 -0
  161. /package/{logo.jpg → docs/.vitepress/dist/logo.jpg} +0 -0
  162. /package/{packages/dashboard → docs}/public/favicon.jpg +0 -0
  163. /package/{packages/dashboard/dist → docs/public}/logo.jpg +0 -0
@@ -1,73 +1,53 @@
1
1
  <template>
2
- <div class="flex flex-col h-full" style="background: #F5F5F7;">
3
- <!-- Header with Tabs -->
4
- <div class="px-6 pt-4 pb-0" style="border-bottom: 1px solid #F0F0F3;">
5
- <div class="flex items-center gap-6">
6
- <h2 class="text-[11px] font-semibold uppercase tracking-[0.2em] font-[JetBrains_Mono,monospace]" style="color: #6B7280;">
7
- {{ project?.name || '项目' }}
8
- </h2>
9
- <n-tabs :value="activeTab" type="segment" size="small" @update:value="$emit('switch-tab', $event)" style="max-width: 200px;">
10
- <n-tab name="pipeline">流水线</n-tab>
11
- <n-tab name="docs">文档</n-tab>
12
- </n-tabs>
13
- </div>
2
+ <div class="flex flex-col h-full" style="background: #0E0E10;">
3
+ <!-- Header -->
4
+ <div class="px-6 pt-6 pb-4" style="border-bottom: 1px solid #1F1F22;">
5
+ <h2 class="text-[11px] font-semibold uppercase tracking-[0.2em] font-[JetBrains_Mono,monospace]" style="color: #525252;">
6
+ Pipeline
7
+ </h2>
8
+ <p v-if="project" class="text-[12px] mt-1.5 font-[JetBrains_Mono,monospace]" style="color: #8B8B8E;">
9
+ {{ project.name }} <span style="color: #2A2A2D;">/</span> <span style="color: #FBBF24;">{{ currentStage }}</span>
10
+ </p>
14
11
  </div>
15
12
 
16
- <!-- Pipeline Tab -->
17
- <div v-if="activeTab === 'pipeline'" class="flex flex-col flex-1 overflow-hidden">
18
- <div v-if="project && currentStage" class="px-6 pt-4 pb-2">
19
- <p class="text-[12px] font-[JetBrains_Mono,monospace]" style="color: #636366;">
20
- <span style="color: #D97706;">{{ currentStage }}</span>
21
- </p>
22
- </div>
23
-
13
+ <!-- Stages -->
14
+ <div class="flex-1 overflow-y-auto px-6 py-5">
24
15
  <!-- Empty state -->
25
- <n-empty v-if="!project || !project.state" description="选择一个项目查看流水线" style="margin: auto;" />
26
-
27
- <!-- Stages -->
28
- <div v-else class="flex-1 overflow-y-auto px-6 pb-5 space-y-5">
29
- <PipelineStage name="brainstorm" title="头脑风暴" :steps="getStageSteps('brainstorm')" :status="getStageStatus('brainstorm')" :is-active="currentStage === 'brainstorm'" :active-step="activeStep" @select-step="handleSelectStep" />
30
- <div v-if="hasStage('plan')" class="flex items-center pl-[3px]"><div class="w-px h-4" style="background: #F0F0F3;" /></div>
31
- <PipelineStage name="plan" title="规划" :steps="getStageSteps('plan')" :status="getStageStatus('plan')" :is-active="currentStage === 'plan'" :active-step="activeStep" @select-step="handleSelectStep" />
32
- <div v-if="hasStage('execute')" class="flex items-center pl-[3px]"><div class="w-px h-4" style="background: #F0F0F3;" /></div>
33
- <PipelineStage name="execute" title="执行" :steps="getStageSteps('execute')" :status="getStageStatus('execute')" :is-active="currentStage === 'execute'" :active-step="activeStep" @select-step="handleSelectStep" />
34
- <div v-if="hasStage('verify')" class="flex items-center pl-[3px]"><div class="w-px h-4" style="background: #F0F0F3;" /></div>
35
- <PipelineStage name="verify" title="验证" :steps="getStageSteps('verify')" :status="getStageStatus('verify')" :is-active="currentStage === 'verify'" :active-step="activeStep" @select-step="handleSelectStep" />
16
+ <div v-if="!project || !project.state" class="flex items-center justify-center h-full">
17
+ <div class="text-center">
18
+ <div class="w-14 h-14 mx-auto mb-4 rounded-md flex items-center justify-center" style="border: 1px dashed #2A2A2D; transform: rotate(45deg);">
19
+ <svg class="w-5 h-5" style="color: #525252; transform: rotate(-45deg);" fill="none" stroke="currentColor" viewBox="0 0 24 24">
20
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
21
+ </svg>
22
+ </div>
23
+ <p class="text-[12px] font-[JetBrains_Mono,monospace]" style="color: #525252;">Select a project</p>
24
+ </div>
36
25
  </div>
37
26
 
38
- <!-- Activity Log -->
39
- <div v-if="project?.state?.progress" style="border-top: 1px solid #F0F0F3; background: rgba(0,0,0,0.03);">
40
- <div class="px-6 py-2.5 flex items-center justify-between">
41
- <div class="text-[9px] font-semibold uppercase tracking-[0.25em] font-[JetBrains_Mono,monospace]" style="color: #6B7280;">活动日志</div>
42
- <div class="text-[10px] font-mono-log" style="color: #D1D1D6;">{{ activityLogs.length }}</div>
43
- </div>
44
- <div class="px-6 pb-3 max-h-32 overflow-y-auto">
45
- <n-timeline size="small">
46
- <n-timeline-item
47
- v-for="(log, i) in activityLogs"
48
- :key="i"
49
- :type="log.status === 'completed' ? 'success' : 'warning'"
50
- >
51
- <template #default>
52
- <span class="text-[11px]" style="color: #636366;">{{ log.description }}</span>
53
- </template>
54
- <template #time>
55
- <span class="text-[10px] font-mono-log" style="color: #D1D1D6;">{{ log.time }}</span>
56
- </template>
57
- </n-timeline-item>
58
- </n-timeline>
59
- <div v-if="activityLogs.length === 0" class="text-[10px] py-1" style="color: #D1D1D6;">暂无活动记录</div>
60
- </div>
27
+ <div v-else class="space-y-5">
28
+ <PipelineStage name="brainstorm" title="BRAINSTORM" :steps="getStageSteps('brainstorm')" :status="getStageStatus('brainstorm')" :is-active="currentStage === 'brainstorm'" :active-step="activeStep" @select-step="handleSelectStep" />
29
+ <div v-if="hasStage('plan')" class="flex items-center pl-[3px]"><div class="w-px h-4" style="background: #1F1F22;" /></div>
30
+ <PipelineStage name="plan" title="PLAN" :steps="getStageSteps('plan')" :status="getStageStatus('plan')" :is-active="currentStage === 'plan'" :active-step="activeStep" @select-step="handleSelectStep" />
31
+ <div v-if="hasStage('execute')" class="flex items-center pl-[3px]"><div class="w-px h-4" style="background: #1F1F22;" /></div>
32
+ <PipelineStage name="execute" title="EXECUTE" :steps="getStageSteps('execute')" :status="getStageStatus('execute')" :is-active="currentStage === 'execute'" :active-step="activeStep" @select-step="handleSelectStep" />
33
+ <div v-if="hasStage('verify')" class="flex items-center pl-[3px]"><div class="w-px h-4" style="background: #1F1F22;" /></div>
34
+ <PipelineStage name="verify" title="VERIFY" :steps="getStageSteps('verify')" :status="getStageStatus('verify')" :is-active="currentStage === 'verify'" :active-step="activeStep" @select-step="handleSelectStep" />
61
35
  </div>
62
36
  </div>
63
37
 
64
- <!-- Docs Tab -->
65
- <div v-if="activeTab === 'docs'" class="flex-1 flex overflow-hidden">
66
- <div class="w-[200px] flex-shrink-0 overflow-hidden" style="border-right: 1px solid #F0F0F3;">
67
- <DocTree :groups="docs.groups" :selected-file="selectedDocFile" @select-file="$emit('select-doc-file', $event)" />
38
+ <!-- Activity Log -->
39
+ <div v-if="project?.state?.progress" style="border-top: 1px solid #1F1F22; background: rgba(10,10,11,0.6);">
40
+ <div class="px-6 py-2.5 flex items-center justify-between">
41
+ <div class="text-[9px] font-semibold uppercase tracking-[0.25em] font-[JetBrains_Mono,monospace]" style="color: #525252;">Activity</div>
42
+ <div class="text-[10px] font-mono-log" style="color: #3A3A3D;">{{ activityLogs.length }}</div>
68
43
  </div>
69
- <div class="flex-1 overflow-hidden">
70
- <DocPreview :content="docContent" :loading="docLoading" />
44
+ <div class="px-6 pb-3 space-y-0.5 max-h-32 overflow-y-auto">
45
+ <div v-for="(log, i) in activityLogs" :key="i" class="flex items-start gap-2.5 text-[11px] py-0.5">
46
+ <span class="w-10 font-mono-log flex-shrink-0" style="color: #3A3A3D;">{{ log.time }}</span>
47
+ <span :style="{ color: log.status === 'completed' ? '#34D399' : '#FBBF24' }">›</span>
48
+ <span style="color: #8B8B8E;">{{ log.description }}</span>
49
+ </div>
50
+ <div v-if="activityLogs.length === 0" class="text-[10px] py-1" style="color: #3A3A3D;">No activity</div>
71
51
  </div>
72
52
  </div>
73
53
  </div>
@@ -76,39 +56,24 @@
76
56
  <script setup>
77
57
  import { computed } from 'vue'
78
58
  import PipelineStage from './PipelineStage.vue'
79
- import DocTree from './DocTree.vue'
80
- import DocPreview from './DocPreview.vue'
81
59
 
82
60
  const props = defineProps({
83
61
  project: { type: Object, default: null },
84
- activeStep: { type: Object, default: null },
85
- activeTab: { type: String, default: 'pipeline' },
86
- docs: { type: Object, default: () => ({ groups: [] }) },
87
- selectedDocFile: { type: Object, default: null },
88
- docContent: { type: String, default: '' },
89
- docLoading: { type: Boolean, default: false }
62
+ activeStep: { type: Object, default: null }
90
63
  })
91
64
 
92
- const emit = defineEmits(['select-step', 'switch-tab', 'select-doc-file'])
65
+ const emit = defineEmits(['select-step'])
93
66
 
94
- const currentStage = computed(() => props.project?.state?.currentStage || '')
67
+ const currentStage = computed(() => props.project?.state?.currentStage || 'unknown')
95
68
  const progress = computed(() => props.project?.state?.progress || {})
96
69
  const stages = computed(() => progress.value.stages || {})
97
70
 
98
- const stageNameMap = {
99
- brainstorm: '头脑风暴',
100
- plan: '规划',
101
- execute: '执行',
102
- verify: '验证'
103
- }
104
-
105
71
  const activityLogs = computed(() => {
106
72
  if (!props.project?.state) return []
107
73
  const logs = []
108
74
  for (const [name, data] of Object.entries(progress.value.stages || {})) {
109
- const label = stageNameMap[name] || name
110
- if (data.status === 'completed') logs.push({ time: data.completedAt ? formatTime(data.completedAt) : '--:--', status: 'completed', description: `${label} 已完成` })
111
- else if (data.status === 'in-progress') logs.push({ time: '--:--', status: 'in-progress', description: `${label} 运行中` })
75
+ if (data.status === 'completed') logs.push({ time: data.completedAt ? formatTime(data.completedAt) : '--:--', status: 'completed', description: `${name} completed` })
76
+ else if (data.status === 'in-progress') logs.push({ time: '--:--', status: 'in-progress', description: `${name} running` })
112
77
  }
113
78
  return logs.reverse()
114
79
  })
@@ -3,109 +3,84 @@
3
3
  <!-- Header -->
4
4
  <div class="relative z-10 px-5 pt-5 pb-4">
5
5
  <div class="flex items-center gap-3">
6
- <div class="w-8 h-8 rounded-md flex items-center justify-center" style="background: linear-gradient(135deg, #D97706 0%, #F59E0B 100%); clip-path: polygon(0 0, 100% 0, 85% 100%, 15% 100%);">
6
+ <div class="w-8 h-8 rounded-md flex items-center justify-center" style="background: linear-gradient(135deg, #FBBF24 0%, #F59E0B 100%); clip-path: polygon(0 0, 100% 0, 85% 100%, 15% 100%);">
7
7
  <span class="text-[10px] font-bold text-black font-[JetBrains_Mono,monospace]">S</span>
8
8
  </div>
9
- <img src="/logo.jpg" style="width:28px;height:28px;border-radius:6px;margin-right:8px;">
10
- <div class="flex-1">
11
- <h1 class="text-[13px] font-semibold tracking-tight font-[JetBrains_Mono,monospace]" style="color: #1C1C1E;">
9
+ <div>
10
+ <h1 class="text-[13px] font-semibold tracking-tight font-[JetBrains_Mono,monospace]" style="color: #E4E4E7;">
12
11
  SillySpec
13
12
  </h1>
14
- <p class="text-[10px] tracking-widest uppercase" style="color: #6B7280;">控制台</p>
13
+ <p class="text-[10px] tracking-widest uppercase" style="color: #525252;">Dashboard</p>
15
14
  </div>
16
- <!-- Scan paths gear button -->
17
- <n-button quaternary size="tiny" @click="showScanPanel = !showScanPanel" :type="showScanPanel ? 'primary' : 'default'">
18
- <template #icon>
19
- <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
20
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
21
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
22
- </svg>
23
- </template>
24
- </n-button>
25
15
  </div>
26
-
27
- <!-- Scan paths panel (inline) -->
28
- <Transition name="slide">
29
- <div v-if="showScanPanel" class="mt-3 rounded-md p-3" style="background: #FFFFFF; border: 1px solid #F0F0F3;">
30
- <div class="text-[10px] font-semibold uppercase tracking-[0.15em] mb-2 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">扫描路径</div>
31
-
32
- <div v-if="scanPaths.length === 0" class="text-[10px] py-1" style="color: #D1D1D6;">暂无自定义路径</div>
33
- <div v-else class="space-y-1 mb-2">
34
- <div v-for="(p, i) in scanPaths" :key="i" class="flex items-center gap-2 text-[10px] group">
35
- <span class="flex-1 truncate font-mono-log" style="color: #636366;">{{ p }}</span>
36
- <n-button quaternary size="tiny" type="error" @click="removePath(p)">✕</n-button>
37
- </div>
38
- </div>
39
-
40
- <!-- Add path -->
41
- <div v-if="showAddInput" class="flex items-center gap-2">
42
- <n-input v-model:value="newPath" size="tiny" placeholder="输入目录路径..." @keydown.enter="addPath" @keydown.escape="showAddInput = false" ref="pathInput" />
43
- <n-button size="tiny" type="primary" @click="addPath">添加</n-button>
44
- </div>
45
- <n-button v-else size="tiny" dashed @click="showAddInput = true">+ 添加目录</n-button>
46
- </div>
47
- </Transition>
48
16
  </div>
49
17
 
50
18
  <!-- Divider -->
51
- <div class="mx-4 h-px" style="background: linear-gradient(90deg, transparent, #E5E5EA, transparent);"></div>
19
+ <div class="mx-4 h-px" style="background: linear-gradient(90deg, transparent, #2A2A2D, transparent);"></div>
52
20
 
53
21
  <!-- Projects List -->
54
22
  <div class="flex-1 overflow-y-auto py-3 relative z-10">
55
23
  <!-- Loading skeleton -->
56
24
  <div v-if="isLoading" class="px-4 space-y-2">
57
- <n-card v-for="i in 4" :key="i" size="small" :bordered="false">
58
- <n-skeleton text :width="80" size="small" />
59
- <n-skeleton text :width="140" size="small" style="margin-top: 6px;" />
60
- </n-card>
61
- <p class="text-center text-[10px] mt-4 font-[JetBrains_Mono,monospace]" style="color: #6B7280;">
62
- 正在扫描项目...
25
+ <div v-for="i in 4" :key="i" class="rounded-lg p-3" style="background: #141416;">
26
+ <div class="h-3 rounded w-20 skeleton-shimmer mb-2"></div>
27
+ <div class="h-2 rounded w-32 skeleton-shimmer"></div>
28
+ </div>
29
+ <p class="text-center text-[10px] mt-4 font-[JetBrains_Mono,monospace]" style="color: #525252;">
30
+ scanning projects...
63
31
  </p>
64
32
  </div>
65
33
 
66
34
  <!-- Empty state -->
67
- <n-empty v-else-if="projects.length === 0" description="未发现 SillySpec 项目" style="padding: 48px 0;" />
35
+ <div v-else-if="projects.length === 0" class="px-4 py-12 text-center">
36
+ <div class="w-10 h-10 mx-auto mb-3 rounded-full flex items-center justify-center" style="border: 1px dashed #2A2A2D;">
37
+ <svg class="w-4 h-4" style="color: #525252;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
38
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
39
+ </svg>
40
+ </div>
41
+ <p class="text-[11px]" style="color: #8B8B8E;">No projects found</p>
42
+ <p class="text-[10px] mt-1" style="color: #525252;">Looking for .sillyspec dirs</p>
43
+ </div>
68
44
 
69
45
  <!-- Projects -->
70
46
  <div v-else class="px-3 space-y-0.5">
71
47
  <div
72
48
  v-for="project in projects"
73
- :key="project.path"
74
- :class="['relative rounded-md cursor-pointer transition-all duration-150 overflow-hidden group']"
49
+ :key="project.name"
50
+ :class="[
51
+ 'relative rounded-md cursor-pointer transition-all duration-150 overflow-hidden group',
52
+ ]"
75
53
  :style="{
76
- background: isActive(project) ? 'rgba(217,119,6,0.06)' : 'transparent',
77
- borderLeft: isActive(project) ? '2px solid #D97706' : '2px solid transparent',
54
+ background: isActive(project) ? 'rgba(251,191,36,0.06)' : 'transparent',
55
+ borderLeft: isActive(project) ? '2px solid #FBBF24' : '2px solid transparent',
78
56
  }"
79
- @mouseenter="$event.currentTarget.style.background = isActive(project) ? 'rgba(217,119,6,0.08)' : 'rgba(255,255,255,0.02)'"
80
- @mouseleave="$event.currentTarget.style.background = isActive(project) ? 'rgba(217,119,6,0.06)' : 'transparent'"
57
+ @mouseenter="$event.currentTarget.style.background = isActive(project) ? 'rgba(251,191,36,0.08)' : 'rgba(255,255,255,0.02)'"
58
+ @mouseleave="$event.currentTarget.style.background = isActive(project) ? 'rgba(251,191,36,0.06)' : 'transparent'"
81
59
  @click="$emit('select', project)"
82
60
  >
83
61
  <div class="px-3 py-2.5">
84
62
  <div class="flex items-center justify-between gap-2">
85
63
  <div class="flex-1 min-w-0">
86
64
  <h3
87
- class="text-[12px] font-medium truncate transition-colors duration-150 font-[JetBrains_Mono,monospace]"
88
- :style="{ color: isActive(project) ? '#D97706' : '#1C1C1E' }"
65
+ :class="['text-[12px] font-medium truncate transition-colors duration-150 font-[JetBrains_Mono,monospace]']"
66
+ :style="{ color: isActive(project) ? '#FBBF24' : '#E4E4E7' }"
89
67
  >
90
68
  {{ project.name }}
91
69
  </h3>
92
- <p class="text-[10px] mt-0.5 truncate font-mono-log" style="color: #6B7280;">
70
+ <p class="text-[10px] mt-0.5 truncate font-mono-log" style="color: #525252;">
93
71
  {{ project.path }}
94
72
  </p>
95
73
  </div>
96
- <n-tag
74
+ <StageBadge
97
75
  v-if="project.state?.currentStage"
98
- :type="statusTagType(getProjectStatus(project))"
99
- size="small"
100
- :bordered="false"
101
- round
102
- >
103
- {{ stageLabel(project) }}
104
- </n-tag>
76
+ :status="getProjectStatus(project)"
77
+ :label="stageLabel(project)"
78
+ size="sm"
79
+ />
105
80
  </div>
106
81
 
107
82
  <!-- Progress -->
108
- <div v-if="project.state?.progress" class="mt-2 h-[2px] rounded-full overflow-hidden" style="background: #FFFFFF;">
83
+ <div v-if="project.state?.progress" class="mt-2 h-[2px] rounded-full overflow-hidden" style="background: #1C1C1F;">
109
84
  <div
110
85
  class="h-full rounded-full transition-all duration-500 progress-gradient"
111
86
  :style="{ width: getProjectProgress(project) + '%' }"
@@ -117,43 +92,29 @@
117
92
  </div>
118
93
 
119
94
  <!-- Footer -->
120
- <div class="relative z-10 px-4 py-2.5" style="border-top: 1px solid #F0F0F3;">
95
+ <div class="relative z-10 px-4 py-2.5" style="border-top: 1px solid #1F1F22;">
121
96
  <div class="flex items-center justify-between">
122
- <span class="text-[10px] font-[JetBrains_Mono,monospace]" style="color: #6B7280;">{{ projects.length }} 个项目</span>
123
- <kbd class="text-[9px] px-1.5 py-0.5 rounded font-mono-log" style="color: #6B7280; background: #FFFFFF; border: 1px solid #E5E5EA;">⌘K</kbd>
97
+ <span class="text-[10px] font-[JetBrains_Mono,monospace]" style="color: #525252;">{{ projects.length }} proj</span>
98
+ <kbd class="text-[9px] px-1.5 py-0.5 rounded font-mono-log" style="color: #525252; background: #141416; border: 1px solid #2A2A2D;">⌘K</kbd>
124
99
  </div>
125
100
  </div>
126
101
  </div>
127
102
  </template>
128
103
 
129
104
  <script setup>
130
- import { ref, nextTick, watch } from 'vue'
105
+ import { computed } from 'vue'
106
+ import StageBadge from './StageBadge.vue'
131
107
 
132
108
  const props = defineProps({
133
109
  projects: { type: Array, default: () => [] },
134
110
  activeProject: { type: Object, default: null },
135
- isLoading: { type: Boolean, default: false },
136
- scanPaths: { type: Array, default: () => [] }
111
+ isLoading: { type: Boolean, default: false }
137
112
  })
138
113
 
139
- const emit = defineEmits(['select', 'scan:add-path', 'scan:remove-path'])
140
-
141
- const showScanPanel = ref(false)
142
- const showAddInput = ref(false)
143
- const newPath = ref('')
144
- const pathInput = ref(null)
145
-
146
- watch(showAddInput, (v) => {
147
- if (v) nextTick(() => { pathInput.value?.focus() })
148
- })
114
+ const emit = defineEmits(['select'])
149
115
 
150
116
  function isActive(project) {
151
- return props.activeProject?.path === project.path
152
- }
153
-
154
- function statusTagType(status) {
155
- const map = { 'in-progress': 'warning', 'completed': 'success', 'failed': 'error', 'blocked': 'warning' }
156
- return map[status] || 'default'
117
+ return props.activeProject?.name === project.name
157
118
  }
158
119
 
159
120
  function getProjectStatus(project) {
@@ -188,23 +149,4 @@ function getProjectProgress(project) {
188
149
  }
189
150
  return total === 0 ? 0 : Math.round((done / total) * 100)
190
151
  }
191
-
192
- function addPath() {
193
- const p = newPath.value.trim()
194
- if (p) {
195
- emit('scan:add-path', p)
196
- newPath.value = ''
197
- showAddInput.value = false
198
- }
199
- }
200
-
201
- function removePath(p) {
202
- emit('scan:remove-path', p)
203
- }
204
152
  </script>
205
-
206
- <style scoped>
207
- .slide-enter-active, .slide-leave-active { transition: all 200ms ease; }
208
- .slide-enter-from, .slide-leave-to { opacity: 0; max-height: 0; overflow: hidden; }
209
- .slide-enter-to, .slide-leave-from { max-height: 300px; }
210
- </style>
@@ -19,19 +19,19 @@ const props = defineProps({
19
19
 
20
20
  const displayLabel = computed(() => {
21
21
  if (props.label) return props.label
22
- const labels = { 'completed': 'done', 'in-progress': 'running', 'blocked': 'blocked', 'failed': 'error' }
23
- return labels[props.status] || ''
22
+ const labels = { 'completed': 'done', 'in-progress': 'running', 'blocked': 'blocked', 'failed': 'error', 'pending': 'idle' }
23
+ return labels[props.status] || 'idle'
24
24
  })
25
25
 
26
26
  const sizeClass = computed(() => props.size === 'sm' ? 'px-1.5 py-0.5' : 'px-2 py-1')
27
27
 
28
28
  const badgeStyle = computed(() => {
29
29
  const styles = {
30
- 'completed': { background: 'rgba(22,163,74,0.1)', color: '#16A34A' },
31
- 'in-progress': { background: 'rgba(251,191,36,0.1)', color: '#D97706' },
32
- 'blocked': { background: 'rgba(251,146,60,0.1)', color: '#EA580C' },
33
- 'failed': { background: 'rgba(239,68,68,0.1)', color: '#DC2626' },
34
- 'pending': { background: 'rgba(82,82,82,0.15)', color: '#6B7280' }
30
+ 'completed': { background: 'rgba(52,211,153,0.1)', color: '#34D399' },
31
+ 'in-progress': { background: 'rgba(251,191,36,0.1)', color: '#FBBF24' },
32
+ 'blocked': { background: 'rgba(251,146,60,0.1)', color: '#FB923C' },
33
+ 'failed': { background: 'rgba(239,68,68,0.1)', color: '#EF4444' },
34
+ 'pending': { background: 'rgba(82,82,82,0.15)', color: '#525252' }
35
35
  }
36
36
  return styles[props.status] || styles.pending
37
37
  })
@@ -42,12 +42,12 @@ const dotClass = computed(() => {
42
42
 
43
43
  const dotStyle = computed(() => {
44
44
  const colors = {
45
- 'completed': '#16A34A',
46
- 'in-progress': '#D97706',
47
- 'blocked': '#EA580C',
48
- 'failed': '#DC2626',
49
- 'pending': '#6B7280'
45
+ 'completed': '#34D399',
46
+ 'in-progress': '#FBBF24',
47
+ 'blocked': '#FB923C',
48
+ 'failed': '#EF4444',
49
+ 'pending': '#525252'
50
50
  }
51
- return { background: colors[props.status] || '#6B7280' }
51
+ return { background: colors[props.status] || '#525252' }
52
52
  })
53
53
  </script>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- :class="['group relative rounded-md cursor-pointer transition-all duration-200']"
3
+ :class="['group relative rounded-md cursor-pointer overflow-hidden transition-all duration-200']"
4
4
  :style="cardStyle"
5
5
  @mouseenter="hovered = true"
6
6
  @mouseleave="hovered = false"
@@ -9,9 +9,9 @@
9
9
  <!-- Left accent bar -->
10
10
  <div class="absolute left-0 top-0 bottom-0 w-[2px]" :style="{ background: barColor }" />
11
11
 
12
- <div class="pl-4 pr-4 py-3">
12
+ <div class="pl-3.5 pr-3 py-2.5">
13
13
  <div class="flex items-center gap-2">
14
- <h3 class="text-[12px] font-medium transition-colors duration-150" :style="{ color: isActive ? '#D97706' : '#1C1C1E', fontFamily: '\'JetBrains Mono\', monospace' }">
14
+ <h3 class="text-[12px] font-medium transition-colors duration-150" :style="{ color: isActive ? '#FBBF24' : '#E4E4E7', fontFamily: '\'JetBrains Mono\', monospace' }">
15
15
  {{ step.title || step.name }}
16
16
  </h3>
17
17
  <StageBadge v-if="step.status" :status="step.status" :label="statusLabel" />
@@ -20,28 +20,28 @@
20
20
  <!-- Hover summary -->
21
21
  <div
22
22
  v-if="step.summary || step.description"
23
- class="transition-all duration-200"
24
- :style="{ maxHeight: hovered ? '80px' : '0', opacity: hovered ? 1 : 0, overflow: 'hidden' }"
23
+ class="overflow-hidden transition-all duration-200"
24
+ :style="{ maxHeight: hovered ? '60px' : '0', opacity: hovered ? 1 : 0 }"
25
25
  >
26
- <p class="mt-1.5 text-[11px] line-clamp-2" style="color: #636366;">
26
+ <p class="mt-1.5 text-[11px] line-clamp-2" style="color: #8B8B8E;">
27
27
  {{ step.summary || step.description }}
28
28
  </p>
29
29
  </div>
30
30
 
31
31
  <!-- Active details -->
32
32
  <div v-if="isActive" class="mt-2 space-y-1">
33
- <p v-if="step.conclusion" class="text-[11px]" style="color: #1C1C1E;">
34
- <span style="color: #D97706; font-weight: 600;">结论:</span> {{ step.conclusion }}
33
+ <p v-if="step.conclusion" class="text-[11px]" style="color: #E4E4E7;">
34
+ <span style="color: #FBBF24; font-weight: 600;">结论:</span> {{ step.conclusion }}
35
35
  </p>
36
- <p v-if="step.decision" class="text-[11px]" style="color: #1C1C1E;">
37
- <span style="color: #D97706; font-weight: 600;">决策:</span> {{ step.decision }}
36
+ <p v-if="step.decision" class="text-[11px]" style="color: #E4E4E7;">
37
+ <span style="color: #FBBF24; font-weight: 600;">决策:</span> {{ step.decision }}
38
38
  </p>
39
- <p v-if="step.userQuery" class="text-[11px] italic" style="color: #636366;">
39
+ <p v-if="step.userQuery" class="text-[11px] italic" style="color: #8B8B8E;">
40
40
  "{{ step.userQuery }}"
41
41
  </p>
42
42
  </div>
43
43
 
44
- <div v-if="step.duration" class="mt-1 text-[10px] font-mono-log" style="color: #6B7280;">
44
+ <div v-if="step.duration" class="mt-1 text-[10px] font-mono-log" style="color: #525252;">
45
45
  {{ step.duration }}
46
46
  </div>
47
47
  </div>
@@ -62,13 +62,13 @@ const emit = defineEmits(['select'])
62
62
  const hovered = ref(false)
63
63
 
64
64
  const barColor = computed(() => {
65
- const colors = { 'completed': '#16A34A', 'in-progress': '#D97706', 'blocked': '#EA580C', 'failed': '#DC2626', 'pending': '#E5E5EA' }
65
+ const colors = { 'completed': '#34D399', 'in-progress': '#FBBF24', 'blocked': '#FB923C', 'failed': '#EF4444', 'pending': '#2A2A2D' }
66
66
  return colors[props.step.status] || colors.pending
67
67
  })
68
68
 
69
69
  const cardStyle = computed(() => ({
70
- background: props.isActive ? 'rgba(217,119,6,0.08)' : (hovered.value ? 'rgba(0,0,0,0.02)' : '#FFFFFF'),
71
- border: `1px solid ${props.isActive ? 'rgba(251,191,36,0.2)' : '#F0F0F3'}`,
70
+ background: props.isActive ? 'rgba(251,191,36,0.04)' : (hovered.value ? 'rgba(255,255,255,0.015)' : '#141416'),
71
+ border: `1px solid ${props.isActive ? 'rgba(251,191,36,0.2)' : '#1F1F22'}`,
72
72
  }))
73
73
 
74
74
  const statusLabel = computed(() => {
@@ -13,12 +13,7 @@ export function useDashboard() {
13
13
  logs: [],
14
14
  isPanelOpen: true,
15
15
  executingProject: null,
16
- isLoading: true,
17
- activeTab: 'pipeline',
18
- docs: { groups: [] },
19
- selectedDocFile: null,
20
- docContent: '',
21
- docLoading: false
16
+ isLoading: true
22
17
  })
23
18
 
24
19
  /**
@@ -26,13 +21,13 @@ export function useDashboard() {
26
21
  * @param {string} name - Project name
27
22
  * @returns {object|null} Project or null
28
23
  */
29
- function getProject(path) {
30
- return state.projects.find(p => p.path === path) || null
24
+ function getProject(name) {
25
+ return state.projects.find(p => p.name === name) || null
31
26
  }
32
27
 
33
28
  /**
34
29
  * Select a project as active
35
- * @param {object|string} project - Project object or path
30
+ * @param {object|string} project - Project object or name
36
31
  */
37
32
  function selectProject(project) {
38
33
  const proj = typeof project === 'string'
@@ -43,8 +38,6 @@ export function useDashboard() {
43
38
  state.activeProject = proj
44
39
  state.activeStep = null
45
40
  state.logs = []
46
- state.selectedDocFile = null
47
- state.docContent = ''
48
41
 
49
42
  // Load initial logs from project state if available
50
43
  if (proj.state?.progress?.currentLogs) {
@@ -122,7 +115,7 @@ export function useDashboard() {
122
115
 
123
116
  // Restore active project if it still exists
124
117
  if (state.activeProject) {
125
- const updated = getProject(state.activeProject.path)
118
+ const updated = getProject(state.activeProject.name)
126
119
  if (updated) {
127
120
  state.activeProject = updated
128
121
  }
@@ -148,7 +141,6 @@ export function useDashboard() {
148
141
 
149
142
  // Computed properties
150
143
  const activeProjectName = computed(() => state.activeProject?.name || null)
151
- const activeProjectPath = computed(() => state.activeProject?.path || null)
152
144
  const activeProjectStage = computed(() => state.activeProject?.state?.currentStage || null)
153
145
  const hasProjects = computed(() => state.projects.length > 0)
154
146
  const activeProjectSteps = computed(() => {
@@ -172,14 +164,8 @@ export function useDashboard() {
172
164
  setExecuting,
173
165
  isExecuting,
174
166
  activeProjectName,
175
- activeProjectPath,
176
167
  activeProjectStage,
177
168
  hasProjects,
178
- activeProjectSteps,
179
- setActiveTab(tab) { state.activeTab = tab },
180
- updateDocs(docs) { state.docs = docs },
181
- selectDocFile(file) { state.selectedDocFile = file },
182
- setDocContent(content) { state.docContent = content },
183
- setDocLoading(loading) { state.docLoading = loading }
169
+ activeProjectSteps
184
170
  }
185
171
  }
@@ -14,17 +14,15 @@ export function useKeyboard(options = {}) {
14
14
  onEnter = null,
15
15
  onArrowUp = null,
16
16
  onArrowDown = null,
17
- disabled: initialDisabled = false
17
+ disabled = false
18
18
  } = options
19
19
 
20
- let isDisabled = initialDisabled
21
-
22
20
  /**
23
21
  * Handle keyboard events
24
22
  * @param {KeyboardEvent} event
25
23
  */
26
24
  function handleKeyDown(event) {
27
- if (isDisabled) return
25
+ if (disabled) return
28
26
 
29
27
  // Ignore if in input field
30
28
  const target = event.target
@@ -89,8 +87,8 @@ export function useKeyboard(options = {}) {
89
87
  })
90
88
 
91
89
  return {
92
- disable: () => { isDisabled = true },
93
- enable: () => { isDisabled = false }
90
+ disable: () => { disabled = true },
91
+ enable: () => { disabled = false }
94
92
  }
95
93
  }
96
94
 
@@ -1,8 +1,5 @@
1
1
  import { createApp } from 'vue'
2
- import naive from 'naive-ui'
3
2
  import App from './App.vue'
4
3
  import './style.css'
5
4
 
6
- const app = createApp(App)
7
- app.use(naive)
8
- app.mount('#app')
5
+ createApp(App).mount('#app')