瀏覽代碼

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

徐福静0235668 1 天之前
父節點
當前提交
36ea49efb4
共有 40 個文件被更改,包括 148 次插入85 次删除
  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"
   },