123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- <div class="project-detail-container designer-page">
- <!-- 项目标题栏 -->
- <div class="project-header card">
- <div class="header-content">
- <h1>项目详情</h1>
- <div class="project-meta">
- <span class="project-id">项目ID: {{ projectId }}</span>
- <span class="project-status" *ngIf="project">{{ project.status }}</span>
- </div>
- </div>
- <div class="header-actions">
- <!-- 返回工作台按钮 -->
- <button (click)="backToWorkbench()" class="back-btn">返回工作台</button>
-
- <!-- 切换项目下拉菜单 -->
- <div class="project-switcher">
- <button (click)="showDropdown = !showDropdown" class="switch-btn">切换项目</button>
- <div *ngIf="showDropdown" class="switch-dropdown" (click)="$event.stopPropagation()">
- <div *ngFor="let p of projects"
- (click)="switchProject(p.id); showDropdown = false"
- [class.active]="p.id === projectId"
- class="project-item">
- <span class="project-name">{{ p.name }}</span>
- <span class="project-status-badge"
- [class.ongoing]="p.status === '进行中'"
- [class.completed]="p.status === '已完成'"
- [class.pending]="p.status === '待处理'">
- {{ p.status }}
- </span>
- </div>
- </div>
- </div>
-
- <button (click)="generateReminderMessage()" class="stagnation-btn">设置停滞</button>
- </div>
- </div>
- <!-- 提醒消息弹窗 -->
- <div *ngIf="reminderMessage" class="reminder-popup">
- {{ reminderMessage }}
- </div>
- <!-- 顶部导航标签页 -->
- <!-- <div class="project-tabs">
- <div class="tab-header">
- <button (click)="switchTab('progress')" [class.active]="isActiveTab('progress')" class="tab-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
- </svg>
- <span>项目进度</span>
- </button>
- <button (click)="switchTab('members')" [class.active]="isActiveTab('members')" class="tab-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
- <circle cx="9" cy="7" r="4"></circle>
- <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
- <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
- </svg>
- <span>项目成员</span>
- </button>
- <button (click)="switchTab('files')" [class.active]="isActiveTab('files')" class="tab-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
- <polyline points="14 2 14 8 20 8"></polyline>
- <line x1="16" y1="13" x2="8" y2="13"></line>
- <line x1="16" y1="17" x2="8" y2="17"></line>
- <polyline points="10 9 9 9 8 9"></polyline>
- </svg>
- <span>项目文件</span>
- </button>
- </div> -->
- <!-- 标签页内容 -->
- <div class="tab-content">
- <!-- 项目进度标签页 -->
- <div *ngIf="isActiveTab('progress')" class="progress-tab-content">
- <!-- 主要内容布局 - 左侧三分之一,右侧三分之二 -->
- <div class="main-content-layout">
- <!-- 左侧三分之一 - 项目基本信息和客户画像 -->
- <div class="left-column">
- <!-- 项目基本信息 -->
- <div class="project-info-card card">
- <h2>项目基本信息</h2>
- <div class="info-grid">
- <div class="info-item">
- <label>项目名称</label>
- <span>{{ project?.name || '加载中...' }}</span>
- </div>
- <div class="info-item">
- <label>客户姓名</label>
- <span>{{ project?.customerName || '加载中...' }}</span>
- </div>
- <div class="info-item">
- <label>当前阶段</label>
- <span class="stage-tag">{{ project?.currentStage || '加载中...' }}</span>
- </div>
- <div class="info-item" *ngIf="project">
- <label>预计交付日期</label>
- <span>{{ project.deadline | date:'yyyy-MM-dd' }}</span>
- </div>
- </div>
- </div>
- <!-- 客户画像 -->
- <div class="customer-profile-card card">
- <h2>客户画像</h2>
-
- <!-- 技能匹配度警告 -->
- <div *ngIf="getSkillMismatchWarning()" class="warning-banner">
- <div class="warning-content">
- <span class="warning-icon">⚠️</span>
- <span class="warning-text">{{ getSkillMismatchWarning() }}</span>
- </div>
- <button (click)="notifyTeamLeader('skill-mismatch')" class="contact-leader-btn">联系组长</button>
- </div>
-
- <div *ngIf="project" class="tags-container">
- <div class="tag-section">
- <h3>客户偏好</h3>
- <div class="tags-grid">
- <ng-container *ngIf="project.customerTags && project.customerTags.length > 0">
- <div class="tag-item">
- <span class="tag-label">需求类型</span>
- <span *ngIf="project.customerTags[0].needType" class="tag">
- {{ project.customerTags[0].needType }}
- </span>
- </div>
- <div class="tag-item">
- <span class="tag-label">设计风格</span>
- <span *ngIf="project.customerTags[0].preference" class="tag">
- {{ project.customerTags[0].preference }}
- </span>
- </div>
- <div class="tag-item">
- <span class="tag-label">色彩氛围</span>
- <span *ngIf="project.customerTags[0].colorAtmosphere" class="tag">
- {{ project.customerTags[0].colorAtmosphere }}
- </span>
- </div>
- </ng-container>
- </div>
- </div>
-
- <div class="tag-section">
- <h3>项目要求</h3>
- <div class="tags-flex">
- <div class="tag-group">
- <span class="group-label">高优先级需求</span>
- <div class="tags">
- <span *ngFor="let priority of project.highPriorityNeeds" class="priority-tag">
- {{ priority }}
- </span>
- </div>
- </div>
- <div class="tag-group">
- <span class="group-label">擅长技能</span>
- <div class="tags">
- <span *ngFor="let skill of project.skillsRequired" class="skill-tag">
- {{ skill }}
- </span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 右侧三分之二 - 制作流程进度 -->
- <div class="right-column">
- <div class="process-card card">
- <h2>制作流程进度</h2>
- <div class="stage-progress-container">
- <div class="stage-progress">
- <div class="stage" [class.completed]="project?.currentStage !== '建模'" [class.active]="project?.currentStage === '建模'">
- <div class="stage-icon">
- <span>{{ project?.currentStage !== '建模' ? '✓' : '1' }}</span>
- </div>
- <div class="stage-name">建模</div>
- </div>
- <div class="progress-line"></div>
- <div class="stage" [class.completed]="project?.currentStage !== '软装' && project?.currentStage !== '建模'" [class.active]="project?.currentStage === '软装'">
- <div class="stage-icon">
- <span>{{ project?.currentStage !== '软装' && project?.currentStage !== '建模' ? '✓' : '2' }}</span>
- </div>
- <div class="stage-name">软装</div>
- </div>
- <div class="progress-line"></div>
- <div class="stage" [class.completed]="project?.currentStage !== '渲染' && project?.currentStage !== '建模' && project?.currentStage !== '软装'" [class.active]="project?.currentStage === '渲染'">
- <div class="stage-icon">
- <span>{{ project?.currentStage !== '渲染' && project?.currentStage !== '建模' && project?.currentStage !== '软装' ? '✓' : '3' }}</span>
- </div>
- <div class="stage-name">渲染</div>
- </div>
- <div class="progress-line"></div>
- <div class="stage" [class.completed]="project?.currentStage !== '后期' && project?.currentStage !== '建模' && project?.currentStage !== '软装' && project?.currentStage !== '渲染'" [class.active]="project?.currentStage === '后期'">
- <div class="stage-icon">
- <span>{{ project?.currentStage !== '后期' && project?.currentStage !== '建模' && project?.currentStage !== '软装' && project?.currentStage !== '渲染' ? '✓' : '4' }}</span>
- </div>
- <div class="stage-name">后期</div>
- </div>
- </div>
- </div>
-
- <!-- 当前阶段操作 -->
- <div *ngIf="project" class="current-stage-actions">
- <div class="current-stage-info">
- <h3>当前阶段: <span class="stage-highlight">{{ project.currentStage }}</span></h3>
- </div>
- <div class="stage-actions">
- <button *ngIf="project.currentStage === '建模'" (click)="updateProjectStage('软装')" [disabled]="!areAllModelChecksPassed()" class="primary-btn">
- {{ areAllModelChecksPassed() ? '完成建模' : '完成所有模型检查' }}
- </button>
- <button *ngIf="project.currentStage === '软装'" (click)="updateProjectStage('渲染')" class="primary-btn">完成软装</button>
- <button *ngIf="project.currentStage === '渲染'" (click)="updateProjectStage('后期')" class="primary-btn">完成渲染</button>
- <button *ngIf="project.currentStage === '后期'" (click)="updateProjectStage('完成')" class="primary-btn">完成后期</button>
- </div>
- </div>
- <!-- 模型误差检查清单 - 仅在建模阶段显示 -->
- <div *ngIf="project?.currentStage === '建模'" class="model-check-section">
- <h3>模型误差检查清单</h3>
- <div class="checklist">
- <div *ngFor="let item of modelCheckItems" class="checklist-item">
- <input type="checkbox" [checked]="item.isPassed" (change)="updateModelCheckItem(item.id, !item.isPassed)" class="custom-checkbox">
- <span class="checklist-text">{{ item.name }}</span>
- <span class="check-status" [class.passed]="item.isPassed" [class.failed]="!item.isPassed">
- {{ item.isPassed ? '通过' : '未通过' }}
- </span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 阶段专属任务卡片 - 仅在对应节点显示 -->
- <div class="stage-specific-cards">
- <!-- 渲染阶段专属卡片 -->
- <div *ngIf="project?.currentStage === '渲染'" class="render-progress-card card">
- <h2>渲染进度</h2>
- <div *ngIf="isLoadingRenderProgress" class="loading-state">
- <div class="loading-spinner"></div>
- <span>加载中...</span>
- </div>
- <div *ngIf="errorLoadingRenderProgress" class="error-state">
- <span>加载失败</span>
- <button (click)="retryLoadRenderProgress()" class="secondary-btn">点击重试</button>
- </div>
- <div *ngIf="renderProgress && !isLoadingRenderProgress && !errorLoadingRenderProgress" class="progress-content">
- <!-- 渲染超时预警 -->
- <div *ngIf="renderProgress.estimatedTimeRemaining <= 3" class="timeout-warning">
- <div class="warning-icon">⚠️</div>
- <div class="warning-text">
- <span class="warning-title">渲染即将超时</span>
- <span class="warning-time">预计剩余时间: {{ renderProgress.estimatedTimeRemaining }} 小时</span>
- </div>
- </div>
- <!-- 渲染异常反馈模块 -->
- <div class="render-exception-section">
- <h3>渲染异常反馈</h3>
- <div class="exception-feedback-form">
- <div class="form-group">
- <label>异常类型:</label>
- <select [(ngModel)]="exceptionType" class="exception-select">
- <option value="failed">渲染失败</option>
- <option value="stuck">渲染卡顿</option>
- <option value="quality">渲染质量问题</option>
- <option value="other">其他问题</option>
- </select>
- </div>
- <div class="form-group">
- <label>详细描述:</label>
- <textarea
- [(ngModel)]="exceptionDescription"
- placeholder="请描述渲染过程中遇到的具体问题..."
- class="exception-textarea"
- ></textarea>
- </div>
- <div class="form-group">
- <label>上传截图 (可选):</label>
- <input type="file" (change)="uploadExceptionScreenshot($event)" class="screenshot-upload" id="screenshot-upload">
- <label for="screenshot-upload" class="upload-btn">选择文件</label>
- <div *ngIf="exceptionScreenshotUrl" class="screenshot-preview">
- <img [src]="exceptionScreenshotUrl" alt="异常截图">
- <button (click)="clearExceptionScreenshot()" class="clear-screenshot-btn">×</button>
- </div>
- </div>
- <button
- (click)="submitExceptionFeedback()"
- [disabled]="!exceptionDescription.trim()"
- class="submit-feedback-btn"
- >
- 提交反馈并联系技术支持
- </button>
- </div>
- <!-- 历史反馈记录 -->
- <div class="exception-history" *ngIf="exceptionHistories.length > 0">
- <h4>历史反馈记录</h4>
- <div class="history-list">
- <div *ngFor="let history of exceptionHistories" class="history-item">
- <div class="history-header">
- <span class="history-type">{{ getExceptionTypeText(history.type) }}</span>
- <span class="history-time">{{ formatDate(history.submitTime) }}</span>
- </div>
- <div class="history-description">{{ history.description }}</div>
- <div class="history-status" [class.status-pending]="history.status === '待处理'" [class.status-processing]="history.status === '处理中'" [class.status-resolved]="history.status === '已解决'">
- {{ history.status }} - {{ history.response || '暂无回复' }}
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <div class="progress-bar-container">
- <div class="progress-bar">
- <div class="progress-fill" [style.width.percent]="renderProgress.completionRate"></div>
- </div>
- <div class="progress-percentage">{{ renderProgress.completionRate }}%</div>
- </div>
-
- <div class="progress-details">
- <div class="progress-info">
- <span class="info-label">预计剩余时间</span>
- <span class="info-value">{{ renderProgress.estimatedTimeRemaining }} 小时</span>
- </div>
- <div class="progress-info">
- <span class="info-label">当前状态</span>
- <span class="info-value">{{ renderProgress.status }}</span>
- </div>
- </div>
- </div>
- </div>
- <!-- 客户反馈和设计师变更记录 -->
- <div class="additional-info-section">
- <div class="feedback-card card">
- <h2>客户反馈</h2>
- <div *ngIf="feedbacks.length === 0" class="empty-state">
- <div class="empty-icon">📭</div>
- <span>暂无客户反馈</span>
- </div>
- <div *ngFor="let feedback of feedbacks" class="feedback-item">
- <div class="feedback-header">
- <div class="feedback-meta">
- <span class="feedback-type">{{ feedback.isSatisfied ? '满意反馈' : '不满意反馈' }}</span>
- <span *ngIf="getFeedbackTag(feedback)" class="feedback-tag">{{ getFeedbackTag(feedback) }}</span>
- </div>
- <div class="feedback-date">{{ feedback.createdAt | date:'yyyy-MM-dd HH:mm' }}</div>
- </div>
- <div class="feedback-content">
- <div class="feedback-status"><span class="status-label">状态:</span> <span class="status-value">{{ feedback.status }}</span></div>
- <!-- 反馈倒计时 -->
- <div *ngIf="feedback.status === '待处理' && feedbackTimeoutCountdown > 0" class="feedback-countdown">
- <span class="countdown-icon">⏱️</span>
- <span>响应倒计时: {{ formatCountdown(feedbackTimeoutCountdown) }}</span>
- </div>
- <div class="feedback-details">
- <div class="detail-item">
- <span class="detail-label">修改部位:</span>
- <span class="detail-value">{{ feedback.problemLocation || '-' }}</span>
- </div>
- <div class="detail-item">
- <span class="detail-label">期望效果:</span>
- <span class="detail-value">{{ feedback.expectedEffect || '-' }}</span>
- </div>
- <div class="detail-item">
- <span class="detail-label">参考案例:</span>
- <span class="detail-value">{{ feedback.referenceCase || '-' }}</span>
- </div>
- </div>
- </div>
- <div class="feedback-actions">
- <button (click)="updateFeedbackStatus(feedback.id, '处理中')" [disabled]="feedback.status === '处理中' || feedback.status === '已解决'" class="secondary-btn">
- 标记为处理中
- </button>
- <button (click)="updateFeedbackStatus(feedback.id, '已解决')" [disabled]="feedback.status === '已解决'" class="primary-btn">
- 标记为已解决
- </button>
- </div>
- </div>
- </div>
- <div class="designer-change-card card">
- <h2>设计师变更记录</h2>
- <div class="change-actions">
- <button (click)="initiateDesignerChange('技能不匹配')" class="secondary-btn">发起变更 - 技能不匹配</button>
- <button (click)="initiateDesignerChange('休假')" class="secondary-btn">发起变更 - 休假</button>
- </div>
- <div *ngIf="designerChanges.length === 0" class="empty-state">
- <div class="empty-icon">👤</div>
- <span>暂无设计师变更记录</span>
- </div>
- <div *ngFor="let change of designerChanges" class="change-item">
- <div class="change-header">
- <div class="change-time">{{ change.changeTime | date:'yyyy-MM-dd' }}</div>
- <button *ngIf="!change.acceptanceTime" (click)="acceptDesignerChange(change.id)" class="accept-change-btn primary-btn">
- 确认承接
- </button>
- </div>
- <div class="change-details">
- <div class="designer-change-info">
- <div class="designer-change">
- <span class="designer-label">原设计师:</span>
- <span class="designer-name">{{ change.oldDesignerName }}</span>
- </div>
- <div class="designer-change">
- <span class="designer-label">新设计师:</span>
- <span class="designer-name">{{ change.newDesignerName }}</span>
- </div>
- </div>
- <div class="workload-info">
- <span>已完成工作量: <strong>{{ change.completedWorkload }}%</strong></span>
- </div>
- <div class="achievements">
- <h4>历史阶段成果:</h4>
- <ul>
- <li *ngFor="let achievement of change.historicalAchievements">{{ achievement }}</li>
- </ul>
- </div>
- <div *ngIf="change.acceptanceTime" class="change-status">
- 承接确认时间: {{ change.acceptanceTime | date:'yyyy-MM-dd' }}
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 项目成员标签页 -->
- <div *ngIf="isActiveTab('members')" class="members-tab-content">
- <div class="project-members-card card">
- <h2>项目团队成员</h2>
- <div class="members-grid">
- <div *ngFor="let member of projectMembers" class="member-card">
- <div class="member-avatar">
- <div class="avatar-placeholder">{{ member.avatar }}</div>
- </div>
- <div class="member-info">
- <div class="member-name">{{ member.name }}</div>
- <div class="member-role">{{ member.role }}</div>
- <div class="member-skills">
- <span *ngIf="member.skillMatch >= 90" class="skill-badge">技能匹配良好</span>
- <span *ngIf="member.progress >= 80" class="skill-badge">进度领先</span>
- </div>
- </div>
- <div class="member-actions">
- <button class="message-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
- </svg>
- </button>
- </div>
- </div>
- </div>
- </div>
-
- <div class="members-timeline-card card">
- <h2>团队协作时间轴</h2>
- <div class="timeline-entries">
- <div *ngFor="let event of timelineEvents" class="timeline-entry">
- <div class="timeline-dot"></div>
- <div class="timeline-content">
- <div class="timeline-header">
- <span class="timeline-author">{{ getEventAuthor(event.action) }}</span>
- <span class="timeline-time">{{ event.time }}</span>
- </div>
- <div class="timeline-text">{{ event.description }}</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 项目文件标签页 -->
- <div *ngIf="isActiveTab('files')" class="files-tab-content">
- <div class="file-actions">
- <button class="upload-btn primary-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
- <polyline points="17 8 12 3 7 8"></polyline>
- <line x1="12" y1="3" x2="12" y2="15"></line>
- </svg>
- <span>上传文件</span>
- </button>
- <div class="file-filter">
- <select class="file-filter-select">
- <option value="all">全部文件</option>
- <option value="images">图片</option>
- <option value="documents">文档</option>
- <option value="models">模型文件</option>
- </select>
- </div>
- </div>
-
- <div class="files-grid">
- <div *ngFor="let file of projectFiles" class="file-card">
- <div class="file-icon">
- <svg *ngIf="file.type.includes('pdf')" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#EA4335" stroke-width="2">
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
- <polyline points="14 2 14 8 20 8"></polyline>
- <line x1="16" y1="13" x2="8" y2="13"></line>
- <line x1="16" y1="17" x2="8" y2="17"></line>
- <polyline points="10 9 9 9 8 9"></polyline>
- </svg>
- <svg *ngIf="file.type.includes('jpg') || file.type.includes('png')" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#34A853" stroke-width="2">
- <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
- <circle cx="8.5" cy="8.5" r="1.5"></circle>
- <polyline points="21 15 16 10 5 21"></polyline>
- </svg>
- <svg *ngIf="file.type.includes('docx') || file.type.includes('doc')" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#4285F4" stroke-width="2">
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
- <polyline points="14 2 14 8 20 8"></polyline>
- <line x1="16" y1="13" x2="8" y2="13"></line>
- <line x1="16" y1="17" x2="8" y2="17"></line>
- <polyline points="10 9 9 9 8 9"></polyline>
- </svg>
- <svg *ngIf="file.type.includes('rar') || file.type.includes('zip')" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#FBBC05" stroke-width="2">
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
- <polyline points="14 2 14 8 20 8"></polyline>
- <line x1="16" y1="13" x2="8" y2="13"></line>
- <line x1="16" y1="17" x2="8" y2="17"></line>
- <polyline points="10 9 9 9 8 9"></polyline>
- </svg>
- <svg *ngIf="file.type.includes('max') || file.type.includes('obj')" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#9C27B0" stroke-width="2">
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
- <polyline points="14 2 14 8 20 8"></polyline>
- <line x1="16" y1="13" x2="8" y2="13"></line>
- <line x1="16" y1="17" x2="8" y2="17"></line>
- <polyline points="10 9 9 9 8 9"></polyline>
- </svg>
- </div>
- <div class="file-info">
- <div class="file-name">{{ file.name }}</div>
- <div class="file-meta">
- <span class="file-size">{{ file.size }}</span>
- <span class="file-date">{{ file.date }}</span>
- </div>
- </div>
- <button class="file-action-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <circle cx="12" cy="12" r="1"></circle>
- <circle cx="19" cy="12" r="1"></circle>
- <circle cx="5" cy="12" r="1"></circle>
- </svg>
- </button>
- </div>
- <div class="file-icon">
- <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#FBBC05" stroke-width="2">
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
- <polyline points="14 2 14 8 20 8"></polyline>
- <line x1="16" y1="13" x2="8" y2="13"></line>
- <line x1="16" y1="17" x2="8" y2="17"></line>
- <polyline points="10 9 9 9 8 9"></polyline>
- </svg>
- </div>
- <div class="file-info">
- <div class="file-name">色彩方案.xlsx</div>
- <div class="file-meta">
- <span class="file-size">0.9MB</span>
- <span class="file-date">2025-09-04</span>
- </div>
- </div>
- <button class="file-action-btn">
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
- <circle cx="12" cy="12" r="1"></circle>
- <circle cx="19" cy="12" r="1"></circle>
- <circle cx="5" cy="12" r="1"></circle>
- </svg>
- </button>
- </div>
- </div>
-
- <div class="file-storage-info">
- <div class="storage-bar">
- <div class="storage-used" style="width: 45%"></div>
- </div>
- <div class="storage-text">
- <span>已使用 450MB / 1GB</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 分阶段结算记录卡片 -->
- <div class="settlement-card card">
- <h2>分阶段结算记录</h2>
- <div *ngIf="settlements.length === 0" class="empty-state">
- <div class="empty-icon">💰</div>
- <span>暂无结算记录</span>
- </div>
- <div *ngIf="settlements.length > 0" class="settlement-table">
- <table>
- <thead>
- <tr>
- <th>阶段</th>
- <th>比例</th>
- <th>金额(元)</th>
- <th>状态</th>
- <th>完成时间</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let settlement of settlements">
- <td>{{ settlement.stage }}</td>
- <td>{{ settlement.percentage }}%</td>
- <td>{{ settlement.amount }}</td>
- <td><span class="status-badge" [class.status-pending]="settlement.status === '待结算'" [class.status-settled]="settlement.status === '已结算'">{{ settlement.status }}</span></td>
- <td>{{ settlement.completionTime | date:'yyyy-MM-dd' }}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
|