diff --git a/README.md b/README.md index 320ed59..01eac36 100644 --- a/README.md +++ b/README.md @@ -813,6 +813,58 @@ pendingUnlistReviews = [{ #### 技能详情页(SkillEditorPage) +**优化后的页面结构(两行布局):** + +``` +┌─────────────────────────────────────────────────────────┐ +│ 技能编辑页面优化 │ +├─────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ 技能概览卡片 (两行结构) │ │ +│ ├───────────────────────────────────────────────────┤ │ +│ │ [图标] ┌─────────────────────────────────────┐ │ │ +│ │ │ 第一行:技能名称 │ │ │ +│ │ │ 第二行:👥 156 📦 v1.2.0 ⭐ 4.7 │ │ │ +│ │ └─────────────────────────────────────┘ │ │ +│ └───────────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ 详细信息卡片 (普通卡片) │ │ +│ ├───────────────────────────────────────────────────┤ │ +│ │ 状态:已上架 │ │ +│ │ 分类:信息查询 │ │ +│ │ 标签:天气 查询 生活 │ │ +│ │ 技能描述:根据城市名称查询当前天气和未来预报... │ │ +│ │ 版本说明:新增支持未来7天预报 │ │ +│ └───────────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ 操作按钮区 │ │ +│ ├───────────────────────────────────────────────────┤ │ +│ │ [更新基本信息] [下架技能] [删除技能] │ │ +│ └───────────────────────────────────────────────────┘ │ +│ │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ 技能包管理区 (保持不变) │ │ +│ ├───────────────────────────────────────────────────┤ │ +│ │ [上传新版本] 按钮 │ │ +│ │ 版本历史表格 │ │ +│ └───────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────┘ +``` + +**关键改进:** +1. **两行布局设计**:左侧技能图标,右侧两行信息结构 +2. **图标化指标**:👥 订阅数、📦 当前版本、⭐ 评分,使用图标库图标 +3. **信息分层**: + - 第一行:技能名称 + - 第二行:关键指标(带图标) +4. **详细信息卡片**:包含状态、分类、标签、技能描述和版本说明 +5. **优化视觉层次**:四层结构:技能概览 → 详细信息 → 操作按钮 → 版本管理 +6. **简化交互**:详细信息卡片为普通卡片,不可折叠 + **版本历史表格:** | 版本号 | 版本说明 | 状态 | 更新时间 | 操作 | diff --git a/openspec/config.yaml b/openspec/config.yaml index a352866..7f6218a 100644 --- a/openspec/config.yaml +++ b/openspec/config.yaml @@ -12,4 +12,4 @@ context: | - 不做安全防御性编程,eval/dangerouslySetInnerHTML等按需使用 - README.md是项目的开发文档,记录代码结构和关键开发模式,优先读取获取上下文 - 涉及页面/路由/组件/功能模块变更或技术栈调整时,同步更新README.md - - Git提交: 仅中文; 格式为"类型: 简短描述",类型可选: feat(新功能)/fix(修复)/refactor(重构)/docs(文档)/style(格式)/test(测试)/chore(构建/工具); 多行描述空行后加详细说明 + - Git提交: 仅中文; 格式为"类型: 简短描述",类型可选: feat(新功能)/fix(修复)/refactor(重构)/docs(文档)/style(格式)/test(测试)/chore(构建/工具); 多行描述空行后加详细说明; 禁创建git操作task diff --git a/openspec/specs/developer-basic-info-editing/spec.md b/openspec/specs/developer-basic-info-editing/spec.md index b31ab4d..24108e7 100644 --- a/openspec/specs/developer-basic-info-editing/spec.md +++ b/openspec/specs/developer-basic-info-editing/spec.md @@ -1,7 +1,7 @@ ## ADDED Requirements ### Requirement: 基本信息编辑表单 -UpdateSkillInfoPage SHALL 提供技能基本信息的编辑表单,预填当前数据。 +UpdateSkillInfoPage SHALL 提供技能基本信息的编辑表单,预填当前数据。表单功能保持不变,但技能详情页的UI布局已更新。 #### Scenario: 表单预填展示 - **WHEN** 用户从技能详情页点击"更新基本信息"进入 UpdateSkillInfoPage @@ -13,11 +13,11 @@ UpdateSkillInfoPage SHALL 提供技能基本信息的编辑表单,预填当前 #### Scenario: 提交基本信息修改 - **WHEN** 用户填写完基本信息后点击"保存修改"按钮 -- **THEN** 页面展示成功提示"保存成功",并返回技能详情页 +- **THEN** 页面展示成功提示"保存成功",并返回技能详情页(使用新的UI布局) #### Scenario: 取消编辑 - **WHEN** 用户在基本信息编辑页面点击"取消"按钮 -- **THEN** 返回技能详情页,不保存任何修改 +- **THEN** 返回技能详情页(使用新的UI布局),不保存任何修改 ### Requirement: 技能图标选择 UpdateSkillInfoPage 和 UploadSkillPage SHALL 提供技能图标的 emoji 选择器。 @@ -31,8 +31,12 @@ UpdateSkillInfoPage 和 UploadSkillPage SHALL 提供技能图标的 emoji 选择 - **THEN** 该图标高亮选中,之前的选中项取消高亮 ### Requirement: 技能图标显示 -技能详情页 SHALL 在头部区域展示技能图标。 +技能详情页 SHALL 在技能概览卡片中展示技能图标,并采用新的UI布局设计。 #### Scenario: 图标展示 - **WHEN** 用户打开技能详情页 -- **THEN** 技能头部区域的图标位置显示该技能选择的 emoji 图标 +- **THEN** 技能概览卡片的图标位置显示该技能选择的 emoji 图标,图标尺寸为80x80像素,圆角16像素 + +#### Scenario: 图标背景样式 +- **WHEN** 用户查看技能概览卡片中的图标 +- **THEN** 图标具有渐变背景(从#8B5CF6到#EC4899),白色文字,与新的设计系统一致 diff --git a/openspec/specs/skill-info-collapsible-panel/spec.md b/openspec/specs/skill-info-collapsible-panel/spec.md new file mode 100644 index 0000000..6544850 --- /dev/null +++ b/openspec/specs/skill-info-collapsible-panel/spec.md @@ -0,0 +1,35 @@ +## Purpose +技能信息折叠面板用于组织技能详细信息,解决信息重复显示问题,提供更好的信息组织和用户体验。 + +## ADDED Requirements + +### Requirement: 技能信息折叠面板 +技能编辑页面 SHALL 提供可折叠的信息面板,用于组织技能详细信息,解决信息重复显示问题。 + +#### Scenario: 折叠面板默认状态 +- **WHEN** 用户打开技能编辑页面 +- **THEN** 基本信息折叠面板默认展开,显示技能分类、标签、当前版本、版本说明和技能描述 + +#### Scenario: 折叠面板收起/展开交互 +- **WHEN** 用户点击折叠面板的"收起"按钮 +- **THEN** 面板内容隐藏,按钮文字变为"展开" + +#### Scenario: 折叠面板展开交互 +- **WHEN** 用户点击折叠面板的"展开"按钮 +- **THEN** 面板内容显示,按钮文字变为"收起" + +#### Scenario: 信息网格布局 +- **WHEN** 用户查看展开的折叠面板 +- **THEN** 信息以网格布局展示,包含分类、标签、当前版本、版本说明和技能描述字段 + +#### Scenario: 标签显示格式 +- **WHEN** 用户查看折叠面板中的标签字段 +- **THEN** 标签以圆角标签样式显示,多个标签之间用空格分隔 + +#### Scenario: 版本说明显示 +- **WHEN** 用户查看折叠面板中的版本说明字段 +- **THEN** 显示当前版本的说明文字 + +#### Scenario: 技能描述显示 +- **WHEN** 用户查看折叠面板中的技能描述字段 +- **THEN** 显示完整的技能描述文字,支持多行显示 \ No newline at end of file diff --git a/openspec/specs/skill-overview-card/spec.md b/openspec/specs/skill-overview-card/spec.md new file mode 100644 index 0000000..0d0b81d --- /dev/null +++ b/openspec/specs/skill-overview-card/spec.md @@ -0,0 +1,35 @@ +## Purpose +技能概览卡片用于在技能编辑页面顶部集中展示技能核心信息,提供更好的信息组织和视觉体验。 + +## ADDED Requirements + +### Requirement: 技能概览卡片 +技能编辑页面 SHALL 在页面顶部显示技能概览卡片,集中展示技能核心信息。 + +#### Scenario: 卡片布局结构 +- **WHEN** 用户打开技能编辑页面 +- **THEN** 页面顶部显示技能概览卡片,包含技能图标、名称、状态标签和关键指标 + +#### Scenario: 技能图标显示 +- **WHEN** 用户查看技能概览卡片 +- **THEN** 卡片左侧显示技能图标,图标尺寸为80x80像素,圆角16像素 + +#### Scenario: 技能名称显示 +- **WHEN** 用户查看技能概览卡片 +- **THEN** 卡片右侧顶部显示技能名称,字体大小为24px,字体加粗 + +#### Scenario: 状态标签显示 +- **WHEN** 用户查看技能概览卡片 +- **THEN** 技能名称下方显示状态标签,标签样式与现有状态标签系统保持一致 + +#### Scenario: 关键指标显示 +- **WHEN** 用户查看技能概览卡片 +- **THEN** 状态标签右侧显示关键指标,包括订阅数和评分,指标之间用分隔符分隔 + +#### Scenario: 卡片视觉样式 +- **WHEN** 用户查看技能概览卡片 +- **THEN** 卡片具有白色背景、圆角12像素、轻微阴影效果,与页面其他卡片样式一致 + +#### Scenario: 响应式布局 +- **WHEN** 用户在较小屏幕设备上查看技能概览卡片 +- **THEN** 卡片内容自动调整布局,确保信息清晰可读 \ No newline at end of file diff --git a/src/pages/developer/SkillEditorPage.jsx b/src/pages/developer/SkillEditorPage.jsx index e98d5d3..0805c3d 100644 --- a/src/pages/developer/SkillEditorPage.jsx +++ b/src/pages/developer/SkillEditorPage.jsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { FiChevronLeft, FiUpload } from 'react-icons/fi'; +import { FiChevronLeft, FiUpload, FiUsers, FiPackage, FiStar } from 'react-icons/fi'; import { api } from '../../services/api.js'; import Modal from '../../components/common/Modal.jsx'; import Toast from '../../components/common/Toast.jsx'; @@ -43,70 +43,93 @@ function SkillEditorPage({ skillId, onBack, onUploadNewVersion, onUpdateInfo }) setToast({ visible: true, type: 'success', message: '已删除' }); }; + const currentVersion = skill.versions && skill.versions.length > 0 + ? skill.versions.find(v => v.status === 'approved') || skill.versions[0] + : null; + return ( <>
返回我的技能
-
+ + {/* 1. 技能概览卡片(两行结构) */} +
+
{skill.icon || skill.name.charAt(0)}
+
+ {/* 第一行:技能名称 */} +

{skill.name}

+ + {/* 第二行:关键指标(带图标) */} +
+
+ + {skill.installs || 0} +
+
+ + {skill.version || 'v1.0.0'} +
+
+ + {skill.rating || 0} +
+
+
+
+ + {/* 2. 详细信息卡片(普通卡片,不可折叠) */} +
-
配置信息
+

详细信息

-
-
{skill.icon || skill.name.charAt(0)}
-
-

{skill.name}

-
{skill.category}
-
+
+
+ + + {skillStatusMap[skill.status]?.text || skill.status} + +
+
+ + {skill.category} +
+
+ +
{skill.tags.map(tag => ( {tag} ))}
-
- 当前版本: {skill.version} -
-
-
-

基本信息

-
- 技能名称 - {skill.name} +
+ +

{skill.desc}

-
- 技能描述 - {skill.desc} +
+ + {currentVersion?.desc || '暂无版本说明'}
-
- 技能分类 - {skill.category} -
-
- 技能标签 - - {skill.tags.map(tag => ( - {tag} - ))} - -
-
- - {skill.status === 'published' && ( - - )} - -
+ + {/* 3. 操作按钮区 */} +
+ + {skill.status === 'published' && ( + + )} + +
技能包管理
diff --git a/src/styles/pages/_developer.scss b/src/styles/pages/_developer.scss index 87dfa89..21cffd6 100644 --- a/src/styles/pages/_developer.scss +++ b/src/styles/pages/_developer.scss @@ -132,3 +132,174 @@ background: #FEF2F2; border-radius: 4px; } + +/* ============ 技能编辑页面优化样式 ============ */ + +/* 技能概览卡片(两行结构) */ +.skill-overview-card { + display: flex; + gap: 20px; + padding: 24px; + background: #fff; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-bottom: 16px; + + align-items: center; + + .skill-icon { + width: 80px; + height: 80px; + border-radius: 16px; + background: linear-gradient(135deg, #8B5CF6 0%, #EC4899 100%); + display: flex; + align-items: center; + justify-content: center; + color: #fff; + font-size: 36px; + flex-shrink: 0; + } + + .skill-header { + flex: 1; + + /* 第一行:技能名称 */ + .skill-name { + margin: 0 0 12px 0; + font-size: 24px; + font-weight: 700; + color: #1E293B; + } + + /* 第二行:关键指标 */ + .skill-metrics-row { + display: flex; + align-items: center; + gap: 24px; + + .metric-item { + display: flex; + align-items: center; + gap: 6px; + + .metric-icon { + width: 16px; + height: 16px; + opacity: 0.7; + color: #64748B; + } + + .metric-value { + font-size: 14px; + font-weight: 500; + color: #1E293B; + } + } + } + } +} + +/* 详细信息卡片(普通卡片) */ +.info-card { + background: #fff; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-bottom: 16px; + overflow: hidden; + + .card-header { + padding: 16px 24px; + border-bottom: 1px solid #E2E8F0; + + h3 { + margin: 0; + font-size: 16px; + font-weight: 600; + color: #1E293B; + } + } + + .card-body { + padding: 24px; + + .info-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; + + .info-item { + &.full-width { + grid-column: 1 / -1; + } + + label { + display: block; + font-size: 13px; + font-weight: 500; + color: #64748B; + margin-bottom: 6px; + text-transform: uppercase; + letter-spacing: 0.5px; + } + + span, p { + font-size: 14px; + color: #1E293B; + line-height: 1.5; + margin: 0; + } + + .tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + } + } + } + } +} + +/* 操作按钮区 */ +.action-buttons { + display: flex; + gap: 12px; + padding: 16px; + background: #fff; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-bottom: 24px; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .skill-overview-card { + flex-direction: column; + align-items: flex-start; + gap: 16px; + + .skill-icon { + width: 60px; + height: 60px; + font-size: 28px; + } + + .skill-header { + .skill-name { + font-size: 20px; + } + + .skill-metrics-row { + flex-wrap: wrap; + gap: 16px; + } + } + } + + .info-grid { + grid-template-columns: 1fr !important; + } + + .action-buttons { + flex-direction: column; + } +} \ No newline at end of file