123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <div class="complaint-card">
- <!-- 统计数据概览 -->
- <div class="stats-overview">
- <h4>投诉处理概览</h4>
- <div class="stats-grid">
- <div class="stat-item total">
- <div class="stat-value">{{ stats().totalCount }}</div>
- <div class="stat-label">总投诉数</div>
- </div>
- <div class="stat-item pending">
- <div class="stat-value">{{ stats().pendingCount }}</div>
- <div class="stat-label">待处理</div>
- </div>
- <div class="stat-item processing">
- <div class="stat-value">{{ stats().processingCount }}</div>
- <div class="stat-label">处理中</div>
- </div>
- <div class="stat-item resolved">
- <div class="stat-value">{{ stats().resolvedCount }}</div>
- <div class="stat-label">已解决</div>
- </div>
- <div class="stat-item high-priority">
- <div class="stat-value">{{ stats().highPriorityCount }}</div>
- <div class="stat-label">高优先级</div>
- </div>
- <div class="stat-item resolution-time">
- <div class="stat-value">{{ stats().averageResolutionTime }}<span class="time-suffix">天</span></div>
- <div class="stat-label">平均解决时间</div>
- </div>
- </div>
- </div>
- <!-- 优先级统计 -->
- <div class="priority-stats">
- <h5>优先级分布</h5>
- <div class="priority-cards-grid">
- @for (priority of priorities; track priority.value) {
- <div class="priority-card" [style.border-color]="priority.color">
- <div class="priority-card-header" [style.background-color]="priority.color">
- <span class="priority-card-label">{{ priority.label }}</span>
- </div>
- <div class="priority-card-body">
- <div class="priority-card-count">{{ stats().priorityStats[priority.value] || 0 }}</div>
- <div class="priority-card-suffix">个</div>
- </div>
- </div>
- }
- </div>
- </div>
- <!-- 类型统计 -->
- <div class="type-stats">
- <h5>问题类型统计</h5>
- <div class="type-grid">
- @for (type of complaintTypes; track type.value) {
- <div class="type-item">
- <span class="type-label">{{ type.label }}</span>
- <span class="type-count">{{ stats().typeStats[type.value] || 0 }}</span>
- </div>
- }
- </div>
- </div>
- <!-- 筛选区域 -->
- <div class="filter-section">
- <div class="search-row">
- <div class="search-group">
- <label>搜索:</label>
- <input
- type="text"
- class="search-input"
- placeholder="搜索投诉内容、客户姓名..."
- [value]="searchKeyword()"
- (input)="updateSearchKeyword($event.target.value)">
- </div>
- </div>
- <div class="filter-row">
- <div class="filter-group">
- <label>状态筛选:</label>
- <div class="filter-buttons">
- <button
- class="filter-btn"
- [class.active]="statusFilter() === 'all'"
- (click)="updateStatusFilter('all')">
- 全部
- </button>
- <button
- class="filter-btn pending"
- [class.active]="statusFilter() === 'pending'"
- (click)="updateStatusFilter('pending')">
- 待处理
- </button>
- <button
- class="filter-btn processing"
- [class.active]="statusFilter() === 'processing'"
- (click)="updateStatusFilter('processing')">
- 处理中
- </button>
- <button
- class="filter-btn resolved"
- [class.active]="statusFilter() === 'resolved'"
- (click)="updateStatusFilter('resolved')">
- 已解决
- </button>
- </div>
- </div>
- </div>
-
- <div class="filter-row">
- <div class="filter-group">
- <label>优先级筛选:</label>
- <select
- class="filter-select"
- [value]="priorityFilter()"
- (change)="updatePriorityFilter($event)">
- <option value="all">全部优先级</option>
- @for (priority of priorities; track priority.value) {
- <option [value]="priority.value">{{ priority.label }}</option>
- }
- </select>
- </div>
-
- <div class="filter-group">
- <label>类型筛选:</label>
- <select
- class="filter-select"
- [value]="typeFilter()"
- (change)="updateTypeFilter($event)">
- <option value="all">全部类型</option>
- @for (type of complaintTypes; track type.value) {
- <option [value]="type.value">{{ type.label }}</option>
- }
- </select>
- </div>
- </div>
- </div>
- <!-- 投诉列表 -->
- <div class="complaints-list">
- @if (filteredComplaints() && filteredComplaints().length > 0) {
- <div class="complaints-grid">
- @for (complaint of filteredComplaints(); track complaint.id) {
- <div class="complaint-card-item" [class]="getStatusClass(complaint)" [class.overdue]="isOverdue(complaint)">
- <!-- 卡片头部 -->
- <div class="card-header">
- <div class="header-left">
- <span class="type-tag" [class]="getComplaintType(complaint)">{{ getTypeLabel(getComplaintType(complaint)) }}</span>
- <div class="priority-badge" [class]="getPriorityClass(complaint.priority || 'low')" [style.background-color]="getPriorityInfo(complaint.priority || 'low').color">
- {{ getPriorityInfo(complaint.priority || 'low').label }}优先级
- </div>
- </div>
- <div class="header-right">
- <span class="status-badge" [class]="getStatusClass(complaint)">
- {{ complaint.status }}
- </span>
- @if (isOverdue(complaint)) {
- <span class="overdue-badge">超时</span>
- }
- </div>
- </div>
-
- <!-- 卡片主体 -->
- <div class="card-body">
- @if (complaint.customerName) {
- <div class="customer-info">
- <span class="customer-label">客户:</span>
- <span class="customer-name">{{ complaint.customerName }}</span>
- </div>
- }
-
- <div class="complaint-description">
- <h4>投诉内容</h4>
- <p>{{ complaint.description }}</p>
- </div>
-
- @if (complaint.images && complaint.images.length > 0) {
- <div class="complaint-images">
- <h5>相关图片</h5>
- <div class="images-grid">
- @for (image of complaint.images; track $index) {
- <img [src]="image" [alt]="'投诉图片' + ($index + 1)" class="complaint-image">
- }
- </div>
- </div>
- }
-
- <div class="time-section">
- <div class="time-item">
- <span class="time-label">提交时间:</span>
- <span class="time-value">{{ complaint.submittedAt | date:'yyyy-MM-dd HH:mm' }}</span>
- </div>
- <div class="time-item">
- <span class="time-label">处理天数:</span>
- <span class="time-value">{{ getDaysInProgress(complaint) }} 天</span>
- </div>
- @if (complaint.resolvedAt) {
- <div class="time-item">
- <span class="time-label">解决时间:</span>
- <span class="time-value">{{ complaint.resolvedAt | date:'yyyy-MM-dd HH:mm' }}</span>
- </div>
- }
- </div>
-
- @if (complaint.handlerComment) {
- <div class="handler-section">
- <h5>处理意见</h5>
- <p class="handler-comment">{{ complaint.handlerComment }}</p>
- @if (complaint.handlerName) {
- <div class="handler-info">
- <span class="handler-label">处理人:</span>
- <span class="handler-name">{{ complaint.handlerName }}</span>
- </div>
- }
- </div>
- }
-
- @if (complaint.solution) {
- <div class="solution-section">
- <h5>解决方案</h5>
- <p class="solution-text">{{ complaint.solution }}</p>
- </div>
- }
- </div>
-
- <!-- 卡片底部操作按钮 -->
- <div class="card-footer">
- @if (complaint.status === '待处理') {
- <button class="action-btn process-btn" (click)="startProcessing(complaint)">
- <span class="btn-icon">🔧</span>
- 开始处理
- </button>
- } @else if (complaint.status === '处理中') {
- <button class="action-btn complete-btn" (click)="completeProcessing(complaint)">
- <span class="btn-icon">✅</span>
- 完成处理
- </button>
- } @else if (complaint.status === '已解决') {
- <div class="completed-status">
- <span class="completed-icon">✓</span>
- <span class="completed-text">处理完成</span>
- </div>
- }
-
- @if (complaint.status !== '已解决') {
- <button class="action-btn detail-btn" (click)="viewDetails(complaint)">
- <span class="btn-icon">👁️</span>
- 查看详情
- </button>
- }
- </div>
- </div>
- }
- </div>
- } @else {
- <div class="empty-state">
- <div class="empty-icon">📋</div>
- <div class="empty-title">暂无投诉记录</div>
- <div class="empty-description">当前没有符合筛选条件的投诉记录</div>
- </div>
- }
- </div>
- </div>
|