@templmf/temp-solf-lmf 0.0.135 → 0.0.137

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.
@@ -1,177 +0,0 @@
1
- // src/data/features.js
2
- // 新增能力只需在对应模块的 items 数组里追加一条记录即可
3
- // date 格式: "YYYY-MM"
4
- // isNew: true → 显示「新」标签
5
- // isBeta: true → 显示「Beta」标签
6
-
7
- export const FEATURE_MODULES = [
8
- {
9
- id: 'component',
10
- cls: 'blue',
11
- icon: 'ti-components',
12
- name: '组件渲染',
13
- desc: 'Vue、ElementPlus、HTML 实时渲染',
14
- items: [
15
- {
16
- name: 'Vue SFC',
17
- desc: '支持 <script setup>、<style scoped>,右侧 Artifact 面板实时预览。',
18
- tags: ['Vue 3', 'Composition API'],
19
- date: '2024-09',
20
- },
21
- {
22
- name: 'React JSX',
23
- desc: 'Artifact 面板渲染函数组件,支持 useState、useEffect 等 Hooks。',
24
- tags: ['React 18', 'JSX'],
25
- date: '2024-09',
26
- },
27
- {
28
- name: 'Element Plus',
29
- desc: 'AI 生成组件自动引入 Element Plus,无需手动配置依赖。',
30
- tags: ['Element Plus'],
31
- date: '2025-01',
32
- },
33
- {
34
- name: 'Less / CSS',
35
- desc: '内置 Less 编译器,支持嵌套、变量、mixin,实时编译输出。',
36
- tags: ['Less', 'CSS Variables'],
37
- date: '2024-11',
38
- },
39
- {
40
- name: 'HTML 片段',
41
- desc: '任意 HTML + JS 代码段,iframe 沙箱隔离运行,安全预览。',
42
- tags: ['iframe 沙箱'],
43
- date: '2024-09',
44
- },
45
- ],
46
- },
47
- {
48
- id: 'chart',
49
- cls: 'green',
50
- icon: 'ti-chart-dots',
51
- name: '图表 & 图库',
52
- desc: 'ECharts、G6、Mermaid、D3',
53
- items: [
54
- {
55
- name: 'ECharts',
56
- desc: '折线、柱状、饼图、散点、热力图,支持大数据量渲染。',
57
- tags: ['Apache ECharts 5'],
58
- date: '2024-10',
59
- },
60
- {
61
- name: 'AntV G6',
62
- desc: '关系图、拓扑图、树图,适合节点连线类可视化场景。',
63
- tags: ['@antv/g6'],
64
- date: '2025-03',
65
- isNew: true,
66
- },
67
- {
68
- name: 'Mermaid',
69
- desc: 'Markdown 消息中直接渲染流程图、时序图、甘特图,支持缩放查看。',
70
- tags: ['Mermaid 10', '流程图', '时序图'],
71
- date: '2024-12',
72
- },
73
- {
74
- name: 'D3.js',
75
- desc: '支持自定义数据驱动图形,适合复杂定制化可视化需求。',
76
- tags: ['D3 v7'],
77
- date: '2025-04',
78
- isNew: true,
79
- },
80
- {
81
- name: 'SVG / Canvas',
82
- desc: 'AI 生成原生 SVG 矢量图或 Canvas 绘图代码,直接嵌入渲染。',
83
- tags: ['SVG', 'Canvas 2D'],
84
- date: '2024-09',
85
- },
86
- ],
87
- },
88
- {
89
- id: 'tool',
90
- cls: 'amber',
91
- icon: 'ti-plug',
92
- name: '工具集成',
93
- desc: 'GitLab、文件上传、Skills 插件',
94
- items: [
95
- {
96
- name: 'GitLab',
97
- desc: '读取项目列表、MR、Issue,AI 直接基于仓库内容回答和生成代码。',
98
- tags: ['GitLab API', '工具调用'],
99
- date: '2025-02',
100
- },
101
- {
102
- name: '文件上传',
103
- desc: '支持图片、PDF 上传,AI 读取内容结合对话上下文分析。',
104
- tags: ['图片', 'PDF'],
105
- date: '2024-11',
106
- },
107
- {
108
- name: 'Skills 插件',
109
- desc: '从 Skills 市场安装能力插件,扩展 AI 在特定场景下的执行能力。',
110
- tags: ['官方', '社区'],
111
- date: '2025-05',
112
- isBeta: true,
113
- },
114
- ],
115
- },
116
- {
117
- id: 'markdown',
118
- cls: 'purple',
119
- icon: 'ti-markdown',
120
- name: 'Markdown 增强',
121
- desc: '代码高亮、LaTeX、GFM',
122
- items: [
123
- {
124
- name: '代码高亮',
125
- desc: '基于 Shiki,支持 100+ 语言语法高亮,深浅主题自动切换。',
126
- tags: ['Shiki', '100+ 语言'],
127
- date: '2024-09',
128
- },
129
- {
130
- name: 'LaTeX 公式',
131
- desc: '行内 $ 和块级 $$ 公式均可渲染,适合数学、算法类内容。',
132
- tags: ['KaTeX', '行内 & 块级'],
133
- date: '2024-10',
134
- },
135
- {
136
- name: '表格 / 任务列表',
137
- desc: '完整 GFM 支持,表格、任务列表、引用块、分割线均正确渲染。',
138
- tags: ['GFM'],
139
- date: '2024-09',
140
- },
141
- ],
142
- },
143
- {
144
- id: 'model',
145
- cls: 'coral',
146
- icon: 'ti-brain',
147
- name: '模型 & 对话',
148
- desc: '多模型、流式输出、持久化',
149
- items: [
150
- {
151
- name: '多模型切换',
152
- desc: '对话中随时切换模型,配置即时生效,不打断上下文。',
153
- tags: ['DashScope'],
154
- date: '2025-01',
155
- },
156
- {
157
- name: '流式输出',
158
- desc: 'SSE 实时流式返回,逐字渲染,响应不等待完整结果。',
159
- tags: ['SSE', 'Stream'],
160
- date: '2024-09',
161
- },
162
- {
163
- name: '对话历史持久化',
164
- desc: 'IndexedDB 本地存储,刷新不丢记录,支持跨会话回溯。',
165
- tags: ['IndexedDB'],
166
- date: '2024-12',
167
- },
168
- {
169
- name: '思考链展示',
170
- desc: 'AI 推理过程可折叠展示,方便理解模型决策路径。',
171
- tags: ['CoT'],
172
- date: '2025-03',
173
- isNew: true,
174
- },
175
- ],
176
- },
177
- ]
@@ -1,44 +0,0 @@
1
- import { createRouter, createWebHistory } from 'vue-router'
2
-
3
- const routes = [
4
- { path: '/', component: () => import('../views/HomeView.vue') },
5
- { path: '/chat', component: () => import('../views/ChatView.vue') },
6
- { path: '/chat/share/:uuid', component: () => import('../views/ChatView.vue') },
7
- { path: '/market', component: () => import('../views/MarketView.vue') },
8
- { path: '/skills', component: () => import('../views/SkillsView.vue') },
9
- { path: '/practices', component: () => import('../views/PracticesView.vue') },
10
- // ── 新增 ──
11
- {
12
- path: '/features',
13
- name: 'features',
14
- component: () => import('../views/FeaturesView.vue')
15
- },
16
- { path: '/:pathMatch(.*)*', redirect: '/' },
17
- ]
18
-
19
- const router = createRouter({
20
- history: createWebHistory(),
21
- routes,
22
- scrollBehavior: () => ({ top: 0 }),
23
- })
24
-
25
- /**
26
- * 路由守卫:首页和 public 页面跳过鉴权,其他页面检查登录态
27
- */
28
- router.beforeEach(async (to) => {
29
- if (to.path === '/' || to.meta.public) return true
30
-
31
- const { useAuthStore } = await import('../composables/useAuth.js')
32
- const authStore = useAuthStore()
33
-
34
- const result = await authStore.checkAuth(to.fullPath)
35
- if (result.ok) return true
36
-
37
- if (result.redirectUrl) {
38
- window.location.href = result.redirectUrl
39
- return false
40
- }
41
- return false
42
- })
43
-
44
- export default router
@@ -1,475 +0,0 @@
1
- <template>
2
- <div class="features-page">
3
- <!-- Hero -->
4
- <section class="hero" :class="{ visible: mounted }">
5
- <p class="eyebrow">AI对话能力地图</p>
6
- <h1 class="hero-title">
7
- 我们支持<br />
8
- <em>哪些能力</em>
9
- </h1>
10
- <div class="hero-stats">
11
- <div class="stat">
12
- <span class="stat-n">{{ visibleStats.total }}</span>
13
- <span class="stat-l">支持项</span>
14
- </div>
15
- <div class="stat">
16
- <span class="stat-n">{{ visibleStats.newCount }}</span>
17
- <span class="stat-l">近期新增</span>
18
- </div>
19
- <div class="stat">
20
- <span class="stat-n">{{ visibleStats.modCount }}</span>
21
- <span class="stat-l">功能模块</span>
22
- </div>
23
- </div>
24
- </section>
25
-
26
- <!-- 筛选栏 -->
27
- <div class="filter-bar" :class="{ visible: mounted }" style="animation-delay: 0.08s">
28
- <button
29
- v-for="f in filters"
30
- :key="f.id"
31
- class="fbtn"
32
- :class="{ on: activeFilter === f.id }"
33
- @click="setFilter(f.id)"
34
- >
35
- {{ f.label }}
36
- </button>
37
- </div>
38
-
39
- <!-- 模块列表 -->
40
- <div class="modules" :class="{ visible: mounted }" style="animation-delay: 0.14s">
41
- <div
42
- v-for="mod in visibleModules"
43
- :key="mod.id"
44
- class="module"
45
- :class="mod.cls"
46
- >
47
- <!-- 模块标题行 -->
48
- <div class="mhead" @click="handleModuleClick(mod.id)">
49
- <div class="micon">
50
- <el-icon :size="18"><component :is="iconMap[mod.icon] || 'Grid'" /></el-icon>
51
- </div>
52
- <div class="minfo">
53
- <span class="mname">{{ mod.name }}</span>
54
- <span class="mdesc">{{ mod.desc }}</span>
55
- </div>
56
- <div class="mright">
57
- <span class="mcount">{{ mod.items.length }} 项</span>
58
- <i
59
- class="ti ti-chevron-down mchevron"
60
- :class="{ open: openState[mod.id] }"
61
- />
62
- </div>
63
- </div>
64
-
65
- <!-- 模块内容 -->
66
- <Transition name="slide">
67
- <div v-if="openState[mod.id]" class="mbody">
68
- <div
69
- v-for="(item, idx) in getVisibleItems(mod)"
70
- :key="idx"
71
- class="row"
72
- >
73
- <div class="row-main">
74
- <div class="rname">{{ item.name }}</div>
75
- <div class="rdesc" v-html="item.desc" />
76
- <div class="rtags">
77
- <span v-for="t in item.tags" :key="t" class="tag">{{ t }}</span>
78
- <span v-if="item.isNew" class="tag new">新</span>
79
- <span v-if="item.isBeta" class="tag beta">Beta</span>
80
- </div>
81
- </div>
82
- <div class="rdate">
83
- <span class="rdate-mon">{{ formatDate(item.date).mon }}</span>
84
- <span class="rdate-yr">{{ formatDate(item.date).yr }}</span>
85
- </div>
86
- </div>
87
-
88
- <!-- 展开/收起更多 -->
89
- <div
90
- v-if="mod.items.length > COLLAPSE_AT"
91
- class="more-row"
92
- @click="toggleExpand(mod.id)"
93
- >
94
- <i
95
- class="ti"
96
- :class="expandState[mod.id] ? 'ti-chevron-up' : 'ti-chevron-down'"
97
- />
98
- <span v-if="expandState[mod.id]">收起</span>
99
- <span v-else>还有 {{ mod.items.length - COLLAPSE_AT }} 项,点击展开</span>
100
- </div>
101
- </div>
102
- </Transition>
103
- </div>
104
- </div>
105
- </div>
106
- </template>
107
-
108
- <script setup>
109
- import { ref, computed, onMounted } from 'vue'
110
- import { FEATURE_MODULES } from '../data/features.js'
111
-
112
- const COLLAPSE_AT = 5
113
-
114
- const MONTHS = ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
115
-
116
- function formatDate(d) {
117
- const [y, mo] = d.split('-')
118
- return { mon: MONTHS[parseInt(mo, 10) - 1], yr: y }
119
- }
120
-
121
- // 入场动画
122
- const mounted = ref(false)
123
- onMounted(() => {
124
- requestAnimationFrame(() => {
125
- mounted.value = true
126
- })
127
- })
128
-
129
- // 筛选
130
- const activeFilter = ref('all')
131
- const filters = computed(() => [
132
- { id: 'all', label: '全部模块' },
133
- ...FEATURE_MODULES.map(m => ({ id: m.id, label: m.name })),
134
- ])
135
-
136
- function setFilter(id) {
137
- activeFilter.value = id
138
- if (id === 'all') {
139
- FEATURE_MODULES.forEach(m => { openState.value[m.id] = false })
140
- } else {
141
- openState.value[id] = true
142
- }
143
- }
144
-
145
- const visibleModules = computed(() =>
146
- activeFilter.value === 'all'
147
- ? FEATURE_MODULES
148
- : FEATURE_MODULES.filter(m => m.id === activeFilter.value)
149
- )
150
-
151
- // 顶部统计数字
152
- const visibleStats = computed(() => {
153
- const mods = visibleModules.value
154
- return {
155
- total: mods.reduce((a, m) => a + m.items.length, 0),
156
- newCount: mods.reduce((a, m) => a + m.items.filter(i => i.isNew || i.isBeta).length, 0),
157
- modCount: mods.length,
158
- }
159
- })
160
-
161
- // 模块折叠状态
162
- const openState = ref(
163
- Object.fromEntries(FEATURE_MODULES.map(m => [m.id, false]))
164
- )
165
- const expandState = ref(
166
- Object.fromEntries(FEATURE_MODULES.map(m => [m.id, false]))
167
- )
168
-
169
- function handleModuleClick(id) {
170
- if (activeFilter.value !== id) {
171
- setFilter(id)
172
- } else {
173
- toggleOpen(id)
174
- }
175
- }
176
- function toggleOpen(id) {
177
- openState.value[id] = !openState.value[id]
178
- }
179
- function toggleExpand(id) {
180
- expandState.value[id] = !expandState.value[id]
181
- }
182
-
183
- function getVisibleItems(mod) {
184
- if (mod.items.length <= COLLAPSE_AT || expandState.value[mod.id]) {
185
- return mod.items
186
- }
187
- return mod.items.slice(0, COLLAPSE_AT)
188
- }
189
-
190
- // Element Plus 图标映射(按需替换为项目中实际已注册的图标)
191
- const iconMap = {
192
- 'ti-components': 'Grid',
193
- 'ti-chart-dots': 'TrendCharts',
194
- 'ti-plug': 'Connection',
195
- 'ti-markdown': 'Document',
196
- 'ti-brain': 'Cpu',
197
- }
198
- </script>
199
-
200
- <style scoped>
201
- /* ── 入场动画 ── */
202
- @keyframes fadeUp {
203
- from { opacity: 0; transform: translateY(18px); }
204
- to { opacity: 1; transform: translateY(0); }
205
- }
206
- .hero,
207
- .filter-bar,
208
- .modules {
209
- opacity: 0;
210
- transition: none;
211
- }
212
- .hero.visible,
213
- .filter-bar.visible,
214
- .modules.visible {
215
- animation: fadeUp 0.45s ease both;
216
- }
217
- .filter-bar.visible { animation-delay: 0.08s; }
218
- .modules.visible { animation-delay: 0.14s; }
219
-
220
- /* ── 页面容器 ── */
221
- .features-page {
222
- max-width: 800px;
223
- margin: 0 auto;
224
- padding: 2.5rem 1.5rem 4rem;
225
- }
226
-
227
- /* ── Hero ── */
228
- .hero {
229
- padding-bottom: 2rem;
230
- margin-bottom: 2rem;
231
- border-bottom: 0.5px solid var(--el-border-color-light);
232
- }
233
- .eyebrow {
234
- font-size: 11px;
235
- letter-spacing: 0.14em;
236
- text-transform: uppercase;
237
- color: var(--el-text-color-placeholder);
238
- margin-bottom: 1rem;
239
- }
240
- .hero-title {
241
- font-size: 48px;
242
- font-weight: 500;
243
- line-height: 1.05;
244
- letter-spacing: -1.5px;
245
- color: var(--el-text-color-primary);
246
- margin-bottom: 1.5rem;
247
- }
248
- .hero-title em {
249
- font-style: normal;
250
- color: var(--el-color-primary);
251
- }
252
- .hero-stats {
253
- display: flex;
254
- gap: 2.5rem;
255
- }
256
- .stat {
257
- display: flex;
258
- flex-direction: column;
259
- gap: 3px;
260
- }
261
- .stat-n {
262
- font-size: 28px;
263
- font-weight: 500;
264
- color: var(--el-text-color-primary);
265
- letter-spacing: -0.5px;
266
- line-height: 1;
267
- }
268
- .stat-l {
269
- font-size: 12px;
270
- color: var(--el-text-color-placeholder);
271
- }
272
-
273
- /* ── 筛选栏 ── */
274
- .filter-bar {
275
- display: flex;
276
- gap: 6px;
277
- flex-wrap: wrap;
278
- margin-bottom: 1.75rem;
279
- }
280
- .fbtn {
281
- font-size: 12px;
282
- padding: 5px 14px;
283
- border-radius: 999px;
284
- border: 0.5px solid var(--el-border-color);
285
- background: transparent;
286
- color: var(--el-text-color-secondary);
287
- cursor: pointer;
288
- transition: all 0.12s;
289
- font-family: inherit;
290
- }
291
- .fbtn:hover {
292
- border-color: var(--el-border-color-darker);
293
- color: var(--el-text-color-primary);
294
- }
295
- .fbtn.on {
296
- background: var(--el-text-color-primary);
297
- color: var(--el-bg-color);
298
- border-color: transparent;
299
- }
300
-
301
- /* ── 模块卡片 ── */
302
- .module {
303
- margin-bottom: 1rem;
304
- border: 0.5px solid var(--el-border-color-light);
305
- border-radius: 12px;
306
- overflow: hidden;
307
- }
308
- .mhead {
309
- display: flex;
310
- align-items: center;
311
- gap: 12px;
312
- padding: 1rem 1.25rem;
313
- cursor: pointer;
314
- user-select: none;
315
- transition: background 0.1s;
316
- }
317
- .mhead:hover {
318
- background: var(--el-fill-color-light);
319
- }
320
- .micon {
321
- width: 36px;
322
- height: 36px;
323
- border-radius: 8px;
324
- display: flex;
325
- align-items: center;
326
- justify-content: center;
327
- flex-shrink: 0;
328
- border: 0.5px solid transparent;
329
- }
330
- .minfo {
331
- display: flex;
332
- flex-direction: column;
333
- gap: 2px;
334
- }
335
- .mname {
336
- font-size: 15px;
337
- font-weight: 500;
338
- color: var(--el-text-color-primary);
339
- }
340
- .mdesc {
341
- font-size: 12px;
342
- color: var(--el-text-color-secondary);
343
- }
344
- .mright {
345
- margin-left: auto;
346
- display: flex;
347
- align-items: center;
348
- gap: 10px;
349
- }
350
- .mcount {
351
- font-size: 12px;
352
- color: var(--el-text-color-placeholder);
353
- }
354
- .mchevron {
355
- font-size: 14px;
356
- color: var(--el-text-color-placeholder);
357
- transition: transform 0.2s;
358
- }
359
- .mchevron.open {
360
- transform: rotate(180deg);
361
- }
362
-
363
- /* 模块主题色 */
364
- .blue .micon { background: #E6F1FB; color: #185FA5; border-color: #B5D4F4; }
365
- .green .micon { background: #EAF3DE; color: #3B6D11; border-color: #C0DD97; }
366
- .amber .micon { background: #FAEEDA; color: #854F0B; border-color: #FAC775; }
367
- .purple .micon{ background: #EEEDFE; color: #534AB7; border-color: #CECBF6; }
368
- .coral .micon { background: #FAECE7; color: #993C1D; border-color: #F5C4B3; }
369
-
370
- /* ── 模块内容体 ── */
371
- .mbody {
372
- border-top: 0.5px solid var(--el-border-color-light);
373
- }
374
-
375
- /* 展开动画 */
376
- .slide-enter-active,
377
- .slide-leave-active {
378
- transition: max-height 0.25s ease, opacity 0.2s ease;
379
- overflow: hidden;
380
- max-height: 2000px;
381
- }
382
- .slide-enter-from,
383
- .slide-leave-to {
384
- max-height: 0;
385
- opacity: 0;
386
- }
387
-
388
- /* ── 每行能力 ── */
389
- .row {
390
- display: grid;
391
- grid-template-columns: 1fr 80px;
392
- gap: 1rem;
393
- padding: 0.75rem 1.25rem;
394
- border-bottom: 0.5px solid var(--el-border-color-lighter);
395
- align-items: start;
396
- transition: background 0.1s;
397
- }
398
- .row:last-of-type {
399
- border-bottom: none;
400
- }
401
- .row:hover {
402
- background: var(--el-fill-color-light);
403
- }
404
- .rname {
405
- font-size: 14px;
406
- font-weight: 500;
407
- color: var(--el-text-color-primary);
408
- margin-bottom: 3px;
409
- }
410
- .rdesc {
411
- font-size: 13px;
412
- color: var(--el-text-color-secondary);
413
- line-height: 1.55;
414
- }
415
- .rtags {
416
- display: flex;
417
- gap: 5px;
418
- flex-wrap: wrap;
419
- margin-top: 6px;
420
- }
421
- .tag {
422
- font-size: 11px;
423
- padding: 2px 8px;
424
- border-radius: 999px;
425
- border: 0.5px solid var(--el-border-color);
426
- color: var(--el-text-color-secondary);
427
- }
428
- .tag.new { background: #E6F1FB; border-color: #B5D4F4; color: #0C447C; }
429
- .tag.beta { background: #FAEEDA; border-color: #FAC775; color: #633806; }
430
-
431
- .rdate {
432
- text-align: right;
433
- display: flex;
434
- flex-direction: column;
435
- gap: 2px;
436
- padding-top: 2px;
437
- }
438
- .rdate-mon {
439
- font-size: 13px;
440
- font-weight: 500;
441
- color: var(--el-text-color-secondary);
442
- }
443
- .rdate-yr {
444
- font-size: 11px;
445
- color: var(--el-text-color-placeholder);
446
- }
447
-
448
- /* ── 展开更多行 ── */
449
- .more-row {
450
- display: flex;
451
- align-items: center;
452
- justify-content: center;
453
- gap: 6px;
454
- padding: 0.6rem 1.25rem;
455
- font-size: 12px;
456
- color: var(--el-text-color-placeholder);
457
- background: var(--el-fill-color-light);
458
- cursor: pointer;
459
- border-top: 0.5px solid var(--el-border-color-lighter);
460
- transition: color 0.1s;
461
- }
462
- .more-row:hover {
463
- color: var(--el-text-color-secondary);
464
- }
465
- .more-row .ti {
466
- font-size: 13px;
467
- }
468
-
469
- /* ── 响应式 ── */
470
- @media (max-width: 600px) {
471
- .hero-title { font-size: 32px; }
472
- .hero-stats { gap: 1.5rem; }
473
- .stat-n { font-size: 22px; }
474
- }
475
- </style>