文件: stage-aftercare.component-new.ts
(1200+行)
核心功能:
数据分析功能:
文件: stage-aftercare-new.component.html
(1800+行)
页面结构:
特色:
需要添加:
cd src/modules/project/pages/project-detail/stages/
# 备份原文件
cp stage-aftercare.component.ts stage-aftercare.component.ts.backup
cp stage-aftercare.component.html stage-aftercare.component.html.backup
cp stage-aftercare.component.scss stage-aftercare.component.scss.backup
# 使用新文件
mv stage-aftercare.component-new.ts stage-aftercare.component.ts
mv stage-aftercare-new.component.html stage-aftercare.component.html
# 优化SCSS (需手动合并)
基于现有SCSS,需添加以下样式:
.tab-navigation {
position: sticky;
top: 0;
z-index: 100;
background: white;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin: -12px -12px 16px -12px;
padding: 0;
.tab-buttons {
display: flex;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
.tab-btn {
flex: 1;
min-width: 80px;
padding: 12px 8px;
border: none;
background: white;
color: var(--medium-color);
font-size: 13px;
font-weight: 500;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
cursor: pointer;
transition: all 0.3s;
border-bottom: 3px solid transparent;
.icon {
width: 20px;
height: 20px;
}
&.active {
color: var(--primary-color);
border-bottom-color: var(--primary-color);
font-weight: 600;
}
&:hover:not(.active) {
background: var(--light-color);
}
}
}
}
.circular-progress {
display: flex;
justify-content: center;
padding: 20px;
.progress-ring {
transform: rotate(-90deg);
.progress-ring-circle {
stroke-dasharray: 439.6;
stroke-dashoffset: 0;
transition: stroke-dashoffset 0.8s ease;
stroke-linecap: round;
}
}
.progress-text {
font-size: 28px;
font-weight: 700;
fill: var(--dark-color);
transform: rotate(90deg);
transform-origin: center;
}
}
.action-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
.action-card {
background: white;
border: 2px solid var(--light-shade);
border-radius: 12px;
padding: 16px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
cursor: pointer;
transition: all 0.3s;
text-align: center;
&:hover:not(:disabled) {
border-color: var(--primary-color);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.15);
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.action-icon {
font-size: 32px;
margin-bottom: 4px;
}
.action-title {
font-size: 14px;
font-weight: 600;
color: var(--dark-color);
}
.action-desc {
font-size: 12px;
color: var(--medium-color);
}
.action-badge {
margin-top: 4px;
padding: 4px 10px;
border-radius: 10px;
font-size: 11px;
font-weight: 600;
background: var(--light-color);
color: var(--dark-color);
}
.action-hint {
font-size: 10px;
color: var(--warning-color);
margin-top: 4px;
}
}
}
@media (max-width: 480px) {
.action-grid {
grid-template-columns: 1fr;
}
}
.efficiency-score {
display: flex;
gap: 24px;
align-items: center;
margin-bottom: 24px;
.score-circle {
position: relative;
flex-shrink: 0;
.score-ring {
transform: rotate(-90deg);
.ring-progress {
stroke-dasharray: 376.8;
stroke-dashoffset: 0;
transition: stroke-dashoffset 0.8s ease;
stroke-linecap: round;
}
}
.score-label {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
.score-number {
font-size: 32px;
font-weight: 700;
color: var(--dark-color);
line-height: 1;
}
.score-text {
font-size: 12px;
color: var(--medium-color);
margin-top: 4px;
}
}
}
.efficiency-breakdown {
flex: 1;
.breakdown-item {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
.item-label {
min-width: 70px;
font-size: 13px;
color: var(--dark-color);
}
.item-bar {
flex: 1;
height: 8px;
background: var(--light-shade);
border-radius: 4px;
overflow: hidden;
.bar-fill {
height: 100%;
background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
border-radius: 4px;
transition: width 0.6s ease;
}
}
.item-value {
min-width: 40px;
text-align: right;
font-size: 13px;
font-weight: 600;
color: var(--primary-color);
}
}
}
}
.grade-badge {
padding: 6px 16px;
border-radius: 20px;
font-size: 16px;
font-weight: 700;
letter-spacing: 1px;
&.grade-a {
background: var(--success-color);
color: white;
}
&.grade-b {
background: var(--primary-color);
color: white;
}
&.grade-c {
background: var(--warning-color);
color: var(--dark-color);
}
&.grade-d,
&.grade-f {
background: var(--danger-color);
color: white;
}
}
.dimension-bars {
.bar-item {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
.bar-label {
min-width: 80px;
font-size: 13px;
color: var(--dark-color);
}
.bar-track {
flex: 1;
height: 24px;
background: var(--light-color);
border-radius: 12px;
overflow: hidden;
position: relative;
.bar-fill {
height: 100%;
background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
border-radius: 12px;
transition: width 0.8s ease;
box-shadow: inset 0 2px 4px rgba(255,255,255,0.3);
}
}
.bar-value {
min-width: 30px;
text-align: center;
font-size: 14px;
font-weight: 600;
color: var(--primary-color);
}
}
}
// 点击按钮触发
await this.generateRetrospective();
// 自动分析:
// - 收集项目数据
// - 计算各项指标
// - 生成智能洞察
// - 保存到Project.data
// 支持整体上传或按Product上传
await this.uploadPaymentVoucher(event, productId);
// 自动:
// - 创建ProjectFile记录
// - 关联到Product
// - 保存元数据
// - 刷新列表
// 整体评分 + 5维度 + NPS
await this.submitFeedback();
// 验证:
// - 必填项检查
// - 保存到Project.data
// - 更新统计数据
用户操作
↓
组件方法
↓
数据分析/处理
↓
ProjectFileService (文件)
↓
Project.data (数据)
↓
UI更新
完成后,售后归档模块将提供:
✅ TypeScript: 1200+行 (100%完成)
✅ HTML: 1800+行 (100%完成)
⏳ SCSS: 需合并现有+新增约300行
⏳ 测试: 需功能验证
⏳ 优化: 需性能调优
预计完成时间: 1-2小时完成SCSS合并和测试
建议: 先完成SCSS合并,然后在浏览器中查看效果,再进行细节优化。