从组长看板进入交付执行阶段时,需要显示真正的审批和驳回按钮,而不是测试按钮。按钮需要:
stage-delivery.component.html)修改前:
getDeliveryApprovalStatus() === 'pending' 时才显示审批按钮修改后:
<!-- 🔥 组长审批操作条:组长从组长看板进入时始终显示(只要有文件) -->
@if (isTeamLeader && !isFromCustomerService && shouldShowApprovalButtons()) {
<div class="leader-approval-bar">
<div class="approval-buttons-container">
<button class="btn-approve" (click)="approveDelivery()" [disabled]="saving || !hasDeliveryFiles()">
<span class="btn-icon">✅</span>
<span class="btn-text">通过审批</span>
</button>
<button class="btn-reject" (click)="rejectDelivery()" [disabled]="saving || !hasDeliveryFiles()">
<span class="btn-icon">❌</span>
<span class="btn-text">驳回交付</span>
</button>
</div>
@if (!hasDeliveryFiles()) {
<p class="approval-hint">💡 项目暂无交付文件,请等待设计师上传后再审批</p>
}
</div>
}
stage-delivery.component.ts)shouldShowApprovalButtons()判断是否应该显示审批按钮:
shouldShowApprovalButtons(): boolean {
if (!this.project) return false;
// 如果项目已经审批通过或驳回,不再显示审批按钮
const status = this.getDeliveryApprovalStatus();
if (status === 'approved' || status === 'rejected') {
console.log('🔍 项目已审批完成,隐藏审批按钮');
return false;
}
// 组长从组长看板进入时,始终显示审批按钮
console.log('🔍 组长从组长看板进入,显示审批按钮');
return true;
}
hasDeliveryFiles()判断是否有交付文件:
hasDeliveryFiles(): boolean {
const totalFiles = this.getTotalFileCount();
console.log('🔍 交付文件数量:', totalFiles);
return totalFiles > 0;
}
approveDelivery())新增功能:
data.deliveryApprovalStatus、data.deliveryApproval、顶层 pendingApproval 字段)✅ 详细的控制台日志
async approveDelivery(): Promise<void> {
if (!this.project || !this.currentUser || !this.isTeamLeader) {
console.warn('❌ 无法审批:缺少项目、用户或组长权限');
return;
}
// 检查是否有交付文件
if (!this.hasDeliveryFiles()) {
window?.fmode?.alert?.('项目暂无交付文件,无法审批');
return;
}
// 确认审批
const confirmed = await window?.fmode?.confirm?.(
'确认通过交付执行审批?\n\n' +
'审批通过后,项目将进入下一阶段。'
);
if (!confirmed) return;
try {
this.saving = true;
this.cdr.markForCheck();
console.log('🔥 开始审批交付执行...');
const data = this.project.get('data') || {};
const now = new Date().toISOString();
// 设置审批状态
data.deliveryApprovalStatus = 'approved';
data.deliveryApprovedBy = this.currentUser.id;
data.deliveryApprovedByName = this.currentUser.get('name');
data.deliveryApprovedAt = now;
// 🔥 清除待审批标记(顶层字段)
this.project.set('pendingApproval', false);
this.project.set('approvalStage', null);
// 🔥 更新审批记录到 deliveryApproval
if (data.deliveryApproval) {
data.deliveryApproval.status = 'approved';
data.deliveryApproval.approvedBy = this.currentUser.id;
data.deliveryApproval.approvedByName = this.currentUser.get('name');
data.deliveryApproval.approvedAt = now;
}
this.project.set('data', data);
console.log('💾 保存审批结果...');
await this.project.save();
console.log('✅ 交付执行审批通过!');
window?.fmode?.toast?.success?.('✅ 交付执行审批通过!');
// 刷新页面数据
await this.loadApprovalHistory();
this.cdr.markForCheck();
} catch (error) {
console.error('❌ 审批失败:', error);
window?.fmode?.alert?.('审批失败,请重试');
} finally {
this.saving = false;
this.cdr.markForCheck();
}
}
rejectDelivery())新增功能:
window.fmode.input)✅ 详细的控制台日志
async rejectDelivery(): Promise<void> {
if (!this.project || !this.currentUser || !this.isTeamLeader) {
console.warn('❌ 无法驳回:缺少项目、用户或组长权限');
return;
}
// 检查是否有交付文件
if (!this.hasDeliveryFiles()) {
window?.fmode?.alert?.('项目暂无交付文件,无需驳回');
return;
}
// 输入驳回原因
const reason = await window?.fmode?.input?.('请输入驳回原因:\n\n驳回后设计师需要重新提交。');
if (!reason || reason.trim() === '') {
window?.fmode?.toast?.info?.('已取消驳回');
return;
}
try {
this.saving = true;
this.cdr.markForCheck();
console.log('🔥 开始驳回交付执行...');
const data = this.project.get('data') || {};
const now = new Date().toISOString();
// 设置驳回状态
data.deliveryApprovalStatus = 'rejected';
data.deliveryRejectedBy = this.currentUser.id;
data.deliveryRejectedByName = this.currentUser.get('name');
data.deliveryRejectedAt = now;
data.deliveryRejectionReason = reason;
// 🔥 清除待审批标记(顶层字段)
this.project.set('pendingApproval', false);
this.project.set('approvalStage', null);
// 🔥 更新审批记录到 deliveryApproval
if (data.deliveryApproval) {
data.deliveryApproval.status = 'rejected';
data.deliveryApproval.rejectedBy = this.currentUser.id;
data.deliveryApproval.rejectedByName = this.currentUser.get('name');
data.deliveryApproval.rejectedAt = now;
data.deliveryApproval.rejectionReason = reason;
}
this.project.set('data', data);
console.log('💾 保存驳回结果...');
await this.project.save();
console.log('✅ 已驳回交付执行');
window?.fmode?.toast?.success?.('✅ 已驳回交付执行,设计师需要重新提交');
// 刷新页面数据
await this.loadApprovalHistory();
this.cdr.markForCheck();
} catch (error) {
console.error('❌ 驳回失败:', error);
window?.fmode?.alert?.('驳回失败,请重试');
} finally {
this.saving = false;
this.cdr.markForCheck();
}
}
stage-delivery.component.scss)按钮颜色方案:
#4caf50 → #2e7d32)#f44336 → #c62828)样式特性:
.btn-approve {
background: linear-gradient(135deg, #4caf50 0%, #2e7d32 100%);
color: white;
box-shadow: 0 6px 20px rgba(76, 175, 80, 0.3);
&:hover:not(:disabled) {
background: linear-gradient(135deg, #66bb6a 0%, #43a047 100%);
box-shadow: 0 10px 30px rgba(76, 175, 80, 0.5);
transform: translateY(-3px) scale(1.02); // 悬停时上浮+放大
}
&:active:not(:disabled) {
background: linear-gradient(135deg, #388e3c 0%, #1b5e20 100%);
}
}
.btn-reject {
background: linear-gradient(135deg, #f44336 0%, #c62828 100%);
color: white;
box-shadow: 0 6px 20px rgba(244, 67, 54, 0.3);
&:hover:not(:disabled) {
background: linear-gradient(135deg, #ef5350 0%, #d32f2f 100%);
box-shadow: 0 10px 30px rgba(244, 67, 54, 0.5);
transform: translateY(-3px) scale(1.02); // 悬停时上浮+放大
}
&:active:not(:disabled) {
background: linear-gradient(135deg, #c62828 0%, #b71c1c 100%);
}
}
提示信息样式:
.approval-hint {
text-align: center;
margin: 16px 0 0;
padding: 12px 20px;
background: rgba(255, 193, 7, 0.15);
border: 1px solid rgba(255, 193, 7, 0.3);
border-radius: 8px;
font-size: 14px;
color: #f57c00;
line-height: 1.6;
animation: pulse 2s ease-in-out infinite; // 脉动动画
}
┌─────────────────────────────────────────────────────────────┐
│ 组长审批操作区 │
│ ┌────────────────────────┐ ┌────────────────────────┐ │
│ │ ✅ 通过审批 │ │ ❌ 驳回交付 │ │
│ │ (绿色渐变,悬停上浮) │ │ (红色渐变,悬停上浮) │ │
│ └────────────────────────┘ └────────────────────────┘ │
│ 💡 项目暂无交付文件,请等待设计师上传后再审批 │
│ (仅在无文件时显示,带脉动动画) │
└─────────────────────────────────────────────────────────────┘
| 状态 | 外观 | 行为 |
|---|---|---|
| 正常 | 绿色/红色渐变,阴影 | 可点击 |
| 悬停 | 颜色变亮,阴影加深,上浮3px,放大1.02倍 | 可点击 |
| 点击 | 颜色变暗 | 执行审批/驳回 |
| 禁用 | 半透明,无阴影 | 不可点击(无文件或正在保存) |
// data 字段
{
deliveryApprovalStatus: 'approved',
deliveryApprovedBy: 'userId',
deliveryApprovedByName: '张三',
deliveryApprovedAt: '2024-01-01T12:00:00.000Z',
deliveryApproval: {
status: 'approved',
approvedBy: 'userId',
approvedByName: '张三',
approvedAt: '2024-01-01T12:00:00.000Z'
}
}
// 顶层字段
{
pendingApproval: false, // 清除待审批标记
approvalStage: null // 清除审批阶段标记
}
// data 字段
{
deliveryApprovalStatus: 'rejected',
deliveryRejectedBy: 'userId',
deliveryRejectedByName: '张三',
deliveryRejectedAt: '2024-01-01T12:00:00.000Z',
deliveryRejectionReason: '图片质量不达标,需要重新渲染',
deliveryApproval: {
status: 'rejected',
rejectedBy: 'userId',
rejectedByName: '张三',
rejectedAt: '2024-01-01T12:00:00.000Z',
rejectionReason: '图片质量不达标,需要重新渲染'
}
}
// 顶层字段
{
pendingApproval: false,
approvalStage: null
}
1. 组长从组长看板进入交付执行阶段
URL: http://localhost:4200/wxwork/cDL6R1hgSi/project/xxx/delivery?roleName=team-leader
2. 页面检测到 isTeamLeader=true, 调用 shouldShowApprovalButtons()
→ 返回 true(项目未审批完成)
3. 页面显示审批按钮(绿色通过、红色驳回)
4. 组长点击"通过审批"
↓
5. 检查文件数量:hasDeliveryFiles() → true
↓
6. 弹出确认对话框:"确认通过交付执行审批?"
↓
7. 用户确认 → 开始保存
↓
8. 更新数据:
- data.deliveryApprovalStatus = 'approved'
- data.deliveryApproval.status = 'approved'
- project.pendingApproval = false
↓
9. 显示成功提示:"✅ 交付执行审批通过!"
↓
10. 刷新页面数据,审批按钮消失(项目已审批完成)
1. 组长从组长看板进入交付执行阶段
2. 页面显示审批按钮,但按钮为禁用状态
同时显示提示:"💡 项目暂无交付文件,请等待设计师上传后再审批"
3. 组长点击按钮
↓
4. 检查文件数量:hasDeliveryFiles() → false
↓
5. 弹出提示:"项目暂无交付文件,无法审批"
↓
6. 操作终止
1. 组长点击"驳回交付"按钮
↓
2. 检查文件数量:hasDeliveryFiles() → true
↓
3. 弹出输入框:"请输入驳回原因:"
↓
4. 用户输入原因:"图片质量不达标,需要重新渲染"
↓
5. 开始保存
↓
6. 更新数据:
- data.deliveryApprovalStatus = 'rejected'
- data.deliveryRejectionReason = '图片质量不达标,需要重新渲染'
- data.deliveryApproval.status = 'rejected'
- project.pendingApproval = false
↓
7. 显示成功提示:"✅ 已驳回交付执行,设计师需要重新提交"
↓
8. 刷新页面数据,显示驳回状态横幅(包含驳回原因)
?roleName=team-leaderdata.deliveryApprovalStatus = 'approved'data.deliveryApproval.status = 'approved'pendingApproval = falsedata.deliveryRejectionReason 包含输入的原因?roleName=team-leader)才显示✅ 检测到URL参数 roleName=team-leader,强制启用审批按钮
🧹 已清除客服入口标记
🔍 权限检测结果: { isTeamLeader: true, isFromCustomerService: false }
🔍 组长从组长看板进入,显示审批按钮
🔍 交付文件数量: 15
🔥 开始审批交付执行...
💾 保存审批结果...
✅ 交付执行审批通过!
✅ 检测到URL参数 roleName=team-leader,强制启用审批按钮
🔍 组长从组长看板进入,显示审批按钮
🔍 交付文件数量: 0
❌ 无法审批:缺少项目、用户或组长权限
✅ 检测到URL参数 roleName=team-leader,强制启用审批按钮
🔍 组长从组长看板进入,显示审批按钮
🔍 交付文件数量: 15
🔥 开始驳回交付执行...
💾 保存驳回结果...
✅ 已驳回交付执行
yss-project/src/modules/project/pages/project-detail/stages/stage-delivery.component.html
yss-project/src/modules/project/pages/project-detail/stages/stage-delivery.component.ts
shouldShowApprovalButtons() 方法hasDeliveryFiles() 方法approveDelivery() 方法rejectDelivery() 方法yss-project/src/modules/project/pages/project-detail/stages/stage-delivery.component.scss
.approval-hint 样式pulse 动画现在从组长看板进入交付执行阶段时:
测试URL:
http://localhost:4200/wxwork/cDL6R1hgSi/project/iKvYck89zE/delivery?roleName=team-leader
您现在可以测试完整的审批流程了!🎉