位置:stage-delivery-execution.component.html 第21-58行
功能:
示例代码:
<!-- 🆕 停滞期/改图期状态标记 -->
@if (project?.data?.isModification) {
<div class="project-status-badge modification-badge">
<svg>...</svg>
<span class="badge-text">改图期</span>
<span class="badge-reason">设计师原因</span>
</div>
}
@if (project?.data?.isStalled) {
<div class="project-status-badge stalled-badge">
<svg>...</svg>
<span class="badge-text">停滞期</span>
<span class="badge-reason">客户原因</span>
<span class="badge-date">12/15恢复</span>
</div>
}
位置:stage-delivery-execution.component.html 第245-267行
功能:
isTeamLeader || isFromCustomerService)示例代码:
<!-- 🆕 取消停滞期/改图期按钮 -->
@if (project?.data?.isStalled && (isTeamLeader || isFromCustomerService)) {
<button class="cancel-status-btn stalled-cancel" (click)="cancelStagnation()">
<svg>...</svg>
<span>取消停滞期</span>
</button>
}
@if (project?.data?.isModification && (isTeamLeader || isFromCustomerService)) {
<button class="cancel-status-btn modification-cancel" (click)="cancelModification()">
<svg>...</svg>
<span>取消改图期</span>
</button>
}
文件:stage-delivery-execution.component.ts
async cancelStagnation(): Promise<void> {
if (!this.project) return;
const confirmed = confirm('确定要取消该项目的停滞期状态吗?');
if (!confirmed) return;
this.saving = true;
try {
const query = new Parse.Query('Project');
const projectObj = await query.get(this.project.id);
const projectData = projectObj.get('data') || {};
// 清除停滞期相关字段
projectData.isStalled = false;
delete projectData.stagnationReasonType;
delete projectData.stagnationCustomReason;
delete projectData.estimatedResumeDate;
delete projectData.reasonNotes;
delete projectData.markedAt;
delete projectData.markedBy;
projectObj.set('data', projectData);
await projectObj.save();
alert('停滞期状态已取消');
this.refreshData.emit();
} catch (error) {
console.error('取消停滞期失败:', error);
alert('取消停滞期失败,请重试');
} finally {
this.saving = false;
this.cdr.markForCheck();
}
}
async cancelModification(): Promise<void> {
// 类似 cancelStagnation,清除改图期相关字段
}
文件:stage-delivery.component.ts 第441-487行
逻辑:
async onFileUploaded(event: { productId: string, deliveryType: string, fileCount: number }) {
if (event.fileCount > 0 && this.project) {
const projectData = this.project.get('data') || {};
// 🆕 检查是否处于改图期,如果是则自动取消
if (projectData.isModification === true) {
console.log('🎨 [改图期] 上传文件后自动取消改图期标记');
projectData.isModification = false;
projectData.modificationReasonType = undefined;
projectData.modificationCustomReason = undefined;
await this.project.save();
console.log('✅ [改图期] 改图期标记已取消');
}
}
}
文件:stage-delivery-execution.component.ts 第975-983行
逻辑:
async confirmSpace(spaceId: string) {
// ... 确认逻辑
// 🆕 确认交付清单时自动取消改图期标记
if (data.isModification === true) {
console.log('🎨 [改图期] 确认交付清单,自动取消改图期标记');
data.isModification = false;
delete data.modificationReasonType;
delete data.modificationCustomReason;
console.log('✅ [改图期] 改图期标记已取消');
}
await this.project.save();
}
文件:stage-delivery-execution.component.scss
.revision-toolbar {
display: flex;
flex-wrap: wrap; // 🆕 允许换行,避免小屏幕遮挡
gap: 8px;
margin-bottom: 12px;
align-items: center;
}
.project-status-badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border-radius: 16px;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
&.modification-badge {
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
color: white;
box-shadow: 0 2px 6px rgba(251, 191, 36, 0.3);
}
&.stalled-badge {
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
color: white;
box-shadow: 0 2px 6px rgba(239, 68, 68, 0.3);
}
// 小屏幕优化
@media screen and (max-width: 640px) {
font-size: 11px;
padding: 4px 10px;
.badge-reason, .badge-date {
display: none; // 小屏幕隐藏详细原因
}
}
}
.cancel-status-btn {
padding: 8px 14px;
border: none;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 4px;
transition: all 0.2s;
margin-top: 8px;
&.stalled-cancel {
background: #fee2e2;
color: #dc2626;
border: 1px solid #fecaca;
&:hover:not(:disabled) {
background: #fecaca;
}
}
&.modification-cancel {
background: #fef3c7;
color: #d97706;
border: 1px solid #fde68a;
&:hover:not(:disabled) {
background: #fde68a;
}
}
}
project.data.isStalled / isModification)🎨 [改图期] 上传文件后自动取消改图期标记🎨 [改图期] 确认交付清单,自动取消改图期标记确定要取消该项目的停滞期状态吗?停滞期状态已取消组长Dashboard
↓
markProjectAsStalled/Modification
↓
updateProjectMarkStatus
↓
Parse.save (project.data.isStalled/isModification)
↓
Dashboard刷新,项目移动到对应列
组员/组长点击取消按钮
↓
cancelStagnation/Modification
↓
Parse.save (清除 isStalled/isModification)
↓
refreshData.emit()
↓
UI刷新,徽章消失
组员上传图片 / 确认清单
↓
onFileUploaded / confirmSpace
↓
检测 project.data.isModification === true
↓
清除改图期字段
↓
Parse.save
↓
UI刷新,徽章消失
{
isStalled: boolean; // 是否停滞
stagnationReasonType: string; // 原因类型:'designer' | 'customer' | 'custom'
stagnationCustomReason?: string; // 自定义原因
estimatedResumeDate?: Date; // 预计恢复日期
reasonNotes?: string; // 备注
markedAt?: Date; // 标记时间
markedBy?: string; // 标记人
}
{
isModification: boolean; // 是否改图
modificationReasonType: string; // 原因类型:'customer' | 'designer' | 'custom'
modificationCustomReason?: string; // 自定义原因
reasonNotes?: string; // 备注
markedAt?: Date; // 标记时间
markedBy?: string; // 标记人
}
权限控制
数据一致性
日志记录
用户体验
创建日期:2024-12-07
最后更新:2024-12-07
版本:v1.0