| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef, ViewEncapsulation } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { FormsModule } from '@angular/forms';
- import { RevisionType, RevisionTask, RevisionTaskService } from '../../../../app/pages/services/revision-task.service';
- interface SpaceOption {
- id: string;
- name: string;
- selected: boolean;
- }
- @Component({
- selector: 'app-revision-task-modal',
- standalone: true,
- imports: [CommonModule, FormsModule],
- templateUrl: './revision-task-modal.component.html',
- styleUrls: ['./revision-task-modal.component.scss'],
- styles: [`
- /* 🔥 响应式设计:网页端保持原始大小,企业微信端使用紧凑布局 */
-
- /* 💻 窄屏适配(<= 600px)- 企业微信侧边栏 */
- @media (max-width: 600px) {
- /* 模态框容器 */
- app-revision-task-modal .modal-container {
- width: 95vw !important;
- max-width: 95vw !important;
- max-height: 85vh !important;
- overflow-y: auto !important;
- }
-
- /* 标题 */
- app-revision-task-modal .modal-header h3 {
- font-size: 14px !important;
- }
-
- /* 表单区块 */
- app-revision-task-modal .form-section {
- margin-bottom: 16px !important;
- }
-
- /* 标签 */
- app-revision-task-modal .section-label {
- font-size: 11px !important;
- font-weight: 700 !important;
- margin-bottom: 6px !important;
- }
-
- /* 任务类型 */
- app-revision-task-modal .task-type-options {
- gap: 8px !important;
- }
-
- app-revision-task-modal .task-type-option {
- padding: 10px !important;
- }
-
- app-revision-task-modal .task-type-option h4 {
- font-size: 13px !important;
- margin-bottom: 2px !important;
- }
-
- app-revision-task-modal .task-type-option p {
- font-size: 10px !important;
- }
-
- /* 🔥 空间选择器 - 单列 */
- app-revision-task-modal .space-selector {
- display: grid !important;
- grid-template-columns: 1fr !important;
- gap: 6px !important;
- padding: 8px !important;
- max-height: 180px !important;
- overflow-y: auto !important;
- }
-
- app-revision-task-modal .space-item {
- display: flex !important;
- align-items: center !important;
- gap: 8px !important;
- padding: 8px 10px !important;
- min-height: 36px !important;
- }
-
- app-revision-task-modal .space-item input[type="checkbox"] {
- flex-shrink: 0 !important;
- width: 14px !important;
- height: 14px !important;
- }
-
- app-revision-task-modal .space-item span {
- flex: 1 !important;
- font-size: 12px !important;
- font-weight: 600 !important;
- white-space: normal !important;
- overflow: visible !important;
- word-wrap: break-word !important;
- }
-
- app-revision-task-modal .toggle-all-btn {
- font-size: 11px !important;
- padding: 4px 10px !important;
- }
-
- app-revision-task-modal .selected-count {
- font-size: 10px !important;
- }
-
- /* 🔥 时间选择器 - 单列 */
- app-revision-task-modal .time-selector {
- display: grid !important;
- grid-template-columns: 1fr !important;
- gap: 6px !important;
- }
-
- app-revision-task-modal .time-option {
- padding: 10px 12px !important;
- min-height: 36px !important;
- font-size: 12px !important;
- }
-
- app-revision-task-modal .time-option input[type="radio"] {
- width: 14px !important;
- height: 14px !important;
- }
-
- /* 描述框 */
- app-revision-task-modal textarea {
- min-height: 80px !important;
- font-size: 12px !important;
- padding: 8px !important;
- }
-
- /* 其他 */
- app-revision-task-modal .char-count {
- font-size: 10px !important;
- }
-
- app-revision-task-modal .info-box {
- padding: 8px !important;
- font-size: 10px !important;
- }
-
- app-revision-task-modal .modal-actions button {
- padding: 10px 20px !important;
- font-size: 13px !important;
- }
- }
- `],
- changeDetection: ChangeDetectionStrategy.OnPush,
- encapsulation: ViewEncapsulation.None
- })
- export class RevisionTaskModalComponent {
- @Input() visible: boolean = false;
- @Input() projectId: string = '';
- @Input() availableSpaces: SpaceOption[] = [];
- @Input() currentUser: any = null;
-
- @Output() close = new EventEmitter<void>();
- @Output() created = new EventEmitter<string>();
-
- // 表单数据
- taskType: RevisionType = 'major';
- selectedSpaces: SpaceOption[] = [];
- estimatedDays: string = '2-3天';
- customDays: number = 3;
- description: string = '';
-
- // 预设时间选项
- timeOptions = [
- { value: '2-3天', label: '2-3天' },
- { value: '3-5天', label: '3-5天' },
- { value: '5-7天', label: '5-7天' },
- { value: 'custom', label: '自定义' }
- ];
-
- submitting: boolean = false;
-
- constructor(
- private revisionTaskService: RevisionTaskService,
- private cdr: ChangeDetectorRef
- ) {}
-
- ngOnChanges(): void {
- if (this.visible) {
- // 🔍 调试:输出空间数据
- console.log('📋 [改图任务] 可用空间列表:', this.availableSpaces);
- console.log('📋 [改图任务] 空间数量:', this.availableSpaces.length);
- if (this.availableSpaces.length > 0) {
- console.log('📋 [改图任务] 第一个空间:', this.availableSpaces[0]);
- }
-
- // 重置表单
- this.resetForm();
- }
- }
-
- /**
- * 切换空间选择
- */
- toggleSpace(space: SpaceOption): void {
- space.selected = !space.selected;
- this.updateSelectedSpaces();
- this.cdr.markForCheck();
- }
-
- /**
- * 全选/取消全选
- */
- toggleAllSpaces(): void {
- const allSelected = this.selectedSpaces.length === this.availableSpaces.length;
- this.availableSpaces.forEach(space => {
- space.selected = !allSelected;
- });
- this.updateSelectedSpaces();
- this.cdr.markForCheck();
- }
-
- /**
- * 更新已选空间列表
- */
- private updateSelectedSpaces(): void {
- this.selectedSpaces = this.availableSpaces.filter(s => s.selected);
- }
-
- /**
- * 切换工单类型
- */
- onTypeChange(): void {
- // 小修改默认不需要选择空间和时间
- if (this.taskType === 'minor') {
- this.availableSpaces.forEach(s => s.selected = false);
- this.updateSelectedSpaces();
- }
- this.cdr.markForCheck();
- }
-
- /**
- * 检查表单是否有效
- */
- isFormValid(): boolean {
- if (!this.description.trim()) return false;
-
- if (this.taskType === 'major') {
- if (this.selectedSpaces.length === 0) return false;
- if (this.estimatedDays === 'custom' && (!this.customDays || this.customDays < 1)) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * 提交创建工单
- */
- async submit(): Promise<void> {
- if (!this.isFormValid() || this.submitting) return;
-
- this.submitting = true;
- this.cdr.markForCheck();
-
- try {
- const taskData: Omit<RevisionTask, 'id' | 'createdAt'> = {
- projectId: this.projectId,
- type: this.taskType,
- spaceIds: this.selectedSpaces.map(s => s.id),
- spaceNames: this.selectedSpaces.map(s => s.name),
- estimatedDays: this.estimatedDays === 'custom'
- ? `${this.customDays}天`
- : this.estimatedDays,
- customDays: this.estimatedDays === 'custom' ? this.customDays : undefined,
- description: this.description.trim(),
- status: 'pending_approval',
- createdBy: this.currentUser?.id || '',
- createdByName: this.currentUser?.get('name') || '未知用户',
- createdByRole: this.currentUser?.get('role') || 'designer'
- };
-
- const taskId = await this.revisionTaskService.createRevisionTask(taskData);
-
- // 显示成功提示
- if (this.taskType === 'minor') {
- window?.fmode?.toast?.success?.('小修改已记录');
- } else {
- window?.fmode?.toast?.success?.('改图工单已创建,等待组长审批');
- }
-
- this.created.emit(taskId);
- this.closeModal();
-
- } catch (error) {
- console.error('创建工单失败:', error);
- window?.fmode?.alert?.('创建工单失败,请重试');
- } finally {
- this.submitting = false;
- this.cdr.markForCheck();
- }
- }
-
- /**
- * 关闭弹窗
- */
- closeModal(): void {
- this.close.emit();
- }
-
- /**
- * 重置表单
- */
- private resetForm(): void {
- this.taskType = 'major';
- this.availableSpaces.forEach(s => s.selected = false);
- this.selectedSpaces = [];
- this.estimatedDays = '2-3天';
- this.customDays = 3;
- this.description = '';
- this.submitting = false;
- this.cdr.markForCheck();
- }
- }
|