Pārlūkot izejas kodu

chore: update Angular build configurations and dependencies, improve HTML template bindings, and refactor search input handling

徐福静0235668 11 mēneši atpakaļ
vecāks
revīzija
36ea49efb4
40 mainītis faili ar 148 papildinājumiem un 85 dzēšanām
  1. 19 9
      angular.json
  2. 1 1
      package-lock.json
  3. 3 3
      package.json
  4. 2 2
      src/app/pages/admin/api-integrations/api-dialog/api-dialog.html
  5. 1 1
      src/app/pages/admin/departments/departments.html
  6. 1 1
      src/app/pages/admin/groupchats/groupchats.html
  7. 1 1
      src/app/pages/admin/services/project.service.ts
  8. 1 0
      src/app/pages/admin/system-management/system-management.ts
  9. 5 5
      src/app/pages/customer-service/dashboard/dashboard.html
  10. 26 0
      src/app/pages/customer-service/dashboard/dashboard.ts
  11. 1 0
      src/app/pages/designer/dashboard/dashboard.ts
  12. 1 0
      src/app/pages/designer/dashboard/skill-radar/skill-radar.component.ts
  13. 1 0
      src/app/pages/designer/material-share/material-share.ts
  14. 1 0
      src/app/pages/designer/personal-board/personal-board.ts
  15. 2 2
      src/app/pages/designer/project-detail/components/order-creation/order-creation.component.html
  16. 1 0
      src/app/pages/finance/dashboard/dashboard.ts
  17. 1 0
      src/app/pages/finance/project-records/project-records.ts
  18. 1 0
      src/app/pages/finance/reconciliation/reconciliation.ts
  19. 1 1
      src/app/pages/hr/recruitment-performance/recruitment-performance.html
  20. 1 0
      src/app/pages/team-leader/dashboard/dashboard.ts
  21. 5 6
      src/app/pages/team-leader/workload-calendar/workload-calendar.html
  22. 2 2
      src/app/shared/components/auto-settlement-config/auto-settlement-config.html
  23. 1 1
      src/app/shared/components/complaint-card/complaint-card.html
  24. 7 0
      src/app/shared/components/complaint-card/complaint-card.ts
  25. 1 1
      src/app/shared/components/consultation-order-panel/consultation-order-panel.component.scss
  26. 17 17
      src/app/shared/components/requirements-confirm-card/requirements-confirm-card.html
  27. 1 1
      src/app/shared/components/settlement-card/settlement-card.html
  28. 7 0
      src/app/shared/components/settlement-card/settlement-card.ts
  29. 1 1
      src/app/shared/components/upload-success-modal/upload-success-modal.component.html
  30. 1 0
      src/app/shared/filter/filter.ts
  31. 1 0
      src/app/shared/project-card/project-card.ts
  32. 1 0
      src/app/shared/status-label/status-label.ts
  33. 3 3
      src/modules/project/pages/contact/contact.component.ts
  34. 2 2
      src/modules/project/pages/project-detail/project-detail.component.html
  35. 2 2
      src/modules/project/pages/project-detail/stages/stage-aftercare.component.ts
  36. 2 2
      src/modules/project/pages/project-detail/stages/stage-delivery.component.ts
  37. 2 2
      src/modules/project/pages/project-loader/project-loader.component.ts
  38. 3 3
      src/modules/project/services/wxwork-sdk.service.ts
  39. 17 15
      src/styles.scss
  40. 1 1
      tsconfig.json

+ 19 - 9
angular.json

@@ -15,9 +15,11 @@
       "prefix": "app",
       "architect": {
         "build": {
-          "builder": "@angular/build:application",
+          "builder": "@angular-devkit/build-angular:browser",
           "options": {
-            "browser": "src/main.ts",
+            "outputPath": "dist/yss-project",
+            "index": "src/index.html",
+            "main": "src/main.ts",
             "polyfills": [
               "zone.js"
             ],
@@ -26,12 +28,13 @@
             "assets": [
               {
                 "glob": "**/*",
-                "input": "public"
+                "input": "public",
+                "output": "/"
               },
               {
                 "glob": "**/*.svg",
                 "input": "node_modules/ionicons/dist/ionicons/svg",
-                "output": "./svg"
+                "output": "/svg"
               }
             ],
             "styles": [
@@ -97,7 +100,13 @@
               "jsqr",
               "dhtmlx-gantt",
               "@ctrl/ngx-codemirror",
-              "node_modules/wangeditor/release/wangEditor.js"
+              "node_modules/wangeditor/release/wangEditor.js",
+              "camelcase",
+              "decamelize",
+              "p-retry",
+              "crypto-js",
+              "qiniu-js",
+              "semver"
             ]
           },
           "configurations": {
@@ -131,7 +140,7 @@
           "defaultConfiguration": "production"
         },
         "serve": {
-          "builder": "@angular/build:dev-server",
+          "builder": "@angular-devkit/build-angular:dev-server",
           "configurations": {
             "production": {
               "buildTarget": "yss-project:build:production"
@@ -143,10 +152,10 @@
           "defaultConfiguration": "development"
         },
         "extract-i18n": {
-          "builder": "@angular/build:extract-i18n"
+          "builder": "@angular-devkit/build-angular:extract-i18n"
         },
         "test": {
-          "builder": "@angular/build:karma",
+          "builder": "@angular-devkit/build-angular:karma",
           "options": {
             "polyfills": [
               "zone.js",
@@ -157,7 +166,8 @@
             "assets": [
               {
                 "glob": "**/*",
-                "input": "public"
+                "input": "public",
+                "output": "/"
               }
             ],
             "styles": [

+ 1 - 1
package-lock.json

@@ -83,7 +83,7 @@
         "rxjs": "~7.8.0",
         "spark-md5": "^3.0.2",
         "swiper": "^11.2.10",
-        "tslib": "^2.3.0",
+        "tslib": "^2.8.1",
         "uuid": "^11.1.0",
         "zone.js": "~0.14.0"
       },

+ 3 - 3
package.json

@@ -96,19 +96,19 @@
     "rxjs": "~7.8.0",
     "spark-md5": "^3.0.2",
     "swiper": "^11.2.10",
-    "tslib": "^2.3.0",
+    "tslib": "^2.8.1",
     "uuid": "^11.1.0",
     "zone.js": "~0.14.0"
   },
   "devDependencies": {
     "@angular-devkit/build-angular": "^17.3.0",
-    "@angular/cli": "^17.3.0",
-    "@angular/compiler-cli": "^17.3.0",
     "@angular-eslint/builder": "^17.5.3",
     "@angular-eslint/eslint-plugin": "^17.5.3",
     "@angular-eslint/eslint-plugin-template": "^17.5.3",
     "@angular-eslint/schematics": "^17.5.3",
     "@angular-eslint/template-parser": "^17.5.3",
+    "@angular/cli": "^17.3.0",
+    "@angular/compiler-cli": "^17.3.0",
     "@types/jasmine": "~5.1.0",
     "@types/qrcode": "^1.5.5",
     "@typescript-eslint/eslint-plugin": "^7.18.0",

+ 2 - 2
src/app/pages/admin/api-integrations/api-dialog/api-dialog.html

@@ -122,14 +122,14 @@
                 <mat-label>配置键</mat-label>
                 <input matInput type="text" [(ngModel)]="configKeys[i]" 
                        placeholder="例如:apiKey">
-                <mat-error *ngIf="errors[`config_key_${i}`]">{{ errors[`config_key_${i}`] }}</mat-error>
+                <mat-error *ngIf="errors['config_key_' + i]">{{ errors['config_key_' + i] }}</mat-error>
               </mat-form-field>
               
               <mat-form-field appearance="outline" class="value-field">
                 <mat-label>配置值</mat-label>
                 <textarea matInput [(ngModel)]="configValues[i]" 
                           placeholder="例如:abcdef123456" rows="2"></textarea>
-                <mat-error *ngIf="errors[`config_value_${i}`]">{{ errors[`config_value_${i}`] }}</mat-error>
+                <mat-error *ngIf="errors['config_value_' + i]">{{ errors['config_value_' + i] }}</mat-error>
               </mat-form-field>
             </div>
           </div>

+ 1 - 1
src/app/pages/admin/departments/departments.html

@@ -133,7 +133,7 @@
           </div>
           <div class="detail-item">
             <label>组长</label>
-            <div class="detail-value">{{ currentDepartment.leader?.get("name") }}</div>
+            <div class="detail-value">{{ currentDepartment.leader.get("name") }}</div>
           </div>
           <div class="detail-item">
             <label>成员数</label>

+ 1 - 1
src/app/pages/admin/groupchats/groupchats.html

@@ -44,7 +44,7 @@
           <td><code>{{ group.chat_id }}</code></td>
           <td>
             <span *ngIf="group.project" class="project-link" [routerLink]="['/admin/project-detail', group.project.id]" title="点击查看项目详情">
-              {{ group.project?.get("title") }}
+              {{ group.project.get("title") }}
             </span>
             <span *ngIf="!group.project" class="no-project">
               未关联

+ 1 - 1
src/app/pages/admin/services/project.service.ts

@@ -190,7 +190,7 @@ export class ProjectService {
       objectIds.map(id => this.getProject(id))
     );
 
-    const validProjects = projects.filter(p => p !== null) as FmodeObject[];
+    const validProjects = projects.filter((p): p is FmodeObject => p !== null);
     if (validProjects.length === 0) {
       return 0;
     }

+ 1 - 0
src/app/pages/admin/system-management/system-management.ts

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
 
 @Component({
   selector: 'app-system-management',
+  standalone: true,
   imports: [],
   templateUrl: './system-management.html',
   styleUrl: './system-management.scss'

+ 5 - 5
src/app/pages/customer-service/dashboard/dashboard.html

@@ -551,7 +551,7 @@
         <input 
           type="text" 
           [value]="searchTerm()"
-          (input)="searchTerm.set($event.target.value)"
+          (input)="searchTerm.set($any($event.target).value)"
           placeholder="搜索动态..." 
           class="search-input"
         />
@@ -578,18 +578,18 @@
           </svg>
         </div>
         <div class="update-content">
-          @if ('name' in update && update.name && 'status' in update && update.status) {
+          @if (isProjectUpdate(update) && update.name && update.status) {
           <div class="update-title">
             项目 <strong>{{ update.name }}</strong> 状态更新为 {{ update.status }}
           </div>
           }
-          @if ('content' in update) {
+          @if (hasContent(update)) {
           <div class="update-title">
             <strong>{{ getCustomerName(update) }}</strong> 提交了反馈
           </div>
           }
-          @if ('content' in update && update.content) {
-          <p class="update-text">{{ update.content }}</p>
+          @if (hasContent(update) && getUpdateContent(update)) {
+          <p class="update-text">{{ getUpdateContent(update) }}</p>
           }
           <div class="update-meta">
             <span class="update-time">{{ getFormattedDate(update) }}</span>

+ 26 - 0
src/app/pages/customer-service/dashboard/dashboard.ts

@@ -658,6 +658,32 @@ getUpdateStatus(update: Project | CustomerFeedback): string {
   return '已更新';
 }
 
+// 检查是否是项目更新
+isProjectUpdate(update: Project | CustomerFeedback): update is Project {
+  return 'name' in update && 'status' in update;
+}
+
+// 检查是否有内容字段
+hasContent(update: Project | CustomerFeedback): boolean {
+  return 'content' in update;
+}
+
+// 获取更新内容
+getUpdateContent(update: Project | CustomerFeedback): string {
+  if ('content' in update) {
+    return (update as CustomerFeedback).content;
+  }
+  return '';
+}
+
+// 处理搜索输入事件
+onSearchInput(event: Event): void {
+  const target = event.target as HTMLInputElement;
+  if (target) {
+    this.searchTerm.set(target.value);
+  }
+}
+
   // 添加getTaskStatus方法的正确实现
   getTaskStatus(task: Task): string {
     if (!task) return '未知状态';

+ 1 - 0
src/app/pages/designer/dashboard/dashboard.ts

@@ -25,6 +25,7 @@ interface ProjectTimelineItem {
 
 @Component({
   selector: 'app-dashboard',
+  standalone: true,
   imports: [CommonModule, RouterModule, SkillRadarComponent, PersonalBoard],
   templateUrl: './dashboard.html',
   styleUrl: './dashboard.scss'

+ 1 - 0
src/app/pages/designer/dashboard/skill-radar/skill-radar.component.ts

@@ -17,6 +17,7 @@ interface SkillAnalysisItem {
 
 @Component({
   selector: 'app-skill-radar',
+  standalone: true,
   imports: [CommonModule],
   templateUrl: './skill-radar.component.html',
   styleUrl: './skill-radar.component.scss'

+ 1 - 0
src/app/pages/designer/material-share/material-share.ts

@@ -20,6 +20,7 @@ interface MaterialItem {
 
 @Component({
   selector: 'app-material-share',
+  standalone: true,
   imports: [CommonModule, FormsModule],
   templateUrl: './material-share.html',
   styleUrl: './material-share.scss'

+ 1 - 0
src/app/pages/designer/personal-board/personal-board.ts

@@ -12,6 +12,7 @@ import {
 
 @Component({
   selector: 'app-personal-board',
+  standalone: true,
   imports: [CommonModule, RouterModule],
   templateUrl: './personal-board.html',
   styleUrl: './personal-board.scss'

+ 2 - 2
src/app/pages/designer/project-detail/components/order-creation/order-creation.component.html

@@ -143,7 +143,7 @@
             <button type="button" class="btn-secondary" (click)="addSpaceType()">添加空间类型</button>
           </div>
           <div class="config-list">
-            @for (space of spaceTypeConfig(); track $index; let i = $index) {
+            @for (space of spaceTypeConfig(); let i = $index; track i) {
               <div class="config-item">
                 <div class="config-fields">
                   <input type="text" [(ngModel)]="space.type" placeholder="空间类型" class="field-input">
@@ -163,7 +163,7 @@
             <button type="button" class="btn-secondary" (click)="addStyleLevel()">添加风格等级</button>
           </div>
           <div class="config-list">
-            @for (style of styleLevelConfig(); track $index; let i = $index) {
+            @for (style of styleLevelConfig(); let i = $index; track i) {
               <div class="config-item">
                 <div class="config-fields">
                   <input type="text" [(ngModel)]="style.level" placeholder="等级代码" class="field-input">

+ 1 - 0
src/app/pages/finance/dashboard/dashboard.ts

@@ -44,6 +44,7 @@ interface DesignerEfficiency {
 
 @Component({
   selector: 'app-dashboard',
+  standalone: true,
   imports: [CommonModule, RouterModule],
   templateUrl: './dashboard.html',
   styleUrl: './dashboard.scss'

+ 1 - 0
src/app/pages/finance/project-records/project-records.ts

@@ -50,6 +50,7 @@ export interface HourlyRateConfig {
 
 @Component({
   selector: 'app-project-records',
+  standalone: true,
   imports: [CommonModule, ReactiveFormsModule, RouterModule],
   templateUrl: './project-records.html',
   styleUrls: ['./project-records.scss']

+ 1 - 0
src/app/pages/finance/reconciliation/reconciliation.ts

@@ -51,6 +51,7 @@ export interface ReconciliationRecord {
 
 @Component({
   selector: 'app-reconciliation',
+  standalone: true,
   imports: [CommonModule, ReactiveFormsModule, FormsModule, RouterModule],
   templateUrl: './reconciliation.html',
   styleUrls: ['./reconciliation.scss']

+ 1 - 1
src/app/pages/hr/recruitment-performance/recruitment-performance.html

@@ -249,7 +249,7 @@
 
           <!-- 阶段时间线 -->
           <div class="stages-timeline">
-            @for (stage of recruitmentStages(); track $index; let i = $index) {
+            @for (stage of recruitmentStages(); let i = $index; track i) {
               <div class="timeline-item" 
                    [class]="getStageStatusClass(stage, i)"
                    (click)="onStageClick(stage, i)">

+ 1 - 0
src/app/pages/team-leader/dashboard/dashboard.ts

@@ -74,6 +74,7 @@ interface EmployeeDetail {
 declare const echarts: any;
 @Component({
   selector: 'app-dashboard',
+  standalone: true,
   imports: [CommonModule, FormsModule, RouterModule],
   templateUrl: './dashboard.html',
   styleUrl: './dashboard.scss'

+ 5 - 6
src/app/pages/team-leader/workload-calendar/workload-calendar.html

@@ -3,9 +3,9 @@
     <h1>负载日历</h1>
     <div class="controls">
       <div class="view-switch" role="tablist" aria-label="视图切换">
-        <button [class.active]="view==='day'" (click)="switchView('day')" role="tab" aria-selected="{{view==='day'}}" title="日视图">日</button>
-        <button [class.active]="view==='week'" (click)="switchView('week')" role="tab" aria-selected="{{view==='week'}}" title="周视图">周</button>
-        <button [class.active]="view==='month'" (click)="switchView('month')" role="tab" aria-selected="{{view==='month'}}" title="月视图">月</button>
+        <button [class.active]="view==='day'" (click)="switchView('day')" role="tab" [attr.aria-selected]="view==='day'" title="日视图">日</button>
+        <button [class.active]="view==='week'" (click)="switchView('week')" role="tab" [attr.aria-selected]="view==='week'" title="周视图">周</button>
+        <button [class.active]="view==='month'" (click)="switchView('month')" role="tab" [attr.aria-selected]="view==='month'" title="月视图">月</button>
       </div>
       <div class="date-nav">
         <button (click)="navigateDate('prev')" aria-label="上一周期">‹</button>
@@ -123,8 +123,7 @@
       <div class="day-panel">
         <div class="date-label large">{{ selectedDate | date:'yyyy-MM-dd EEEE' }}</div>
         <div class="tasks">
-          @let dayTasksLocal = dayTasks;
-          @for (t of dayTasksLocal; track t.id) {
+          @for (t of dayTasks; track t.id) {
             <div class="task-row" [class.overdue]="t.isOverdue" [class.due-soon]="isDueSoon(t.deadline)" title="{{t.title}} - {{t.projectName}} / {{t.assignee}}" (click)="navigateToProject(t, $event)">
               <div class="title">{{ t.title }}</div>
               <div class="project">{{ t.projectName }}</div>
@@ -132,7 +131,7 @@
               <div class="priority" [class.high]="t.priority==='high'">{{ t.priority }}</div>
             </div>
           }
-          @if (dayTasksLocal.length === 0) {
+          @if (dayTasks.length === 0) {
             <div class="no-task">今日暂无任务</div>
           }
         </div>

+ 2 - 2
src/app/shared/components/auto-settlement-config/auto-settlement-config.html

@@ -45,7 +45,7 @@
         <!-- 条件配置 -->
         <div class="conditions-section">
           <h3>条件配置</h3>
-          @for (condition of newRule.conditions; track $index; let i = $index) {
+          @for (condition of newRule.conditions; let i = $index; track i) {
             <div class="condition-item">
               <div class="condition-header">
                 <span>条件 {{ i + 1 }}</span>
@@ -90,7 +90,7 @@
         <!-- 动作配置 -->
         <div class="actions-section">
           <h3>动作配置</h3>
-          @for (action of newRule.actions; track $index; let i = $index) {
+          @for (action of newRule.actions; let i = $index; track i) {
             <div class="action-item">
               <div class="action-header">
                 <span>动作 {{ i + 1 }}</span>

+ 1 - 1
src/app/shared/components/complaint-card/complaint-card.html

@@ -166,7 +166,7 @@
           class="search-input"
           placeholder="搜索投诉内容、客户姓名..."
           [value]="searchKeyword()"
-          (input)="updateSearchKeyword($event.target.value)">
+          (input)="onSearchInput($event)">
       </div>
     </div>
 

+ 7 - 0
src/app/shared/components/complaint-card/complaint-card.ts

@@ -406,6 +406,13 @@ export class ComplaintCardComponent {
     this.searchKeyword.set(keyword);
   }
 
+  onSearchInput(event: Event): void {
+    const target = event.target as HTMLInputElement;
+    if (target) {
+      this.updateSearchKeyword(target.value);
+    }
+  }
+
   updateSourceFilter(event: any) {
     this.sourceFilter.set(event.target.value);
   }

+ 1 - 1
src/app/shared/components/consultation-order-panel/consultation-order-panel.component.scss

@@ -450,7 +450,7 @@ $ios-spacing-xl: 32px;
         &.two-columns {
           .form-group {
             flex: 1;
-            min-width: calc(50% - #{$ios-spacing-md / 2});
+            min-width: calc(50% - (#{$ios-spacing-md} / 2));
           }
         }
 

+ 17 - 17
src/app/shared/components/requirements-confirm-card/requirements-confirm-card.html

@@ -356,12 +356,12 @@
                                 <h6>灯光分析</h6>
                                 @if (material.analysis.lightingAnalysis.ambientAnalysis) {
                                   <div class="lighting-info">
-                                    <span class="mood-tag">{{ material.analysis.lightingAnalysis.ambientAnalysis.lightingMood?.primary || '未知' }}</span>
+                                    <span class="mood-tag">{{ material.analysis.lightingAnalysis.ambientAnalysis.lightingMood.primary || '未知' }}</span>
                                     @if (material.analysis.lightingAnalysis.illuminationAnalysis) {
-                                      <span class="brightness-tag">亮度: {{ material.analysis.lightingAnalysis.illuminationAnalysis.brightness?.overall || 0 }}%</span>
+                                      <span class="brightness-tag">亮度: {{ material.analysis.lightingAnalysis.illuminationAnalysis.brightness.overall || 0 }}%</span>
                                     }
                                     @if (material.analysis.lightingAnalysis.lightSourceIdentification) {
-                                      <span class="source-tag">光源: {{ material.analysis.lightingAnalysis.lightSourceIdentification.lightingSetup?.dominantSource || '未知' }}</span>
+                                      <span class="source-tag">光源: {{ material.analysis.lightingAnalysis.lightSourceIdentification.lightingSetup.dominantSource || '未知' }}</span>
                                     }
                                   </div>
                                 }
@@ -641,9 +641,9 @@
                 <div class="scene-info">
                   <div class="info-row">
                     <span class="label">基础场景:</span>
-                    <span class="value">{{ requirementMapping?.sceneGeneration?.baseScene || '未定义' }}</span>
+                    <span class="value">{{ requirementMapping.sceneGeneration.baseScene || '未定义' }}</span>
                   </div>
-                  @if (requirementMapping?.sceneGeneration?.atmospherePreview) {
+                  @if (requirementMapping.sceneGeneration.atmospherePreview) {
                     <div class="atmosphere-preview">
                       <img [src]="requirementMapping.sceneGeneration.atmospherePreview" 
                            alt="氛围感预览图"
@@ -664,19 +664,19 @@
                     <div class="color-params">
                       <div class="param-item">
                         <span class="label">主要颜色:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.colorParams?.primaryColors?.length || 0 }} 种</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.colorParams.primaryColors.length || 0 }} 种</span>
                       </div>
                       <div class="param-item">
                         <span class="label">色彩和谐:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.colorParams ? getColorHarmonyName(requirementMapping.parameterMapping.colorParams.colorHarmony) : '未知' }}</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.colorParams ? getColorHarmonyName(requirementMapping.parameterMapping.colorParams.colorHarmony) : '未知' }}</span>
                       </div>
                       <div class="param-item">
                         <span class="label">饱和度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.colorParams?.saturation || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.colorParams.saturation || 0 }}%</span>
                       </div>
                       <div class="param-item">
                         <span class="label">亮度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.colorParams?.brightness || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.colorParams.brightness || 0 }}%</span>
                       </div>
                     </div>
                   </div>
@@ -687,19 +687,19 @@
                     <div class="space-params">
                       <div class="param-item">
                         <span class="label">布局类型:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.spaceParams?.layout ? getLayoutTypeName(requirementMapping.parameterMapping.spaceParams.layout.type) : '未知' }}</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.spaceParams.layout ? getLayoutTypeName(requirementMapping.parameterMapping.spaceParams.layout.type) : '未知' }}</span>
                       </div>
                       <div class="param-item">
                         <span class="label">空间流线:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.spaceParams?.layout ? getFlowTypeName(requirementMapping.parameterMapping.spaceParams.layout.flow) : '未知' }}</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.spaceParams.layout ? getFlowTypeName(requirementMapping.parameterMapping.spaceParams.layout.flow) : '未知' }}</span>
                       </div>
                       <div class="param-item">
                         <span class="label">家具比例:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.spaceParams?.scale?.furniture || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.spaceParams.scale.furniture || 0 }}%</span>
                       </div>
                       <div class="param-item">
                         <span class="label">开放度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.spaceParams?.scale?.openness || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.spaceParams.scale.openness || 0 }}%</span>
                       </div>
                     </div>
                   </div>
@@ -710,19 +710,19 @@
                     <div class="material-params">
                       <div class="param-item">
                         <span class="label">纹理缩放:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.textureScale || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.textureScale || 0 }}%</span>
                       </div>
                       <div class="param-item">
                         <span class="label">反射率:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.reflectivity || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.reflectivity || 0 }}%</span>
                       </div>
                       <div class="param-item">
                         <span class="label">粗糙度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.roughness || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.roughness || 0 }}%</span>
                       </div>
                       <div class="param-item">
                         <span class="label">金属度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.metallic || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.metallic || 0 }}%</span>
                       </div>
                     </div>
                   </div>

+ 1 - 1
src/app/shared/components/settlement-card/settlement-card.html

@@ -63,7 +63,7 @@
         type="text" 
         placeholder="搜索项目名称或阶段..."
         [value]="searchKeyword()"
-        (input)="updateSearchKeyword($event.target.value)">
+        (input)="onSearchInput($event)">
     </div>
     <div class="filter-buttons">
       <button 

+ 7 - 0
src/app/shared/components/settlement-card/settlement-card.ts

@@ -600,6 +600,13 @@ export class SettlementCardComponent implements OnInit {
   updateSearchKeyword(keyword: string): void {
     this.searchKeyword.set(keyword);
   }
+
+  onSearchInput(event: Event): void {
+    const target = event.target as HTMLInputElement;
+    if (target) {
+      this.updateSearchKeyword(target.value);
+    }
+  }
   
   // 计算逾期天数
   getDaysOverdue(settlement: Settlement): number {

+ 1 - 1
src/app/shared/components/upload-success-modal/upload-success-modal.component.html

@@ -232,7 +232,7 @@
                               </div>
                               <div class="info-item">
                                 <span class="label">饱和度范围:</span>
-                                <span class="value">{{ (analysisResult.enhancedAnalysis.colorWheel.saturationRange?.min || 0) }}% - {{ (analysisResult.enhancedAnalysis.colorWheel.saturationRange?.max || 100) }}%</span>
+                                <span class="value">{{ (analysisResult.enhancedAnalysis.colorWheel.saturationRange.min || 0) }}% - {{ (analysisResult.enhancedAnalysis.colorWheel.saturationRange.max || 100) }}%</span>
                               </div>
                             </div>
                           </div>

+ 1 - 0
src/app/shared/filter/filter.ts

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
 
 @Component({
   selector: 'app-filter',
+  standalone: true,
   imports: [],
   templateUrl: './filter.html',
   styleUrl: './filter.scss'

+ 1 - 0
src/app/shared/project-card/project-card.ts

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
 
 @Component({
   selector: 'app-project-card',
+  standalone: true,
   imports: [],
   templateUrl: './project-card.html',
   styleUrl: './project-card.scss'

+ 1 - 0
src/app/shared/status-label/status-label.ts

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
 
 @Component({
   selector: 'app-status-label',
+  standalone: true,
   imports: [],
   templateUrl: './status-label.html',
   styleUrl: './status-label.scss'

+ 3 - 3
src/modules/project/pages/contact/contact.component.ts

@@ -274,7 +274,7 @@ export class CustomerProfileComponent implements OnInit {
 
       // 过滤包含该客户的群聊
       const externalUserId = this.contactInfo!.get('external_userid');
-      const filteredGroups = groups.filter(g => {
+      const filteredGroups = groups.filter((g: any) => {
         const memberList = g.get('member_list') || [];
         return memberList.some((m: any) =>
           m.type === 2 && m.userid === externalUserId
@@ -283,7 +283,7 @@ export class CustomerProfileComponent implements OnInit {
 
       // 加载群聊关联的项目
       this.profile.groups = await Promise.all(
-        filteredGroups.map(async (groupChat) => {
+        filteredGroups.map(async (groupChat: any) => {
           const projectPointer = groupChat.get('project');
           let project = null;
 
@@ -334,7 +334,7 @@ export class CustomerProfileComponent implements OnInit {
 
       const communications = await query.find();
 
-      this.profile.followUpRecords = communications.map(comm => ({
+      this.profile.followUpRecords = communications.map((comm: any) => ({
         time: comm.get('createdAt'),
         type: comm.get('communicationType') || 'message',
         content: comm.get('content') || '',

+ 2 - 2
src/modules/project/pages/project-detail/project-detail.component.html

@@ -88,8 +88,8 @@
             <div class="info-text">
               <h3>{{ customer?.get('name') || '待设置' }}</h3>
               @if (customer && canViewCustomerPhone) {
-                <p>{{ customer?.get('mobile') }}</p>
-                <p class="wechat-id">微信: {{ customer?.get('data')?.wechat || customer?.get('external_userid') }}</p>
+                <p>{{ customer.get('mobile') }}</p>
+                <p class="wechat-id">微信: {{ customer.get('data')?.wechat || customer.get('external_userid') }}</p>
               } @else if (customer) {
                 <p class="info-limited">仅客服可查看联系方式</p>
               }

+ 2 - 2
src/modules/project/pages/project-detail/stages/stage-aftercare.component.ts

@@ -85,7 +85,7 @@ export class StageAftercareComponent implements OnInit {
   saving: boolean = false;
 
   // 注入上传服务
-  private uploadService = inject(NovaUploadService);
+  private uploadService: NovaUploadService = inject(NovaUploadService);
 
   constructor(
     private route: ActivatedRoute
@@ -185,7 +185,7 @@ export class StageAftercareComponent implements OnInit {
       this.uploading = true;
 
       // 使用 NovaUploadService 上传文件
-      const fileResult = await this.uploadService.upload(file);
+      const fileResult: any = await this.uploadService.upload(file);
       const url = fileResult.url;
 
       // 暂时不使用OCR,需要手动输入金额和支付方式

+ 2 - 2
src/modules/project/pages/project-detail/stages/stage-delivery.component.ts

@@ -116,7 +116,7 @@ export class StageDeliveryComponent implements OnInit {
   saving: boolean = false;
 
   // 注入上传服务
-  private uploadService = inject(NovaUploadService);
+  private uploadService: NovaUploadService = inject(NovaUploadService);
 
   constructor(
     private route: ActivatedRoute
@@ -238,7 +238,7 @@ export class StageDeliveryComponent implements OnInit {
       this.uploading = true;
 
       // 使用 NovaUploadService 上传文件
-      const fileResult = await this.uploadService.upload(file);
+      const fileResult: any = await this.uploadService.upload(file);
       const url = fileResult.url;
 
       const deliverable = this.getDeliverable(spaceName, processType);

+ 2 - 2
src/modules/project/pages/project-loader/project-loader.component.ts

@@ -246,8 +246,8 @@ export class ProjectLoaderComponent implements OnInit {
       const projectGroups = await pgQuery.find();
 
       this.historyProjects = projectGroups
-        .map(pg => pg.get('project'))
-        .filter(p => p && !p.get('isDeleted'));
+        .map((pg: any) => pg.get('project'))
+        .filter((p: any) => p && !p.get('isDeleted'));
 
       wxdebug('找到历史项目', { count: this.historyProjects.length });
     } catch (err) {

+ 3 - 3
src/modules/project/services/wxwork-sdk.service.ts

@@ -409,10 +409,10 @@ export class WxworkSDKService {
         groupName: options.groupName,
         userIds: options.userIds,
         externalUserIds: options.externalUserIds,
-        success: (data) => {
+        success: (data: any) => {
           resolve(data);
         },
-        fail: (err) => {
+        fail: (err: any) => {
           reject(err);
         }
       });
@@ -460,7 +460,7 @@ export class WxworkSDKService {
         success: () => {
           resolve();
         },
-        fail: (err) => {
+        fail: (err: any) => {
           reject(err);
         }
       });

+ 17 - 15
src/styles.scss

@@ -1,10 +1,6 @@
 
 
-// Include theming for Angular Material with `mat.theme()`.
-// This Sass mixin will define CSS variables that are used for styling Angular Material
-// components according to the Material 3 design spec.
-// Learn more about theming and how to use it for your application's
-// custom components at https://material.angular.dev/guide/theming
+// Include theming for Angular Material
 @use '@angular/material' as mat;
 
 // 导入变量
@@ -13,16 +9,22 @@
 // 自定义字体配置
 @include mat.core();
 
-html {
-  @include mat.theme((
-    color: (
-      primary: mat.$azure-palette,
-      tertiary: mat.$blue-palette,
-    ),
-    // 不指定typography配置,避免自动加载
-    density: 0,
-  ));
-}
+// 定义调色板
+$primary-palette: mat.define-palette(mat.$indigo-palette);
+$accent-palette: mat.define-palette(mat.$pink-palette, A200, A100, A400);
+$warn-palette: mat.define-palette(mat.$red-palette);
+
+// 创建主题
+$theme: mat.define-light-theme((
+  color: (
+    primary: $primary-palette,
+    accent: $accent-palette,
+    warn: $warn-palette,
+  )
+));
+
+// 应用主题
+@include mat.all-component-themes($theme);
 
 body {
   // Default the application to a light color theme. This can be changed to

+ 1 - 1
tsconfig.json

@@ -11,7 +11,7 @@
     "skipLibCheck": true,
     "isolatedModules": true,
     "experimentalDecorators": true,
-    "importHelpers": true,
+    "importHelpers": false,
     "target": "ES2022",
     "module": "preserve"
   },