Browse Source

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

徐福静0235668 11 months ago
parent
commit
36ea49efb4
40 changed files with 148 additions and 85 deletions
  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",
       "prefix": "app",
       "architect": {
       "architect": {
         "build": {
         "build": {
-          "builder": "@angular/build:application",
+          "builder": "@angular-devkit/build-angular:browser",
           "options": {
           "options": {
-            "browser": "src/main.ts",
+            "outputPath": "dist/yss-project",
+            "index": "src/index.html",
+            "main": "src/main.ts",
             "polyfills": [
             "polyfills": [
               "zone.js"
               "zone.js"
             ],
             ],
@@ -26,12 +28,13 @@
             "assets": [
             "assets": [
               {
               {
                 "glob": "**/*",
                 "glob": "**/*",
-                "input": "public"
+                "input": "public",
+                "output": "/"
               },
               },
               {
               {
                 "glob": "**/*.svg",
                 "glob": "**/*.svg",
                 "input": "node_modules/ionicons/dist/ionicons/svg",
                 "input": "node_modules/ionicons/dist/ionicons/svg",
-                "output": "./svg"
+                "output": "/svg"
               }
               }
             ],
             ],
             "styles": [
             "styles": [
@@ -97,7 +100,13 @@
               "jsqr",
               "jsqr",
               "dhtmlx-gantt",
               "dhtmlx-gantt",
               "@ctrl/ngx-codemirror",
               "@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": {
           "configurations": {
@@ -131,7 +140,7 @@
           "defaultConfiguration": "production"
           "defaultConfiguration": "production"
         },
         },
         "serve": {
         "serve": {
-          "builder": "@angular/build:dev-server",
+          "builder": "@angular-devkit/build-angular:dev-server",
           "configurations": {
           "configurations": {
             "production": {
             "production": {
               "buildTarget": "yss-project:build:production"
               "buildTarget": "yss-project:build:production"
@@ -143,10 +152,10 @@
           "defaultConfiguration": "development"
           "defaultConfiguration": "development"
         },
         },
         "extract-i18n": {
         "extract-i18n": {
-          "builder": "@angular/build:extract-i18n"
+          "builder": "@angular-devkit/build-angular:extract-i18n"
         },
         },
         "test": {
         "test": {
-          "builder": "@angular/build:karma",
+          "builder": "@angular-devkit/build-angular:karma",
           "options": {
           "options": {
             "polyfills": [
             "polyfills": [
               "zone.js",
               "zone.js",
@@ -157,7 +166,8 @@
             "assets": [
             "assets": [
               {
               {
                 "glob": "**/*",
                 "glob": "**/*",
-                "input": "public"
+                "input": "public",
+                "output": "/"
               }
               }
             ],
             ],
             "styles": [
             "styles": [

+ 1 - 1
package-lock.json

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

+ 3 - 3
package.json

@@ -96,19 +96,19 @@
     "rxjs": "~7.8.0",
     "rxjs": "~7.8.0",
     "spark-md5": "^3.0.2",
     "spark-md5": "^3.0.2",
     "swiper": "^11.2.10",
     "swiper": "^11.2.10",
-    "tslib": "^2.3.0",
+    "tslib": "^2.8.1",
     "uuid": "^11.1.0",
     "uuid": "^11.1.0",
     "zone.js": "~0.14.0"
     "zone.js": "~0.14.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@angular-devkit/build-angular": "^17.3.0",
     "@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/builder": "^17.5.3",
     "@angular-eslint/eslint-plugin": "^17.5.3",
     "@angular-eslint/eslint-plugin": "^17.5.3",
     "@angular-eslint/eslint-plugin-template": "^17.5.3",
     "@angular-eslint/eslint-plugin-template": "^17.5.3",
     "@angular-eslint/schematics": "^17.5.3",
     "@angular-eslint/schematics": "^17.5.3",
     "@angular-eslint/template-parser": "^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/jasmine": "~5.1.0",
     "@types/qrcode": "^1.5.5",
     "@types/qrcode": "^1.5.5",
     "@typescript-eslint/eslint-plugin": "^7.18.0",
     "@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>
                 <mat-label>配置键</mat-label>
                 <input matInput type="text" [(ngModel)]="configKeys[i]" 
                 <input matInput type="text" [(ngModel)]="configKeys[i]" 
                        placeholder="例如:apiKey">
                        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>
               
               
               <mat-form-field appearance="outline" class="value-field">
               <mat-form-field appearance="outline" class="value-field">
                 <mat-label>配置值</mat-label>
                 <mat-label>配置值</mat-label>
                 <textarea matInput [(ngModel)]="configValues[i]" 
                 <textarea matInput [(ngModel)]="configValues[i]" 
                           placeholder="例如:abcdef123456" rows="2"></textarea>
                           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>
               </mat-form-field>
             </div>
             </div>
           </div>
           </div>

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

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

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

@@ -44,7 +44,7 @@
           <td><code>{{ group.chat_id }}</code></td>
           <td><code>{{ group.chat_id }}</code></td>
           <td>
           <td>
             <span *ngIf="group.project" class="project-link" [routerLink]="['/admin/project-detail', group.project.id]" title="点击查看项目详情">
             <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>
             <span *ngIf="!group.project" class="no-project">
             <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))
       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) {
     if (validProjects.length === 0) {
       return 0;
       return 0;
     }
     }

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

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

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

@@ -551,7 +551,7 @@
         <input 
         <input 
           type="text" 
           type="text" 
           [value]="searchTerm()"
           [value]="searchTerm()"
-          (input)="searchTerm.set($event.target.value)"
+          (input)="searchTerm.set($any($event.target).value)"
           placeholder="搜索动态..." 
           placeholder="搜索动态..." 
           class="search-input"
           class="search-input"
         />
         />
@@ -578,18 +578,18 @@
           </svg>
           </svg>
         </div>
         </div>
         <div class="update-content">
         <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">
           <div class="update-title">
             项目 <strong>{{ update.name }}</strong> 状态更新为 {{ update.status }}
             项目 <strong>{{ update.name }}</strong> 状态更新为 {{ update.status }}
           </div>
           </div>
           }
           }
-          @if ('content' in update) {
+          @if (hasContent(update)) {
           <div class="update-title">
           <div class="update-title">
             <strong>{{ getCustomerName(update) }}</strong> 提交了反馈
             <strong>{{ getCustomerName(update) }}</strong> 提交了反馈
           </div>
           </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">
           <div class="update-meta">
             <span class="update-time">{{ getFormattedDate(update) }}</span>
             <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 '已更新';
   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方法的正确实现
   getTaskStatus(task: Task): string {
   getTaskStatus(task: Task): string {
     if (!task) return '未知状态';
     if (!task) return '未知状态';

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

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

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

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

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

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

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

@@ -12,6 +12,7 @@ import {
 
 
 @Component({
 @Component({
   selector: 'app-personal-board',
   selector: 'app-personal-board',
+  standalone: true,
   imports: [CommonModule, RouterModule],
   imports: [CommonModule, RouterModule],
   templateUrl: './personal-board.html',
   templateUrl: './personal-board.html',
   styleUrl: './personal-board.scss'
   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>
             <button type="button" class="btn-secondary" (click)="addSpaceType()">添加空间类型</button>
           </div>
           </div>
           <div class="config-list">
           <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-item">
                 <div class="config-fields">
                 <div class="config-fields">
                   <input type="text" [(ngModel)]="space.type" placeholder="空间类型" class="field-input">
                   <input type="text" [(ngModel)]="space.type" placeholder="空间类型" class="field-input">
@@ -163,7 +163,7 @@
             <button type="button" class="btn-secondary" (click)="addStyleLevel()">添加风格等级</button>
             <button type="button" class="btn-secondary" (click)="addStyleLevel()">添加风格等级</button>
           </div>
           </div>
           <div class="config-list">
           <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-item">
                 <div class="config-fields">
                 <div class="config-fields">
                   <input type="text" [(ngModel)]="style.level" placeholder="等级代码" class="field-input">
                   <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({
 @Component({
   selector: 'app-dashboard',
   selector: 'app-dashboard',
+  standalone: true,
   imports: [CommonModule, RouterModule],
   imports: [CommonModule, RouterModule],
   templateUrl: './dashboard.html',
   templateUrl: './dashboard.html',
   styleUrl: './dashboard.scss'
   styleUrl: './dashboard.scss'

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

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

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

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

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

@@ -249,7 +249,7 @@
 
 
           <!-- 阶段时间线 -->
           <!-- 阶段时间线 -->
           <div class="stages-timeline">
           <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" 
               <div class="timeline-item" 
                    [class]="getStageStatusClass(stage, i)"
                    [class]="getStageStatusClass(stage, i)"
                    (click)="onStageClick(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;
 declare const echarts: any;
 @Component({
 @Component({
   selector: 'app-dashboard',
   selector: 'app-dashboard',
+  standalone: true,
   imports: [CommonModule, FormsModule, RouterModule],
   imports: [CommonModule, FormsModule, RouterModule],
   templateUrl: './dashboard.html',
   templateUrl: './dashboard.html',
   styleUrl: './dashboard.scss'
   styleUrl: './dashboard.scss'

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

@@ -3,9 +3,9 @@
     <h1>负载日历</h1>
     <h1>负载日历</h1>
     <div class="controls">
     <div class="controls">
       <div class="view-switch" role="tablist" aria-label="视图切换">
       <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>
       <div class="date-nav">
       <div class="date-nav">
         <button (click)="navigateDate('prev')" aria-label="上一周期">‹</button>
         <button (click)="navigateDate('prev')" aria-label="上一周期">‹</button>
@@ -123,8 +123,7 @@
       <div class="day-panel">
       <div class="day-panel">
         <div class="date-label large">{{ selectedDate | date:'yyyy-MM-dd EEEE' }}</div>
         <div class="date-label large">{{ selectedDate | date:'yyyy-MM-dd EEEE' }}</div>
         <div class="tasks">
         <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="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="title">{{ t.title }}</div>
               <div class="project">{{ t.projectName }}</div>
               <div class="project">{{ t.projectName }}</div>
@@ -132,7 +131,7 @@
               <div class="priority" [class.high]="t.priority==='high'">{{ t.priority }}</div>
               <div class="priority" [class.high]="t.priority==='high'">{{ t.priority }}</div>
             </div>
             </div>
           }
           }
-          @if (dayTasksLocal.length === 0) {
+          @if (dayTasks.length === 0) {
             <div class="no-task">今日暂无任务</div>
             <div class="no-task">今日暂无任务</div>
           }
           }
         </div>
         </div>

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

@@ -45,7 +45,7 @@
         <!-- 条件配置 -->
         <!-- 条件配置 -->
         <div class="conditions-section">
         <div class="conditions-section">
           <h3>条件配置</h3>
           <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-item">
               <div class="condition-header">
               <div class="condition-header">
                 <span>条件 {{ i + 1 }}</span>
                 <span>条件 {{ i + 1 }}</span>
@@ -90,7 +90,7 @@
         <!-- 动作配置 -->
         <!-- 动作配置 -->
         <div class="actions-section">
         <div class="actions-section">
           <h3>动作配置</h3>
           <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-item">
               <div class="action-header">
               <div class="action-header">
                 <span>动作 {{ i + 1 }}</span>
                 <span>动作 {{ i + 1 }}</span>

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

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

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

@@ -406,6 +406,13 @@ export class ComplaintCardComponent {
     this.searchKeyword.set(keyword);
     this.searchKeyword.set(keyword);
   }
   }
 
 
+  onSearchInput(event: Event): void {
+    const target = event.target as HTMLInputElement;
+    if (target) {
+      this.updateSearchKeyword(target.value);
+    }
+  }
+
   updateSourceFilter(event: any) {
   updateSourceFilter(event: any) {
     this.sourceFilter.set(event.target.value);
     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 {
         &.two-columns {
           .form-group {
           .form-group {
             flex: 1;
             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>
                                 <h6>灯光分析</h6>
                                 @if (material.analysis.lightingAnalysis.ambientAnalysis) {
                                 @if (material.analysis.lightingAnalysis.ambientAnalysis) {
                                   <div class="lighting-info">
                                   <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) {
                                     @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) {
                                     @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>
                                   </div>
                                 }
                                 }
@@ -641,9 +641,9 @@
                 <div class="scene-info">
                 <div class="scene-info">
                   <div class="info-row">
                   <div class="info-row">
                     <span class="label">基础场景:</span>
                     <span class="label">基础场景:</span>
-                    <span class="value">{{ requirementMapping?.sceneGeneration?.baseScene || '未定义' }}</span>
+                    <span class="value">{{ requirementMapping.sceneGeneration.baseScene || '未定义' }}</span>
                   </div>
                   </div>
-                  @if (requirementMapping?.sceneGeneration?.atmospherePreview) {
+                  @if (requirementMapping.sceneGeneration.atmospherePreview) {
                     <div class="atmosphere-preview">
                     <div class="atmosphere-preview">
                       <img [src]="requirementMapping.sceneGeneration.atmospherePreview" 
                       <img [src]="requirementMapping.sceneGeneration.atmospherePreview" 
                            alt="氛围感预览图"
                            alt="氛围感预览图"
@@ -664,19 +664,19 @@
                     <div class="color-params">
                     <div class="color-params">
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">主要颜色:</span>
                         <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>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">色彩和谐:</span>
                         <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>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">饱和度:</span>
                         <span class="label">饱和度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.colorParams?.saturation || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.colorParams.saturation || 0 }}%</span>
                       </div>
                       </div>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">亮度:</span>
                         <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>
                     </div>
                   </div>
                   </div>
@@ -687,19 +687,19 @@
                     <div class="space-params">
                     <div class="space-params">
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">布局类型:</span>
                         <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>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">空间流线:</span>
                         <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>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">家具比例:</span>
                         <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>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">开放度:</span>
                         <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>
                     </div>
                   </div>
                   </div>
@@ -710,19 +710,19 @@
                     <div class="material-params">
                     <div class="material-params">
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">纹理缩放:</span>
                         <span class="label">纹理缩放:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.textureScale || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.textureScale || 0 }}%</span>
                       </div>
                       </div>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">反射率:</span>
                         <span class="label">反射率:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.reflectivity || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.reflectivity || 0 }}%</span>
                       </div>
                       </div>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">粗糙度:</span>
                         <span class="label">粗糙度:</span>
-                        <span class="value">{{ requirementMapping?.parameterMapping?.materialParams?.roughness || 0 }}%</span>
+                        <span class="value">{{ requirementMapping.parameterMapping.materialParams.roughness || 0 }}%</span>
                       </div>
                       </div>
                       <div class="param-item">
                       <div class="param-item">
                         <span class="label">金属度:</span>
                         <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>
                     </div>
                   </div>
                   </div>

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

@@ -63,7 +63,7 @@
         type="text" 
         type="text" 
         placeholder="搜索项目名称或阶段..."
         placeholder="搜索项目名称或阶段..."
         [value]="searchKeyword()"
         [value]="searchKeyword()"
-        (input)="updateSearchKeyword($event.target.value)">
+        (input)="onSearchInput($event)">
     </div>
     </div>
     <div class="filter-buttons">
     <div class="filter-buttons">
       <button 
       <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 {
   updateSearchKeyword(keyword: string): void {
     this.searchKeyword.set(keyword);
     this.searchKeyword.set(keyword);
   }
   }
+
+  onSearchInput(event: Event): void {
+    const target = event.target as HTMLInputElement;
+    if (target) {
+      this.updateSearchKeyword(target.value);
+    }
+  }
   
   
   // 计算逾期天数
   // 计算逾期天数
   getDaysOverdue(settlement: Settlement): number {
   getDaysOverdue(settlement: Settlement): number {

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

@@ -232,7 +232,7 @@
                               </div>
                               </div>
                               <div class="info-item">
                               <div class="info-item">
                                 <span class="label">饱和度范围:</span>
                                 <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>
                             </div>
                           </div>
                           </div>

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

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

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

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

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

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
 
 
 @Component({
 @Component({
   selector: 'app-status-label',
   selector: 'app-status-label',
+  standalone: true,
   imports: [],
   imports: [],
   templateUrl: './status-label.html',
   templateUrl: './status-label.html',
   styleUrl: './status-label.scss'
   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 externalUserId = this.contactInfo!.get('external_userid');
-      const filteredGroups = groups.filter(g => {
+      const filteredGroups = groups.filter((g: any) => {
         const memberList = g.get('member_list') || [];
         const memberList = g.get('member_list') || [];
         return memberList.some((m: any) =>
         return memberList.some((m: any) =>
           m.type === 2 && m.userid === externalUserId
           m.type === 2 && m.userid === externalUserId
@@ -283,7 +283,7 @@ export class CustomerProfileComponent implements OnInit {
 
 
       // 加载群聊关联的项目
       // 加载群聊关联的项目
       this.profile.groups = await Promise.all(
       this.profile.groups = await Promise.all(
-        filteredGroups.map(async (groupChat) => {
+        filteredGroups.map(async (groupChat: any) => {
           const projectPointer = groupChat.get('project');
           const projectPointer = groupChat.get('project');
           let project = null;
           let project = null;
 
 
@@ -334,7 +334,7 @@ export class CustomerProfileComponent implements OnInit {
 
 
       const communications = await query.find();
       const communications = await query.find();
 
 
-      this.profile.followUpRecords = communications.map(comm => ({
+      this.profile.followUpRecords = communications.map((comm: any) => ({
         time: comm.get('createdAt'),
         time: comm.get('createdAt'),
         type: comm.get('communicationType') || 'message',
         type: comm.get('communicationType') || 'message',
         content: comm.get('content') || '',
         content: comm.get('content') || '',

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

@@ -88,8 +88,8 @@
             <div class="info-text">
             <div class="info-text">
               <h3>{{ customer?.get('name') || '待设置' }}</h3>
               <h3>{{ customer?.get('name') || '待设置' }}</h3>
               @if (customer && canViewCustomerPhone) {
               @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) {
               } @else if (customer) {
                 <p class="info-limited">仅客服可查看联系方式</p>
                 <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;
   saving: boolean = false;
 
 
   // 注入上传服务
   // 注入上传服务
-  private uploadService = inject(NovaUploadService);
+  private uploadService: NovaUploadService = inject(NovaUploadService);
 
 
   constructor(
   constructor(
     private route: ActivatedRoute
     private route: ActivatedRoute
@@ -185,7 +185,7 @@ export class StageAftercareComponent implements OnInit {
       this.uploading = true;
       this.uploading = true;
 
 
       // 使用 NovaUploadService 上传文件
       // 使用 NovaUploadService 上传文件
-      const fileResult = await this.uploadService.upload(file);
+      const fileResult: any = await this.uploadService.upload(file);
       const url = fileResult.url;
       const url = fileResult.url;
 
 
       // 暂时不使用OCR,需要手动输入金额和支付方式
       // 暂时不使用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;
   saving: boolean = false;
 
 
   // 注入上传服务
   // 注入上传服务
-  private uploadService = inject(NovaUploadService);
+  private uploadService: NovaUploadService = inject(NovaUploadService);
 
 
   constructor(
   constructor(
     private route: ActivatedRoute
     private route: ActivatedRoute
@@ -238,7 +238,7 @@ export class StageDeliveryComponent implements OnInit {
       this.uploading = true;
       this.uploading = true;
 
 
       // 使用 NovaUploadService 上传文件
       // 使用 NovaUploadService 上传文件
-      const fileResult = await this.uploadService.upload(file);
+      const fileResult: any = await this.uploadService.upload(file);
       const url = fileResult.url;
       const url = fileResult.url;
 
 
       const deliverable = this.getDeliverable(spaceName, processType);
       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();
       const projectGroups = await pgQuery.find();
 
 
       this.historyProjects = projectGroups
       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 });
       wxdebug('找到历史项目', { count: this.historyProjects.length });
     } catch (err) {
     } catch (err) {

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

@@ -409,10 +409,10 @@ export class WxworkSDKService {
         groupName: options.groupName,
         groupName: options.groupName,
         userIds: options.userIds,
         userIds: options.userIds,
         externalUserIds: options.externalUserIds,
         externalUserIds: options.externalUserIds,
-        success: (data) => {
+        success: (data: any) => {
           resolve(data);
           resolve(data);
         },
         },
-        fail: (err) => {
+        fail: (err: any) => {
           reject(err);
           reject(err);
         }
         }
       });
       });
@@ -460,7 +460,7 @@ export class WxworkSDKService {
         success: () => {
         success: () => {
           resolve();
           resolve();
         },
         },
-        fail: (err) => {
+        fail: (err: any) => {
           reject(err);
           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;
 @use '@angular/material' as mat;
 
 
 // 导入变量
 // 导入变量
@@ -13,16 +9,22 @@
 // 自定义字体配置
 // 自定义字体配置
 @include mat.core();
 @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 {
 body {
   // Default the application to a light color theme. This can be changed to
   // Default the application to a light color theme. This can be changed to

+ 1 - 1
tsconfig.json

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