cjb 1 week ago
parent
commit
7c43d8bc31
43 changed files with 4216 additions and 1727 deletions
  1. 1 1
      AppScope/app.json5
  2. 1 1
      AppScope/resources/base/element/string.json
  3. 6 5
      build-profile.json5
  4. 1 0
      entry/src/main/ets/common/util/Mqtt.ets
  5. 1 1
      entry/src/main/ets/entryability/EntryAbility.ets
  6. 1 0
      entry/src/main/ets/pages/345.ets
  7. 225 0
      entry/src/main/ets/pages/Login.ets
  8. 443 1282
      entry/src/main/ets/pages/ProcessIndex.ets
  9. 171 102
      entry/src/main/ets/view/DefectRecordDialog.ets
  10. 154 0
      entry/src/main/ets/view/ProductionProcessesView.ets
  11. 233 0
      entry/src/main/ets/view/RecordItemDialog.ets
  12. 135 27
      entry/src/main/ets/view/SelectWorkOrderDialog.ets
  13. 113 0
      entry/src/main/ets/view/SwitchAndScanProductView.ets
  14. 64 70
      entry/src/main/ets/view/process/DeviceCheckView.ets
  15. 269 0
      entry/src/main/ets/view/process/ESOPView.ets
  16. 415 0
      entry/src/main/ets/view/process/ElectricScrewdriverView.ets
  17. 140 143
      entry/src/main/ets/view/process/MaterialCollectView.ets
  18. 970 0
      entry/src/main/ets/view/process/PhotoCollectView.ets
  19. 137 0
      entry/src/main/ets/view/process/RecordItemsView.ets
  20. 170 0
      entry/src/main/ets/view/process/ScanStartWorkView.ets
  21. 62 90
      entry/src/main/ets/view/process/SelfInspectView.ets
  22. 368 0
      entry/src/main/ets/view/process/WeldView.ets
  23. 79 0
      entry/src/main/ets/view/yuyinzhushou.ets
  24. 17 0
      entry/src/main/ets/viewmodel/process/EnumerationType.ets
  25. 2 1
      entry/src/main/ets/viewmodel/process/OperationComponent.ets
  26. 2 0
      entry/src/main/ets/viewmodel/process/ProcessCheck.ets
  27. 9 0
      entry/src/main/ets/viewmodel/process/RecordItem.ets
  28. 1 0
      entry/src/main/resources/base/media/check_one.svg
  29. 1 0
      entry/src/main/resources/base/media/continue.svg
  30. 1 0
      entry/src/main/resources/base/media/devices_all.svg
  31. 1 0
      entry/src/main/resources/base/media/double_left.svg
  32. 1 0
      entry/src/main/resources/base/media/double_right.svg
  33. 1 0
      entry/src/main/resources/base/media/error_upload.svg
  34. 1 0
      entry/src/main/resources/base/media/id_card_green.svg
  35. 1 0
      entry/src/main/resources/base/media/id_card_red.svg
  36. 1 0
      entry/src/main/resources/base/media/id_card_white.svg
  37. 1 0
      entry/src/main/resources/base/media/id_card_yellow.svg
  38. 1 0
      entry/src/main/resources/base/media/next_step.svg
  39. 1 0
      entry/src/main/resources/base/media/thermometer.svg
  40. 1 0
      entry/src/main/resources/base/media/tips.svg
  41. 2 1
      entry/src/main/resources/base/profile/main_pages.json
  42. 7 1
      oh-package-lock.json5
  43. 5 2
      oh-package.json5

+ 1 - 1
AppScope/app.json5

@@ -1,6 +1,6 @@
 {
   "app": {
-    "bundleName": "com.hj.hj_openharmony_process",
+    "bundleName": "com.example.rearendapp",
     "vendor": "example",
     "versionCode": 1000000,
     "versionName": "1.0.0",

+ 1 - 1
AppScope/resources/base/element/string.json

@@ -2,7 +2,7 @@
   "string": [
     {
       "name": "app_name",
-      "value": "HJ_openHarmony_process"
+      "value": "example.rearendapp"
     }
   ]
 }

+ 6 - 5
build-profile.json5

@@ -4,13 +4,13 @@
       {
         "name": "default",
         "material": {
-          "certpath": "C:/Users/hjzx2/.ohos/config/openharmony/default_HJ_openHarmony_process_fsSWWuqE3hB6JtlQ0qIVKU_RvbEwxi_gTtSv4f1zvOo=.cer",
-          "storePassword": "0000001B0B263AB22C9FFA7BEF335E866ACF26F55131F6224F9C8FAAA94E01B840AC6FF7C0DD96AB12C0AA",
+          "certpath": "C:/Users/hjzx2/.ohos/config/openharmony/default_HJ_Process_Guidance_43n5xSvJts9POVBqoJBslngnySmKyHlW5PL4t7oDtR0=.cer",
+          "storePassword": "0000001AF96AF605EE0526BCDC36EE963D246A837AB28CBF91906A0271FD53B07D8553F519EA89EF890C",
           "keyAlias": "debugKey",
-          "keyPassword": "0000001BC4AB29C44B474EB29827AEE217A8CF9E27822FBBF51573DE3E902614575ED23003EEBE727CC140",
-          "profile": "C:/Users/hjzx2/.ohos/config/openharmony/default_HJ_openHarmony_process_fsSWWuqE3hB6JtlQ0qIVKU_RvbEwxi_gTtSv4f1zvOo=.p7b",
+          "keyPassword": "0000001AD819AA498C647C37C3D54D072756624F570033AB2D5A29D515E401CDA151C681D204DCE39C46",
+          "profile": "C:/Users/hjzx2/.ohos/config/openharmony/default_HJ_Process_Guidance_43n5xSvJts9POVBqoJBslngnySmKyHlW5PL4t7oDtR0=.p7b",
           "signAlg": "SHA256withECDSA",
-          "storeFile": "C:/Users/hjzx2/.ohos/config/openharmony/default_HJ_openHarmony_process_fsSWWuqE3hB6JtlQ0qIVKU_RvbEwxi_gTtSv4f1zvOo=.p12"
+          "storeFile": "C:/Users/hjzx2/.ohos/config/openharmony/default_HJ_Process_Guidance_43n5xSvJts9POVBqoJBslngnySmKyHlW5PL4t7oDtR0=.p12"
         }
       }
     ],
@@ -21,6 +21,7 @@
         "compileSdkVersion": 10,
         "compatibleSdkVersion": 10,
         "runtimeOS": "OpenHarmony",
+        "bundleName": 'com.example.rearendapp'
       }
     ],
     "buildModeSet": [

+ 1 - 0
entry/src/main/ets/common/util/Mqtt.ets

@@ -68,6 +68,7 @@ class MqttManager {
   private async handleMessage(message: MqttMessage): Promise<void> {
     const topic = message.topic;
     const payload = message.payload.toString();
+    console.info("sssss"+payload)
     const topicCallbacks = this.callbacks.get(topic) || [];
     topicCallbacks.forEach(cb => cb(topic, payload));
     try {

+ 1 - 1
entry/src/main/ets/entryability/EntryAbility.ets

@@ -48,7 +48,7 @@ export default class EntryAbility extends UIAbility {
       windowClass.setWindowLayoutFullScreen(true)
     })
 
-    windowStage.loadContent('pages/ProcessIndex', (err) => {
+    windowStage.loadContent('pages/Login', (err) => {
       if (err.code) {
         hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
         return;

+ 1 - 0
entry/src/main/ets/pages/345.ets

@@ -0,0 +1 @@
+import { ShimoOffice } from '@shimo/sdk-client';

+ 225 - 0
entry/src/main/ets/pages/Login.ets

@@ -0,0 +1,225 @@
+import {LoginStatus} from '../viewmodel/process/EnumerationType'
+import MqttManager from '../common/util/mqtt';
+import CardReader from '../viewmodel/device/CardReader'
+import { MqttClientOptions, MqttConnectOptions } from '@ohos/mqtt';
+import CommonConstants from '../common/constants/CommonConstants';
+import router from '@ohos.router';
+@Entry
+@Component
+struct ProcessIndex {
+  //0代表初始,1代表登陆成功,2代表正在登陆,3代表登陆失败
+  @State LoginStatus: LoginStatus = LoginStatus.INITIAL
+  @StorageProp('CardReader') cardReader: CardReader = {}
+  @State isConnected: boolean = false
+  private timerId: number = 0
+  // 根据状态获取提示文字
+  getStatusText(): string {
+    switch (this.LoginStatus) {
+      case LoginStatus.INITIAL:
+        return "请使用工作卡贴近读卡器"
+      case LoginStatus.SUCCESS:
+        return "验证成功"
+      case LoginStatus.LOGGING_IN:
+        return "正在验证中..."
+      case LoginStatus.FAILED:
+        return "验证失败,请重试"
+      default:
+        return "请使用工作卡贴近读卡器"
+    }
+  }
+
+  connectMQTT = async ()=> {
+    console.info("sssssss12")
+
+    const clientOptions: MqttClientOptions = {
+      url: 'mqtt://192.168.1.3:1883',   // 替换实际IP
+      clientId: `process_client_${Date.now()}`,
+      persistenceType: 1,              // 使用英文逗号       // 建议开启自动重连
+    };
+    // MQTT连接配置
+    const connectOptions: MqttConnectOptions = {
+      cleanSession: true,
+      connectTimeout: 30,
+      keepAliveInterval: 60,
+      userName: 'optional_username',
+      password: 'optional_password'
+    };
+    try {
+      if (this.isConnected) {
+        return;
+      }
+      console.info("sssssss123")
+      MqttManager.init(clientOptions);
+      this.isConnected = await MqttManager.connect(connectOptions);
+      if (this.isConnected ) {
+        console.info('hhtest', 'MQTT connected successfully');
+        await MqttManager.subscribe(CommonConstants.mqttSubscribeTopic1);
+     //   await MqttManager.subscribe(CommonConstants.mqttSubscribeTopic3);
+        if (CommonConstants.mqttSubscribeTopic1 != CommonConstants.mqttSubscribeTopic2) {
+          await MqttManager.subscribe(CommonConstants.mqttSubscribeTopic2);
+        }
+      } else {
+        console.error('hhtest', 'MQTT connection failed');
+      }
+    } catch (err) {
+      console.error('hhtest', `MQTT error: ${JSON.stringify(err)}`);
+    }
+  }
+  private delay(ms: number): Promise<void> {
+    return new Promise((resolve) => setTimeout(resolve, ms));
+  }
+
+  timerIds(): void {
+    console.info("sssssss121")
+    this.timerId = setInterval(async (): Promise<void> => {  // 添加 async
+      const rfidCard = (this.cardReader.RfidCardNum1 || '') + (this.cardReader.RfidCardNum2 || '');
+      if (rfidCard === '') {
+        this.LoginStatus = LoginStatus.INITIAL;
+        return;
+      }
+      this.LoginStatus = LoginStatus.LOGGING_IN;
+
+      // 使用 await
+      await this.delay(1500);
+
+      if (rfidCard === '3b530bb') {
+        this.LoginStatus = LoginStatus.SUCCESS;
+        // 等待1秒显示成功状态
+        await this.delay(1000);
+        this.navigateToTarget();
+      } else {
+        this.LoginStatus = LoginStatus.FAILED;
+        // 等待1秒显示失败状态
+        await this.delay(1000);
+        this.LoginStatus = LoginStatus.INITIAL;
+      }
+    }, 3000);
+  }
+
+  private navigateToTarget(): void {
+    clearInterval(this.timerId);
+    this.timerId = 0;
+
+
+    router.pushUrl({
+      url: 'pages/ProcessIndex'
+    }).then(() => {
+      console.log('跳转成功');
+    }).catch((error: Error) => {
+      console.error('跳转失败:', error);
+    });
+  }
+
+  onPageShow(): void {
+    this.LoginStatus = LoginStatus.INITIAL
+    this.timerIds()
+  }
+aboutToAppear(): void {
+  this.connectMQTT()
+}
+  getStatusImage(): Resource {
+    switch (this.LoginStatus) {
+      case LoginStatus.INITIAL:
+        return $r("app.media.id_card_white")
+      case LoginStatus.SUCCESS:
+        return $r("app.media.id_card_green")
+      case LoginStatus.FAILED:
+        return $r("app.media.id_card_red") // 需要你有对应的红色图片
+      case LoginStatus.LOGGING_IN:
+        return $r("app.media.id_card_yellow") // 需要你有对应的黄色图片
+      default:
+        return $r("app.media.id_card_green")
+    }
+  }
+  // 根据登录状态获取边框颜色
+  getBorderColor(): string {
+    switch (this.LoginStatus) {
+      case LoginStatus.INITIAL:
+        return '#FFFFFF' // 白色 - 初始状态
+      case LoginStatus.SUCCESS:
+        return '#7ed321' // 绿色 - 登录成功
+      case LoginStatus.LOGGING_IN:
+        return '#f8e71c' // 黄色 - 正在登录
+      case LoginStatus.FAILED:
+        return '#f81c1c' // 红色 - 登录失败
+      default:
+        return '#FFFFFF' // 默认白色
+    }
+  }
+  build() {
+    Column(){
+      Column(){
+        Text("操作人员身份验证")
+          .fontSize($r('app.float.fontSize_60'))
+          .fontColor($r('app.color.FFFFFF'))
+          .fontWeight(FontWeight.Bolder)
+        Text("请完成身份验证继续")
+          .fontSize($r('app.float.fontSize_24'))
+          .fontColor($r('app.color.FFFFFF'))
+          .margin({ top:'1%'})
+          .fontWeight(FontWeight.Lighter)
+      }.height('30%')
+      .justifyContent(FlexAlign.Center)
+      Column(){
+        Image(this.getStatusImage())
+          .width($r('app.float.virtualSize_156'))
+          .height($r('app.float.virtualSize_156'))
+        Text(this.getStatusText())
+          .fontSize($r('app.float.fontSize_30'))
+          .fontColor($r('app.color.FFFFFF'))
+          .fontWeight(FontWeight.Regular)
+          .margin({ top:'1%'})
+      }.height('40%')
+      .width('30%')
+      .borderWidth('4px')
+      .justifyContent(FlexAlign.Center)
+      .borderRadius($r('app.float.fontSize_16'))
+      //green == #7ed321,yellow ==#f8e71c ,red=#f81c1c
+      .borderColor(this.getBorderColor())
+      Column(){
+        Row(){
+          Image($r('app.media.tips'))
+            .width($r('app.float.virtualSize_32'))
+            .height($r('app.float.virtualSize_32'))
+          Text("操作指引")
+            .fontSize($r('app.float.fontSize_30'))
+            .fontColor($r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Bold)
+            .margin({ top:'1%',left:'2%'})
+        }
+        .alignItems(VerticalAlign.Center)
+        .height('20%')
+        Row(){
+          Image($r("app.media.check_one"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+          Text("将你的员工卡贴近读卡器感应区")
+            .fontSize($r('app.float.fontSize_24'))
+            .fontColor($r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Lighter)
+            .margin({ top:'1%',left:'2%'})
+        }
+        .alignItems(VerticalAlign.Center)
+        Row(){
+          Image($r("app.media.check_one"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+          Text("验证成功后进入产品扫码界面")
+            .fontSize($r('app.float.fontSize_24'))
+            .fontColor($r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Lighter)
+            .margin({ top:'1%',left:'2%'})
+        }
+        .alignItems(VerticalAlign.Center)
+      }.height('35%')
+      .width('30%')
+      .margin({top:'5%'})
+      .alignItems(HorizontalAlign.Start)
+    }
+    .backgroundColor($r('app.color.000000'))
+    .width('100%')
+    .height('100%')
+  }
+}
+
+

File diff suppressed because it is too large
+ 443 - 1282
entry/src/main/ets/pages/ProcessIndex.ets


+ 171 - 102
entry/src/main/ets/view/DefectRecordDialog.ets

@@ -15,111 +15,150 @@ export struct DefectRecordDialog {
   //是否是编辑状态(需要传入的参数)
   @Prop isEdit: boolean = false
   //选择不良类型索引(需要传入的参数)
-  @Prop selectDefectType: number = -1
+  @State selectDefectType: number = -1
+  @Prop defectIndex:number
   //选择缺陷类型索引(需要传入的参数)
-  @Prop selectedDefectBug: number= -1
-  // 不良类型(数据字典)
-  @Prop defectTypes: DictValue[] = []
+  @State selectedDefectBug: number= -1
   // 不良类型对应的缺陷
-  defectBugs: ProcessBaseBug[] = []
+ // defectBugs: ProcessBaseBug[] = []
   // 不良类型对应的缺陷map(key为不良类型字典值,value为对应的缺陷)
   defectBugMap: Map<string, ProcessBaseBug[]> = new Map<string, ProcessBaseBug[]>()
   //不良类型
-  @State defectTypeOptions: Array<SelectOption> = []
+  @State defectTypeOptions: Array<SelectOption> = [
+    { value: '外观缺陷', icon: '' },
+    { value: '尺寸不良', icon: '' },
+    { value: '功能异常', icon: '' },
+    { value: '材料问题', icon: '' },
+    { value: '装配问题', icon: '' },
+    { value: '包装问题', icon: '' }
+  ]
   //缺陷类型
   @State defectBugOptions: Array<SelectOption> = []
-  // 如果是修改需要从自检页面传过来
-  @State defectRecord: ProcessDefectRecord = {}
+
+  defectRecord: ProcessDefectRecord = {}
   // 不良类型记录列表
   @Link defectRecords: ProcessDefectRecord[]
   // 备注
   @State defectRemark: string = ''
 
-  @Consume('currentUserName') currentUserName: string
-  @Consume('currentStationId') currentStationId: string
+  //@Consume('currentUserName') currentUserName: string
+  //@Consume('currentStationId') currentStationId: string
   seqNo: string = ''
   selectOperationId: string = ''
   process: ProcessInfo = {}
 
   // 刷新不良类型对应的缺陷
-  async refreshDefectBugs() {
-    let defectTypeValue: string = this.defectTypes[this.selectDefectType]?.dictValue!
-    this.defectBugOptions = []
-    if (this.defectBugMap.has(defectTypeValue)) {
-      this.defectBugs = this.defectBugMap.get(defectTypeValue)!
-    } else {
-      this.defectBugs = await ProcessRequest.post('/api/v1/op/baseBug/list', {
-        bugType: defectTypeValue
-      } as RequestParamModel)
-      this.defectBugMap.set(defectTypeValue, this.defectBugs)
-    }
-    // 遍历封装缺陷下拉选择框
-    for (let i = 0; i < this.defectBugs.length; i++) {
-      this.defectBugOptions.push({value: this.defectBugs[i].bugName!})
-    }
-    this.selectedDefectBug = 0;
+  private initDefectBugMap() {
+    this.defectBugMap.set('外观缺陷', [
+      { bugType: '外观缺陷', bugCode: 'A001-01', bugName: '划痕' },
+      { bugType: '外观缺陷', bugCode: 'A001-02', bugName: '污渍' },
+      { bugType: '外观缺陷', bugCode: 'A001-03', bugName: '色差' }
+    ])
+
+    this.defectBugMap.set('尺寸不良', [
+      { bugType: '尺寸不良', bugCode: 'A002-01', bugName: '尺寸偏大' },
+      { bugType: '尺寸不良', bugCode: 'A002-02', bugName: '尺寸偏小' }
+    ])
+
+    this.defectBugMap.set('功能异常', [
+      { bugType: '功能异常', bugCode: 'A003-01', bugName: '功能失效' },
+      { bugType: '功能异常', bugCode: 'A003-02', bugName: '性能不达标' }
+    ])
+
+    this.defectBugMap.set('材料问题', [
+      { bugType: '材料问题', bugCode: 'A004-01', bugName: '材料裂纹' },
+      { bugType: '材料问题', bugCode: 'A004-02', bugName: '材料变形' }
+    ])
+
+    this.defectBugMap.set('装配问题', [
+      { bugType: '装配问题', bugCode: 'A005-01', bugName: '装配错位' },
+      { bugType: '装配问题', bugCode: 'A005-02', bugName: '螺丝松动' }
+    ])
+
+    this.defectBugMap.set('包装问题', [
+      { bugType: '包装问题', bugCode: 'A006-01', bugName: '包装破损' },
+      { bugType: '包装问题', bugCode: 'A006-02', bugName: '标签错误' }
+    ])
   }
-  // 刷新不良类型记录列表
-  async refreshDefectRecords() {
-    this.defectRecords = []
-    this.defectRecords = await ProcessRequest.post('/api/v1/process/defectRecord/list', {
-      seqNo: this.seqNo
-    } as RequestParamModel)
-    if (this.defectRecords && this.defectTypes) {
-      for (const element of this.defectRecords) {
-        for (const dict of this.defectTypes) {
-          if (element.defectType === dict.dictValue) {
-            element.defectTypeLabel = dict.dictLabel
-            break
+
+
+    refreshDefectBugs() {
+      // 清空当前缺陷类型选项
+      this.defectBugOptions = []
+      this.selectedDefectBug = -1
+      // 检查是否有选中的不良类型
+      if (this.selectDefectType === -1) {
+        return
+      }
+      // 获取选中的不良类型值
+      const selectedDefectType = this.defectTypeOptions[this.selectDefectType].value as string
+      // 从映射中获取对应的缺陷列表
+      const defectBugs = this.defectBugMap.get(selectedDefectType)
+
+      if (defectBugs && defectBugs.length > 0) {
+        // 将缺陷列表转换为SelectOption格式
+        this.defectBugOptions = defectBugs.map((bug: ProcessBaseBug): SelectOption => {
+          const option: SelectOption = {
+            value: bug.bugName || '',
+            icon: ''
+          }
+          return option
+        })
+        // 如果是编辑状态且有初始值,尝试匹配对应的缺陷
+        if (this.isEdit && this.defectRecord.bugName) {
+          const index = defectBugs.findIndex(bug => bug.bugName === this.defectRecord.bugName)
+          if (index !== -1) {
+            this.selectedDefectBug = index
           }
         }
       }
-    }
   }
 
-  async aboutToAppear() {
-    for (let i = 0; i < this.defectTypes.length; i++) {
-      this.defectTypeOptions.push({value: this.defectTypes[i].dictLabel!})
-    }
-    // 新增时,默认选中第一个不良类型及其第一种缺陷
-    if (!this.isEdit && this.defectTypes) {
-      this.defectRecord = {}
-      this.selectDefectType = 0
-      this.defectBugs = await ProcessRequest.post('/api/v1/op/baseBug/list', {
-        bugType: this.defectTypes[0].dictValue!
-      } as RequestParamModel)
-      this.defectBugMap.set(this.defectTypes[0].dictValue!, this.defectBugs)
-      for (let i = 0; i < this.defectBugs.length; i++) {
-        this.defectBugOptions.push({value: this.defectBugs[i].bugName!})
-      }
-      this.selectedDefectBug = 0;
-    } else if (this.isEdit && this.defectRecord && this.defectRecord.defectType) {
-      this.defectRemark = this.defectRecord.remark ? this.defectRecord.remark : ''
-      // 修改时,不良类型、缺陷名称直接选中
-      let defectTypeValue: string = this.defectRecord.defectType!
-      // 不良类型选中
-      for (let i = 0; i < this.defectTypes.length; i++) {
-        if (defectTypeValue === this.defectTypes[i].dictValue!) {
-          this.selectDefectType = i;
-          break
-        }
-      }
-      // 查询不良类型下所有的缺陷
-      let defectBugCode: string = this.defectRecord.bugCode!
-      this.defectBugs = await ProcessRequest.post('/api/v1/op/baseBug/list', {
-        bugType: defectTypeValue
-      } as RequestParamModel)
-      this.defectBugMap.set(defectTypeValue, this.defectBugs)
-      // 缺陷名称选中
-      for (let i = 0; i < this.defectBugs.length; i++) {
-        this.defectBugOptions.push({value: this.defectBugs[i].bugName!})
-        if (defectBugCode === this.defectBugs[i].bugCode) {
-          this.selectedDefectBug = i;
+  // 添加不良记录到列表
+  private addDefectRecordToArray(record: ProcessDefectRecord) {
+    // 添加新记录到数组
+    this.defectRecords.push(record)
+    // 触发数组更新(如果需要)
+    this.defectRecords = [...this.defectRecords]
+  }
+  private isEditLoad(){
+      if (this.isEdit && this.defectRecord) {
+        this.defectRemark = this.defectRecord.remark || ''
+        if (this.defectRecord.defectType) {
+          const defectTypeIndex = this.defectTypeOptions.findIndex(
+            option => option.value === this.defectRecord.defectType
+          )
+          if (defectTypeIndex !== -1) {
+            this.selectDefectType = defectTypeIndex
+          }
         }
+        // 刷新缺陷类型选项并设置选中的缺陷类型
+        this.refreshDefectBugs()
       }
+  }
+
+
+  private deleteDefectRecord() {
+    if (!this.isEdit) {
+      console.error('删除失败:不是编辑状态')
+      return
+    }
+    // 从数组中删除记录 - 使用索引查找
+    if (this.defectIndex >= 0 && this.defectIndex < this.defectRecords.length) {
+      this.defectRecords.splice(this.defectIndex, 1)
+      // 触发数组更新
+      this.defectRecords = [...this.defectRecords]
+      console.info('成功删除不良记录')
+    } else {
+      console.error('未找到要删除的记录,索引无效:' + this.defectIndex)
     }
   }
 
+
+  aboutToAppear(): void {
+    this.initDefectBugMap()
+    this.isEditLoad()
+  }
   build() {
     Column(){
       Column() {
@@ -213,14 +252,34 @@ export struct DefectRecordDialog {
             .justifyContent(FlexAlign.Center)
             .width('33.3%')
             .onClick(async () => {
-              await ProcessRequest.post('/api/v1/process/defectRecord/del', {
-                id: this.defectRecord.id!
-              } as RequestParamModel)
-              // 重新刷新不良类型记录列表
-              this.refreshDefectRecords()
-              if (this.controller) {
-                this.controller.close()
-              }
+              AlertDialog.show(
+                {
+                  title: '确认删除',
+                  message: '确定要删除这条不良记录吗?',
+                  primaryButton: {
+                    value: '取消',
+                    action: () => {
+                      console.info('取消删除')
+                    }
+                  },
+                  secondaryButton: {
+                    value: '确定',
+                    action: () => {
+                      // 执行删除操作
+                      this.deleteDefectRecord()
+                      // 关闭对话框
+                      if (this.controller) {
+                        this.controller.close()
+                      }
+                      // 可以添加删除成功提示
+                      // prompt.showToast({ message: '删除成功', duration: 2000 })
+                    }
+                  },
+                  cancel: () => {
+                    console.info('取消删除操作')
+                  }
+                }
+              )
             })
             Divider()
               .vertical(true)
@@ -246,15 +305,25 @@ export struct DefectRecordDialog {
             .justifyContent(FlexAlign.Center)
             .width('33.3%')
             .onClick(async () => {
-              this.defectRecord.remark = this.defectRemark
-              if (this.defectRecord) {
-                this.defectRecord.defectType = this.defectBugs[this.selectedDefectBug].bugType!
-                this.defectRecord.bugCode = this.defectBugs[this.selectedDefectBug].bugCode!
-                this.defectRecord.bugName = this.defectBugs[this.selectedDefectBug].bugName!
+              const selectedDefectType = this.defectTypeOptions[this.selectDefectType].value as string
+              const defectBugs = this.defectBugMap.get(selectedDefectType)
+
+              if (!defectBugs || this.selectedDefectBug >= defectBugs.length) {
+                return
               }
-              await ProcessRequest.post('/api/v1/process/defectRecord/update', this.defectRecord)
-              // 重新刷新不良类型记录列表
-              this.refreshDefectRecords()
+
+              const selectedDefectBug = defectBugs[this.selectedDefectBug]
+
+              // 直接修改原对象(如果需要深拷贝,可以先复制)
+              const recordToUpdate = this.defectRecords[this.defectIndex]
+              recordToUpdate.remark = this.defectRemark
+              recordToUpdate.defectType = selectedDefectBug.bugType!
+              recordToUpdate.bugName = selectedDefectBug.bugName!
+
+              // 使用splice触发更新(或者重新赋值数组)
+              this.defectRecords.splice(this.defectIndex, 1, recordToUpdate)
+              this.defectRecords = [...this.defectRecords] // 重新赋值触发更新
+
               if (this.controller) {
                 this.controller.close()
               }
@@ -290,16 +359,16 @@ export struct DefectRecordDialog {
             .justifyContent(FlexAlign.Center)
             .width('50%')
             .onClick(async () => {
-              this.defectRecord.processId = this.process.id!
-              this.defectRecord.seqNo = this.seqNo
-              this.defectRecord.operationId = this.selectOperationId
               this.defectRecord.remark = this.defectRemark
-              this.defectRecord.defectType = this.defectBugs[this.selectedDefectBug].bugType!
-              this.defectRecord.bugCode = this.defectBugs[this.selectedDefectBug].bugCode!
-              this.defectRecord.bugName = this.defectBugs[this.selectedDefectBug].bugName!
-              await ProcessRequest.post('/api/v1/process/defectRecord/add', this.defectRecord)
-              // 重新刷新不良类型记录列表
-              this.refreshDefectRecords()
+              const selectedDefectType = this.defectTypeOptions[this.selectDefectType].value as string
+              const defectBugs = this.defectBugMap.get(selectedDefectType)
+              if (!defectBugs ) {
+                return
+              }
+              const selectedDefectBug = defectBugs[this.selectedDefectBug]
+              this.defectRecord.defectType = selectedDefectBug.bugType!
+              this.defectRecord.bugName = selectedDefectBug.bugName!
+              this.addDefectRecordToArray(this.defectRecord)
               if (this.controller) {
                 this.controller.close()
               }

+ 154 - 0
entry/src/main/ets/view/ProductionProcessesView.ets

@@ -0,0 +1,154 @@
+import WorkOrderInfo from '../viewmodel/WorkOrderInfo';
+import OperationInfo from '../viewmodel/process/OperationInfo';
+import promptAction from '@ohos.promptAction';
+import { ProcessStatus } from '../viewmodel/process/EnumerationType';
+
+interface  Tmp {
+  index: number;
+  item: OperationInfo
+}
+
+@Component
+export struct OperationList {
+  // 必需属性
+  @Link @Watch('onWorkOrderChange') selectWorkOder: WorkOrderInfo;
+  @Link selectOperationId: string  ;
+  @Link stationId: string;
+  @Link isStationProcess:boolean;
+  @Link currentProcessStatus: ProcessStatus
+
+  // 新增:监听selectWorkOder变化的回调
+  onWorkOrderChange() {
+    this.findAndSelectMatchingOperation();
+  }
+
+  findAndSelectMatchingOperation(): void {
+    // 如果已经有选中的工序,且该工序匹配当前工位,则保持选中
+    if (this.selectOperationId) {
+      const currentSelected = this.selectWorkOder.ops?.find(op => op.operationId === this.selectOperationId);
+      if (currentSelected && currentSelected.stationId === this.stationId) {
+        return; // 当前选中的工序仍然匹配,不需要更改
+      }
+    }
+    // 查找第一个匹配当前工位且未完成的工序
+    const matchingOperation = this.selectWorkOder.ops?.find(op =>
+    op.stationId === this.stationId && !op.isEnd
+    );
+
+    if (matchingOperation) {
+      this.selectOperationId = matchingOperation.operationId!;
+      this.isStationProcess = true;
+    } else {
+        promptAction.showToast({
+          message: `当前没有该工位未完成工序`,
+          duration: 1500,
+        });
+        this.isStationProcess = false;
+
+      }
+    }
+
+
+  build() {
+    List() {
+      ForEach(this.selectWorkOder.ops!, (item: OperationInfo, index: number) => {
+        ListItem() {
+          this.OperationListItem({ item: item, index: index })
+        }
+      })
+    }
+    .width('83.4%')
+    .height('88.6%')
+    .alignListItem(ListItemAlign.Center)
+  }
+
+  @Builder
+  OperationListItem(params: Tmp) {
+    Column() {
+      // 工序项
+      Row() {
+        // 序号
+        Row() {
+          Text((params.index + 1).toString())
+            .fontSize($r('app.float.fontSize_16'))
+            .fontColor(this.selectOperationId === params.item.operationId ? $r('app.color.90000000') : $r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Bold)
+        }
+        .width('14.6%')
+        .height('80%')
+        .justifyContent(FlexAlign.Center)
+
+        // 工序名称
+        Row() {
+          Text(params.item.operationName)
+            .fontSize($r('app.float.fontSize_16'))
+            .fontColor(this.selectOperationId === params.item.operationId ? $r('app.color.90000000') : $r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Regular)
+            .padding({ left: 5 })
+        }
+        .width('70.8%')
+        .height('100%')
+        .alignItems(VerticalAlign.Center)
+        .justifyContent(FlexAlign.Start)
+
+        // 状态图标
+        Row() {
+          Image(this.selectOperationId === params.item.operationId ?
+          $r('app.media.process_current_operation') :
+            (params.item.isEnd! ? $r('app.media.process_complete') : ''))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+            .fillColor(this.selectOperationId === params.item.operationId ? $r('app.color.90000000') : $r('app.color.FFFFFF'))
+            .opacity(!(this.selectOperationId === params.item.operationId) && !params.item.isEnd! ? 0 : 1)
+        }
+        .width('14.6%')
+        .height('100%')
+        .justifyContent(FlexAlign.Center)
+      }
+      .width('100%')
+      .height('70%')
+      .borderRadius($r('app.float.virtualSize_40'))
+      .backgroundImage(this.selectOperationId === params.item.operationId ?
+      $r('app.media.process_select_operation') :
+      $r('app.media.process_no_select_operation'))
+      .backgroundImageSize(ImageSize.Cover)
+      .onClick(async () => {
+        if(this.selectOperationId == params.item.operationId!) return
+        this.isStationProcess = false;
+        this.currentProcessStatus = ProcessStatus.INITIAL
+        this.selectOperationId = params.item.operationId!;
+        if (this.stationId != params.item.stationId!) {
+          promptAction.showToast({
+            message: `${params.item.operationName}需要在${params.item.stationId}工位上生产`,
+            duration: 1500,
+          });
+          return;
+        }
+        if (params.item.isEnd!) {
+          promptAction.showToast({
+            message: `${params.item.operationName}已经完成`,
+            duration: 1500,
+          });
+          return;
+        }
+        this.isStationProcess = true;
+      })
+
+      // 分隔线(非最后一项显示)
+      if (params.index < (this.selectWorkOder?.ops?.length ? this.selectWorkOder.ops!.length - 1 : 0)) {
+        Row() {
+          Divider()
+            .vertical(true)
+            .color($r('app.color.60FFFFFF'))
+            .padding({ right: '15%' })
+        }
+        .justifyContent(FlexAlign.Center)
+        .width('20%')
+        .layoutWeight(1)
+      }
+    }
+    .width('100%')
+    .height('10.6%')
+    .alignItems(HorizontalAlign.Start)
+  }
+}

+ 233 - 0
entry/src/main/ets/view/RecordItemDialog.ets

@@ -0,0 +1,233 @@
+//添加或者编辑不良类型记录
+import ProcessRequest from '../common/util/request/ProcessRequest';
+import RequestParamModel from '../viewmodel/RequestParamModel';
+import DictValue from '../viewmodel/DictValue';
+import ProcessBaseBug from '../viewmodel/process/ProcessBaseBug';
+import ProcessInfo from '../viewmodel/process/ProcessInfo';
+import ProcessDefectRecord from '../viewmodel/process/ProcessDefectRecord';
+import RecordItem from '../viewmodel/process/RecordItem';
+import prompt from '@ohos.prompt';
+
+@CustomDialog
+export struct RecordItemDialog {
+  controller: CustomDialogController
+  onConfirm: ()=> void = () => {}
+  scroller: Scroller = new Scroller()
+  //是否是编辑状态(需要传入的参数)
+  @Prop isEdit: boolean = false
+  @Prop RecordIndex:number
+  recordItem: RecordItem = {}
+  // 不良类型记录列表
+  @Link recordItems: RecordItem[]
+  // 备注
+  @State recordContent: string = ''
+  @State recordTitle: string = ''
+
+  private deleteDefectRecord() :boolean{
+    // 从数组中删除记录 - 使用索引查找
+    if (this.RecordIndex >= 0 && this.RecordIndex < this.recordItems.length) {
+      this.recordItems.splice(this.RecordIndex, 1)
+      // 触发数组更新
+      this.recordItems = [...this.recordItems]
+      return true
+    } else {
+      return false
+      console.error('未找到要删除的记录,索引无效:' + this.RecordIndex)
+    }
+  }
+  aboutToAppear(): void {
+    if(this.isEdit)
+    {
+      this.recordTitle = this.recordItem.title!
+      this.recordContent = this.recordItem.content!
+    }
+  }
+
+
+  build() {
+    Column(){
+      Column() {
+        Text(this.isEdit ? '记录项' : '添加记录项')
+          .fontColor($r('app.color.FFFFFF'))
+          .fontSize($r('app.float.fontSize_30'))
+      }
+      .height('14%')
+      .width('100%')
+      .justifyContent(FlexAlign.Center)
+      Column(){
+        Text('标题')
+          .fontSize($r('app.float.fontSize_16'))
+          .fontColor($r('app.color.FFFFFF'))
+        TextInput({ text: this.recordTitle, placeholder: '请输入标题' })
+          .height('14%')
+          .width('100%')
+          .borderRadius($r('app.float.virtualSize_16'))
+          .backgroundColor($r('app.color.20FFFFFF'))
+          .fontSize($r('app.float.fontSize_24'))
+          //.fontColor(this.selectDefectType === -1 ? $r('app.color.30FFFFFF'):$r('app.color.FFFFFF'))
+          .margin({top:'3%',bottom:'3%'})
+          .onChange((value: string) => {
+            this.recordTitle = value
+          })
+        Text('内容')
+          .fontSize($r('app.float.fontSize_16'))
+          .fontColor($r('app.color.FFFFFF'))
+        TextArea({placeholder:'请输入内容', text: this.recordContent})
+          .backgroundColor($r('app.color.000000'))
+          .height('60%')
+          .width('100%')
+          .fontColor($r('app.color.FFFFFF'))
+          .placeholderColor($r('app.color.30FFFFFF'))
+          .placeholderFont({size:$r('app.float.fontSize_16')})
+          .fontSize($r('app.float.fontSize_16'))
+          .textAlign(TextAlign.Start)
+          .maxLength(200)
+          .margin({top:'3%',bottom:'3%'})
+          .borderRadius($r('app.float.virtualSize_16'))
+          .onChange((value: string) => {
+            this.recordContent = value
+          })
+      }
+      .width('70%')
+      .height('72%')
+      .margin({left:'15%',right:'15%'})
+      .alignItems(HorizontalAlign.Start)
+      if(this.isEdit){
+        Column() {
+          Divider()
+            .vertical(false)
+            .strokeWidth(1)
+            .color($r('app.color.15FFFFFF'))
+          Row() {
+            Row() {
+              Text('删除')
+                .fontColor($r('app.color.FF453A'))
+                .fontSize($r('app.float.fontSize_30'))
+            }
+            .justifyContent(FlexAlign.Center)
+            .width('33.3%')
+            .onClick(async () => {
+              AlertDialog.show(
+                {
+                  title: '确认删除',
+                  message: '确定要删除这条记录项吗?',
+                  primaryButton: {
+                    value: '取消',
+                    action: () => {
+                      console.info('取消删除')
+                    }
+                  },
+                  secondaryButton: {
+                    value: '确定',
+                    action: () => {
+                      if (this.controller) {
+                        this.controller.close()
+                      }
+                      if(this.deleteDefectRecord()) {
+                        prompt.showToast({ message: '删除成功', duration: 2000 })
+                      }
+                    }
+                  },
+                  cancel: () => {
+                    console.info('取消删除操作')
+                  }
+                }
+              )
+            })
+            Divider()
+              .vertical(true)
+              .strokeWidth(1)
+              .color($r('app.color.15FFFFFF'))
+            Row() {
+              Text('取消')
+                .fontColor($r('app.color.60FFFFFF'))
+                .fontSize($r('app.float.fontSize_30'))
+            }
+            .justifyContent(FlexAlign.Center)
+            .width('33.3%')
+            .onClick(() => this.controller.close())
+            Divider()
+              .vertical(true)
+              .strokeWidth(1)
+              .color($r('app.color.15FFFFFF'))
+            Row() {
+              Text('确定')
+                .fontColor($r('app.color.007AFF'))
+                .fontSize($r('app.float.fontSize_30'))
+            }
+            .justifyContent(FlexAlign.Center)
+            .width('33.3%')
+            .onClick(async () => {
+              if(!this.recordTitle&&!this.recordContent)
+              {
+                prompt.showToast({ message: '标题和内容不能为空', duration: 2000 })
+                return
+              }
+              this.recordItem.title = this.recordTitle
+              this.recordItem.content = this.recordContent
+              const updateRecordItem= this.recordItem
+              this.recordItems.splice(this.RecordIndex,1,updateRecordItem)
+              this.recordItems = [...this.recordItems]
+              if (this.controller) {
+                this.controller.close()
+              }
+            })
+          }
+        }
+        .width('100%')
+        .height('12%')
+      }else{
+        Column() {
+          Divider()
+            .vertical(false)
+            .strokeWidth(1)
+            .color($r('app.color.15FFFFFF'))
+          Row() {
+            Row() {
+              Text('取消')
+                .fontColor($r('app.color.60FFFFFF'))
+                .fontSize($r('app.float.fontSize_30'))
+            }
+            .justifyContent(FlexAlign.Center)
+            .width('50%')
+            .onClick(() => this.controller.close())
+            Divider()
+              .vertical(true)
+              .strokeWidth(1)
+              .color($r('app.color.15FFFFFF'))
+            Row() {
+              Text('确定')
+                .fontColor($r('app.color.007AFF'))
+                .fontSize($r('app.float.fontSize_30'))
+            }
+            .justifyContent(FlexAlign.Center)
+            .width('50%')
+            .onClick(async () => {
+              if(!this.recordTitle&&!this.recordContent)
+              {
+                prompt.showToast({ message: '标题和内容不能为空', duration: 2000 })
+                return
+              }
+              this.recordItem.title = this.recordTitle
+              this.recordItem.content = this.recordContent
+              this.recordItems.push(this.recordItem)
+              if (this.controller) {
+                this.controller.close()
+              }
+            })
+          }
+        }
+        .width('100%')
+        .height('12%')
+      }
+    }
+    .height('50%')
+    .width('40%')
+    .backgroundColor($r('app.color.2A2A2A'))
+    .justifyContent(FlexAlign.End)
+    .alignItems(HorizontalAlign.Start)
+    .borderColor($r('app.color.000000'))
+    .borderWidth(1)
+    .borderRadius($r('app.float.virtualSize_16'))
+  }
+}

+ 135 - 27
entry/src/main/ets/view/SelectWorkOrderDialog.ets

@@ -2,10 +2,13 @@ import ProcessRequest from '../common/util/request/ProcessRequest'
 import RequestParamModel from '../viewmodel/RequestParamModel'
 import WorkOrderInfo from '../viewmodel/WorkOrderInfo'
 import { WorkOrderPage } from '../viewmodel/WorkOrderPage'
-
-@CustomDialog
-export struct SelectWorkOrderDialog {
+import {ProcessCurrentView} from '../viewmodel/process/EnumerationType'
+import OperationInfo from '../viewmodel/process/OperationInfo';
+@Component
+export struct SelectWorkOrderView {
+  @Link processCurrentView:ProcessCurrentView
   private scrollerMaterial: Scroller = new Scroller()
+  @Link previousView:ProcessCurrentView
   //工单列表
   @State workOrderList: WorkOrderInfo[] = []
   //选择的工单索引
@@ -13,22 +16,123 @@ export struct SelectWorkOrderDialog {
   //扫描的工单号
   @State scanOrderValue:string = ''
   @Link selectWorkOder: WorkOrderInfo
+
   // 当前工位ID
-  @Consume('currentStationId') currentStationId: string
-  controller: CustomDialogController
-  onConfirm: () => void = () => {
-  }
+ // @Consume('currentStationId') currentStationId: string
 
   //加载所有工单
   loadWorkOrders = async () => {
-    let queryRes = await ProcessRequest.post('/api/v1/plan/workOrder/taskPage2', {
-      queryCode:this.scanOrderValue,
-      queryComplete: 0,
-      stationId:this.currentStationId,
-      pageNo: 1,
-      pageSize: 99999,
-    } as RequestParamModel) as WorkOrderPage;
-    this.workOrderList = queryRes?.records??[]
+    // let queryRes = await ProcessRequest.post('/api/v1/plan/workOrder/taskPage2', {
+    //   queryCode:this.scanOrderValue,
+    //   queryComplete: 0,
+    //   stationId:this.currentStationId,
+    //   pageNo: 1,
+    //   pageSize: 99999,
+    // } as RequestParamModel) as WorkOrderPage;
+    // this.workOrderList = queryRes?.records??[]
+    if (this.scanOrderValue) {
+      // let queryRes = await ProcessRequest.post('/api/v1/plan/workOrder/taskPage2', {
+      //   queryCode:this.scanOrderValue,
+      //   queryComplete: 0,
+      //   stationId:this.currentStationId,
+      //   pageNo: 1,
+      //   pageSize: 99999,
+      // } as RequestParamModel) as WorkOrderPage;
+      // this.workOrderList = queryRes?.records??[]
+    } else {
+      // 没有扫描值时,显示示例数据
+      this.loadDemoData();
+    }
+  };
+
+  loadDemoData = () => {
+    const demoData: WorkOrderInfo[] = [
+      {
+       materialName: "智能手机外壳",
+      materialCode: "PH-CASE-001",
+      orderCode: "ORD-2024-1001",
+      workOrderCode: "WO-2024-0801",
+      workOrderState: "1",
+      completeNum: "150",
+      planNum: "500",
+      ops: [
+        {
+          operationId: "OP001",
+          operationName: "外壳预处理",
+          isEnd: true,
+          operationCode: "OP-PRE-001",
+          stationId:'123',
+        } as OperationInfo,
+        {
+          operationId: "OP002",
+          operationName: "表面打磨",
+          isEnd: true,
+          operationCode: "OP-POLISH-002",
+          stationId:'3c3c3d3d',
+        } as OperationInfo,
+        {
+          operationId: "OP003",
+          operationName: "喷涂处理",
+          isEnd: false,
+          operationCode: "OP-SPRAY-003",
+          stationId:'123',
+        } as OperationInfo,
+        {
+          operationId: "OP004",
+          operationName: "质量检验",
+          isEnd: false,
+          operationCode: "OP-QC-004",
+          stationId:'3c3c3d3d',
+        } as OperationInfo
+      ]
+    } as WorkOrderInfo,
+      {
+        materialName: "笔记本电脑电池",
+        materialCode: "NB-BATT-002",
+        orderCode: "ORD-2024-1002",
+        workOrderCode: "WO-2024-0802",
+        workOrderState: "3",
+        completeNum: "150",
+        planNum: "500"
+      } as WorkOrderInfo,
+      {
+        materialName: "智能手表屏幕",
+        materialCode: "WT-SCR-003",
+        orderCode: "ORD-2024-1003",
+        workOrderCode: "WO-2024-0803",
+        workOrderState: "6",
+        completeNum: "150",
+        planNum: "500"
+      } as WorkOrderInfo,
+      {
+        materialName: "无线耳机芯片",
+        materialCode: "BUD-CHIP-004",
+        orderCode: "ORD-2024-1004",
+        workOrderCode: "WO-2024-0804",
+        workOrderState: "2",
+        completeNum: "150",
+        planNum: "500"
+      } as WorkOrderInfo,
+      {
+        materialName: "平板电脑主板",
+        materialCode: "TAB-MB-005",
+        orderCode: "ORD-2024-1005",
+        workOrderCode: "WO-2024-0805",
+        workOrderState: "4",
+        completeNum: "150",
+        planNum: "500"
+      } as WorkOrderInfo,
+      {
+        materialName: "摄像头模组",
+        materialCode: "CAM-MOD-006",
+        orderCode: "ORD-2024-1006",
+        workOrderCode: "WO-2024-0806",
+        workOrderState: "1",
+        completeNum: "150",
+        planNum: "500"
+      } as WorkOrderInfo
+    ];
+    this.workOrderList = demoData;
   };
 
   private onSelectOrder(index: number) {
@@ -48,6 +152,8 @@ export struct SelectWorkOrderDialog {
       }.height('8%')
       .width('100%')
       .justifyContent(FlexAlign.Center)
+      .alignItems(HorizontalAlign.Start)
+      .margin({ left: '2%'})
 
       Row() {
         // 左侧二维码图标
@@ -190,7 +296,7 @@ export struct SelectWorkOrderDialog {
           }
           .justifyContent(FlexAlign.Center)
           .width('50%')
-          .onClick(() => this.controller.close())
+          .onClick(() => this.processCurrentView = this.previousView)
 
           Divider()
             .vertical(true)
@@ -205,24 +311,26 @@ export struct SelectWorkOrderDialog {
           .width('50%')
           .onClick(() => {
             if(this.selectedOrderIndex==-1) return
-            // 重新选中的工单就是之前的工单,则不做任何操作
-            if (this.selectWorkOder && this.selectWorkOder.workOrderCode && this.workOrderList[this.selectedOrderIndex].workOrderCode! === this.selectWorkOder.workOrderCode!) {
-              this.controller.close();
-              return
-            }
             this.selectWorkOder = this.workOrderList[this.selectedOrderIndex]
-            this.onConfirm();
-            this.controller.close();
-          })
+            this.processCurrentView = ProcessCurrentView.WORK_STEP_VIEW
+          //   if(this.selectedOrderIndex==-1) return
+          //   // 重新选中的工单就是之前的工单,则不做任何操作
+          //   if (this.selectWorkOder && this.selectWorkOder.workOrderCode && this.workOrderList[this.selectedOrderIndex].workOrderCode! === this.selectWorkOder.workOrderCode!) {
+          //     this.controller.close();
+          //     return
+          //   }
+          //   this.selectWorkOder = this.workOrderList[this.selectedOrderIndex]
+          //   this.onConfirm();
+          //   this.controller.close();
+           })
         }
       }
       .width('100%')
       .height('8%')
 
       }
-      .height('71%')
-      .width('62%')
-      .backgroundColor($r('app.color.2A2A2A'))
+      .height('100%')
+      .width('100%')
       .justifyContent(FlexAlign.End)
       .alignItems(HorizontalAlign.Start)
       .borderColor($r('app.color.000000'))

+ 113 - 0
entry/src/main/ets/view/SwitchAndScanProductView.ets

@@ -0,0 +1,113 @@
+import {ProcessCurrentView} from '../viewmodel/process/EnumerationType'
+// 物料采集工序
+@Component
+export struct SwitchAndScanProductView {
+  @Link processCurrentView:ProcessCurrentView
+  @Link previousView:ProcessCurrentView
+
+  @State scanCode: string = ''
+  private isSubmitting: boolean = false
+
+  controller: TextInputController = new TextInputController()
+  aboutToAppear() {
+    setTimeout(() => {
+      focusControl.requestFocus('CATCH_FOCUS')
+    }, 500)
+  }
+
+  private delay(ms: number): Promise<void> {
+    return new Promise((resolve) => setTimeout(resolve, ms));
+  }
+  private async submitScanCode(code: string) {
+    // 1. 基础校验:非空+防抖
+    if (!code || this.isSubmitting) return
+    this.isSubmitting = true
+    await this.delay(200)
+    try {
+      if(this.scanCode = '79714')
+      {
+        this.previousView = this.processCurrentView;
+        this.processCurrentView = ProcessCurrentView.WORK_ORDER_VIEW
+      }
+      // 2. 执行提交逻辑(示例:打印编码,实际替换为接口调用/业务处理)
+      console.log('扫码内容自动提交:', code)
+      this.scanCode = ''
+      // 4. 重新聚焦输入框(保持扫码状态)
+      focusControl.requestFocus('CATCH_FOCUS')
+    } catch (error) {
+      console.error('提交失败:', error)
+      // 提交失败可提示用户(如Toast)
+      // prompt.showToast({ message: '提交失败,请重试' })
+    } finally {
+      // 重置防抖标记
+      this.isSubmitting = false
+    }
+  }
+
+  build() {
+    Column() {
+      Row() {
+        Text('扫描产品编码')
+          .fontSize($r('app.float.fontSize_30'))
+          .fontWeight(FontWeight.Medium)
+          .fontColor($r('app.color.FFFFFF'))
+      }
+      .height('10%')
+      .width('97.2%')
+      .justifyContent(FlexAlign.Start)
+
+      Row() {
+        Column({ space: 5 }) {
+          Row().height('37%')
+          Row() {
+            Text('请扫描产品编码')
+              .fontSize($r('app.float.fontSize_16'))
+              .fontWeight(FontWeight.Regular)
+              .fontColor($r('app.color.FFFFFF'))
+          }
+          .width('62%')
+
+          Row() {
+            Row().width('3.4%')
+            // 左侧二维码图标
+            Image($r('app.media.material_qr_code'))// 请替换为您的二维码图片资源
+              .width($r('app.float.virtualSize_24'))
+              .height($r('app.float.virtualSize_24'))
+              .fillColor($r('app.color.FFFFFF'))
+            // 扫码输入框
+            TextInput({ placeholder: '请扫描产品编码',
+              controller: this.controller, text: this.scanCode })
+              .type(InputType.Normal)
+              .placeholderFont({ size: $r('app.float.fontSize_16') })
+              .placeholderColor($r('app.color.30FFFFFF'))
+              .fontSize($r('app.float.fontSize_16'))
+              .fontColor($r('app.color.FFFFFF'))
+              .enableKeyboardOnFocus(false)
+              .key('CATCH_FOCUS')
+              .onChange((value: string) => {
+                this.scanCode = value
+              })
+              .onSubmit(() => {
+                // 回车键提交
+                this.submitScanCode(this.scanCode )
+              })
+          }
+          .width('65%')
+          .height('6.5%')
+          .borderRadius($r('app.float.virtualSize_16'))
+          .backgroundColor($r('app.color.000000'))
+          .justifyContent(FlexAlign.Start)
+        }
+        .width('52.9%')
+        .height('100%')
+      }
+      .width('100%')
+      .height('87.7%')
+      .justifyContent(FlexAlign.Center)
+
+    }
+    .width('100%')
+    .height('100%')
+  }
+
+}

+ 64 - 70
entry/src/main/ets/view/process/DeviceCheckView.ets

@@ -14,15 +14,68 @@ import CommonConstants from '../../common/constants/CommonConstants'
 @Component
 export struct DeviceCheckView {
   // 设备每日点检
-  @Link deviceChecks: ProcessDeviceDailyCheck[]
-  // 扫码开工状态(0:未开工 1:已开工)
-  @Link @Watch('queryDeviceCheckByScanState') scanState: number
-  // 当前流转卡号
-  @Link seqNo: string
-  // 选中工序id
-  @Link selectOperationId: string
-  // 扫码开工后的生产过程信息
-  @Link process: ProcessInfo
+  @State deviceChecks: ProcessDeviceDailyCheck[] = [
+    {
+      id: '1',
+      stationIp: '192.168.1.100',
+      deviceNo: 'DEV001',
+      deviceName: '数控机床A型',
+      deviceType: '001',
+      meteringDate: '2024-12-31',
+      meteringState: 1,
+      warrantyPeriod: '2025-06-30',
+      warrantyState: 1,
+      created: Date.now()
+    },
+    {
+      id: '2',
+      stationIp: '192.168.1.101',
+      deviceNo: 'DEV002',
+      deviceName: '激光切割机B型',
+      deviceType: '002',
+      meteringDate: '2024-10-15',
+      meteringState: 0,
+      warrantyPeriod: '2024-12-31',
+      warrantyState: 0,
+      created: Date.now()
+    },
+    {
+      id: '3',
+      stationIp: '192.168.1.102',
+      deviceNo: 'DEV003',
+      deviceName: '注塑机C型',
+      deviceType: '003',
+      meteringDate: '2025-03-20',
+      meteringState: 1,
+      warrantyPeriod: '2025-09-15',
+      warrantyState: 1,
+      created: Date.now()
+    },
+    {
+      id: '4',
+      stationIp: '192.168.1.103',
+      deviceNo: 'DEV004',
+      deviceName: '冲压机D型',
+      deviceType: '001',
+      meteringDate: '2024-08-10',
+      meteringState: 0,
+      warrantyPeriod: '长期有效',
+      warrantyState: 1,
+      created: Date.now()
+    },
+    {
+      id: '5',
+      stationIp: '192.168.1.104',
+      deviceNo: 'DEV005',
+      deviceName: '磨床E型',
+      deviceType: '002',
+      meteringDate: '长期有效',
+      meteringState: 1,
+      warrantyPeriod: '2024-11-30',
+      warrantyState: 0,
+      created: Date.now()
+    }
+  ]
   //查找设备编码
   @State queryDeviceNo: string = 'test000'
   // 设备类型(key为数据字典值,value为数据字典标签)
@@ -32,33 +85,6 @@ export struct DeviceCheckView {
   deviceTypeDictCode: string = 'device_type'
   private scrollerDevice: Scroller = new Scroller()
 
-  // 根据开工状态查询 工序设备点检/工序设备点检历史操作
-  async queryDeviceCheckByScanState() {
-    if (this.scanState === 1) {
-      this.deviceChecks = await ProcessRequest.post('/api/v1/process/deviceCheck/queryAndSave', {
-        stationIp: this.stationIp,
-        processId: this.process.id!,
-      } as RequestParamModel)
-    } else {
-      let result = await ProcessRequest.post('/api/v1/operation/device/page', {
-        operationId: this.selectOperationId,
-        pageNo: 1,
-        pageSize: 99999
-      } as RequestParamModel) as PageInfo;
-      this.deviceChecks = result.records as ProcessCheck[] || []
-    }
-  }
-
-  async aboutToAppear() {
-    let deviceDicts: DictValue[] = await ProcessRequest.get(`/api/v1/sys/dictData/queryByType/${this.deviceTypeDictCode}`)
-    if (deviceDicts) {
-      this.deviceTypes = new HashMap()
-      for (const dict of deviceDicts) {
-        this.deviceTypes.set(dict.dictValue!, dict.dictLabel!);
-      }
-    }
-    this.queryDeviceCheckByScanState()
-  }
 
   build() {
     Column() {
@@ -77,38 +103,6 @@ export struct DeviceCheckView {
             .objectFit(ImageFit.Contain)
             .margin({left:'0.7%'})
           // 扫码输入框
-          TextInput({text:this.queryDeviceNo, placeholder: '请扫描设备编码' })
-            .type(InputType.Normal)
-            .placeholderFont({ size: $r('app.float.fontSize_16') })
-            .placeholderColor($r('app.color.30FFFFFF'))
-            .fontSize($r('app.float.fontSize_16'))
-            .fontColor($r('app.color.FFFFFF'))
-            .enableKeyboardOnFocus(false)
-            .onSubmit(async () => {
-              if (this.deviceChecks) {
-                for (const element of this.deviceChecks) {
-                  if (element.deviceNo === this.queryDeviceNo) {
-                    promptAction.showToast({
-                      message: `设备今日已点检,无需重复点检!`,
-                      duration: 1500,
-                      bottom: 100
-                    })
-                    return
-                  }
-                }
-              }
-              let check: ProcessDeviceDailyCheck = await ProcessRequest.get(`/api/v1/process/deviceDailyCheck/getServiceLifeByDeviceNo/${this.queryDeviceNo}`)
-              check.stationIp = this.stationIp
-              await ProcessRequest.post('/api/v1/process/deviceDailyCheck/add', check)
-              this.deviceChecks = []
-              this.deviceChecks = await ProcessRequest.post('/api/v1/process/deviceCheck/queryAndSave', {
-                stationIp: this.stationIp,
-                processId: this.process.id!,
-              } as RequestParamModel)
-            })
-            .onChange((value: string) => {
-              this.queryDeviceNo = value;
-            })
         }
         .height('100%')
         .width('27.2%')
@@ -152,7 +146,7 @@ export struct DeviceCheckView {
                     .fontSize($r('app.float.fontSize_16'))
                     .fontColor($r('app.color.FFFFFF'))
                     .fontWeight(FontWeight.Lighter)
-                  if (this.scanState === 1 && item.deviceNo) {
+                  if ( item.deviceNo) {
                     Row(){
                       Image(item.meteringState! === 1 ? $r('app.media.device_normal') : $r('app.media.device_expire'))
                         .width($r('app.float.virtualSize_24'))
@@ -179,7 +173,7 @@ export struct DeviceCheckView {
                     .fontSize($r('app.float.fontSize_16'))
                     .fontColor($r('app.color.FFFFFF'))
                     .fontWeight(FontWeight.Lighter)
-                  if (this.scanState === 1 && item.deviceNo) {
+                  if ( item.deviceNo) {
                     Row() {
                       Image(item.warrantyState! === 1 ? $r('app.media.device_normal') : $r('app.media.device_expire'))
                         .width($r('app.float.virtualSize_24'))

File diff suppressed because it is too large
+ 269 - 0
entry/src/main/ets/view/process/ESOPView.ets


File diff suppressed because it is too large
+ 415 - 0
entry/src/main/ets/view/process/ElectricScrewdriverView.ets


+ 140 - 143
entry/src/main/ets/view/process/MaterialCollectView.ets

@@ -7,85 +7,124 @@ import WorkOrderInfo from '../../viewmodel/WorkOrderInfo'
 import promptAction from '@ohos.promptAction'
 import { ModifyMaterialNumDialog } from '../ModifyMaterialNumDialog'
 import PageInfo from '../../viewmodel/PageInfo'
+import OperationComponent from '../../viewmodel/process/OperationComponent'
+
+// 补充缺失的UI相关导入(根据实际项目调整)
+
 
 // 物料采集工序
 @Component
 export struct MaterialCollectView {
   @State scanCode: string = ''
+  @Link opComponents: OperationComponent[]
+  @Link index:number
   // 需要采集的工序物料
-  @State itemArray: OperationItem[] = []
+  @Link itemArray: OperationItem[]
   // 总需求数
   @State needNum: number = 0
   // 实际数量(已采集数)
   @State realNum: number = 0
-  // 扫码查到物料信息
-  scanMaterial: ProcessMaterial = {}
-  // 新增或者修改采集物料(1:新增 2:修改)(采集物料数量修改弹窗使用)
+  // 扫码查到物料信息(修复:规范类型断言)
+  scanMaterial: ProcessMaterial = {} as ProcessMaterial
+  // 新增或者修改采集物料(1:新增 2:修改)
   addOrModifyCollect: number = 1
-  // 扫码开工状态(0:未开工 1:已开工)
-  @Link @Watch('queryByScanState') scanState: number
-  // 当前流转卡号
-  @Link seqNo: string
-  // 选中工单
-  @Link selectWorkOder: WorkOrderInfo
-  // 选中工序id
-  @Link selectOperationId: string
-  // 扫码开工后的生产过程信息
-  @Link process: ProcessInfo
-  // 当前工位ID
-  @Consume('currentStationId') currentStationId: string
+  // 扫码开工状态(0:未开工 1:已开工)(注释完整)
+  // @Link @Watch('queryByScanState') scanState: number = 0
+  // 当前流转卡号(补充未完成的变量声明)
+  currentFlowCardNo: string = ''
+
+  controller: TextInputController = new TextInputController()
 
-  modifyMaterialNumDialogController: CustomDialogController = new CustomDialogController({
-    builder: ModifyMaterialNumDialog({
-      scanMaterial: this.scanMaterial,
-      addOrModifyCollect: this.addOrModifyCollect,
-      operationId: this.selectOperationId!,
-      processId: this.process.id!,
-      seqNo: this.seqNo,
-      confirm: async ()=>{
-        this.queryCollectHistory()
-      },
-    }),
-    autoCancel: true, // 点击遮罩关闭
-    customStyle: true,
-    alignment: DialogAlignment.Center,
-    maskColor: 'rgba(0,0,0,0.8)',  // 黑色遮罩
-  })
 
-  // 采集历史查询
-  async queryCollectHistory() {
-    this.itemArray = await ProcessRequest.post('/api/v1/process/itemRecord/list', {
-      operationId: this.selectOperationId,
-      workOrderCode: this.selectWorkOder.workOrderCode!,
-      seqNo: this.seqNo,
-      processId: this.process.id,
-      pageNo: 1,
-      pageSize: 999999} as RequestParamModel)
+  aboutToAppear() {
+    // 页面显示时统计总量
+    this.calculateTotalNumbers()
+    setTimeout(() => {
+      focusControl.requestFocus('CATCH_FOCUS')
+    }, 500)
+    //console.info("sssss"+this.index+"sss"+this.componentStates[this.index])
   }
 
-  // 根据开工状态查询 需要采集的物料信息/物料采集历史
-  async queryByScanState() {
-    if (this.scanState === 1) {
-      this.queryCollectHistory()
-    } else {
-      let res = await ProcessRequest.post('/api/v1/op/operationItem/page', {
-        operationId: this.selectOperationId,
-        pageNo: 1,
-        pageSize: 999999} as RequestParamModel) as PageInfo
-      this.itemArray = res.records as OperationItem[] || []
-    }
-    if (this.itemArray) {
-      for (const element of this.itemArray) {
-        this.needNum += element.needNum || 0
-        this.realNum += element.realNum || 0
+
+  private delay(ms: number): Promise<void> {
+    return new Promise((resolve) => setTimeout(resolve, ms));
+  }
+
+  // 统计realNum总量和needNum总量(修复:用空值合并更安全)
+  async calculateTotalNumbers() {
+    let totalRealNum = 0
+    let totalNeedNum = 0
+
+    this.itemArray.forEach((item: OperationItem) => {
+      totalRealNum += item.realNum ?? 0
+      totalNeedNum += item.needNum ?? 0
+    })
+
+    this.realNum = totalRealNum
+    this.needNum = totalNeedNum
+    if(this.realNum === this.needNum)
+    {
+      if(!this.opComponents[this.index].isComplete)
+      {
+        this.opComponents[this.index].isComplete=true
+        this.index++
       }
+      //await this.delay(1500)
+      promptAction.showToast({
+        message: `所有物料已采集完成`,
+        duration: 2000
+      })
+
     }
   }
 
-  async aboutToAppear() {
-    this.queryByScanState()
+  async handleScanInput() {
+    await this.delay(200)
+    // 查找对应的物料
+    const foundItemIndex = this.itemArray.findIndex((item: OperationItem) =>
+    item.itemCode === this.scanCode.trim()
+    )
+
+    if (foundItemIndex !== -1) {
+      // 创建新的数组副本(触发UI更新)
+      const newItemArray = [...this.itemArray]
+      const foundItem = newItemArray[foundItemIndex]
+
+      // 检查是否已达到需求数量
+      if (foundItem.realNum! >= foundItem.needNum!) {
+        promptAction.showToast({
+          message: `物料 ${foundItem.itemName} 已采集完成,无需再次采集`,
+          duration: 2000
+        })
+        this.scanCode = ''
+        return
+      }
+
+      // 采集数量+1(确保非空)
+      foundItem.realNum = (foundItem.realNum ?? 0) + 1
+
+      // 更新数组引用触发UI更新
+      this.itemArray = newItemArray
+
+      // 重新统计总量
+      this.calculateTotalNumbers()
+
+      promptAction.showToast({
+        message: `物料 ${foundItem.itemName} 采集成功`,
+        duration: 1000
+      })
+    } else {
+      promptAction.showToast({
+        message: '未找到对应的物料信息',
+        duration: 2000
+      })
+    }
+
+    // 清空扫码输入框
+    this.scanCode = ''
+    focusControl.requestFocus('CATCH_FOCUS')
   }
-  
+
   build() {
     Column() {
       // 扫码框和已采集统计
@@ -97,57 +136,27 @@ export struct MaterialCollectView {
             .height($r('app.float.virtualSize_32'))
             .fillColor($r('app.color.FFFFFF'))
             .margin({ left: '2%'})
-          // 扫码输入框
-          TextInput({text:this.scanCode, placeholder: '请扫描物料编码' })
+          // 扫码输入框(修复:语法格式)
+          TextInput({ text: this.scanCode, placeholder: '请扫描物料编码' })
             .type(InputType.Normal)
             .placeholderFont({ size: $r('app.float.fontSize_16') })
             .placeholderColor($r('app.color.30FFFFFF'))
             .fontSize($r('app.float.fontSize_30'))
             .fontColor($r('app.color.FFFFFF'))
             .enableKeyboardOnFocus(false)
-            .onSubmit(async () => {
-              if (this.scanState === 0) {
-                promptAction.showToast({
-                  message: '工序未开工,请先开工',
-                  duration: 1500,
-                  bottom: 100
-                })
-                return
-              }
-              let result: ProcessMaterial[] = await ProcessRequest.post('/api/v1/process/itemRecord/searchMaterial', {
-              operationId: this.selectOperationId,
-              processId: this.process.id!,
-              seqNo: this.seqNo,
-              scanCode: this.scanCode,
-              workOrderCode: this.selectWorkOder.workOrderCode!} as RequestParamModel)
-              if (result && result.length > 0) {
-                if (result[0].num! <= 0) {
-                  promptAction.showToast({
-                    message: `${result[0].batchNo!}批次物料已用完`,
-                    duration: 1500,
-                    bottom: 100
-                  })
-                }
-                this.scanMaterial = result[0]
-                for (const element of result) {
-                  element.operationId = this.selectOperationId
-                  element.processId = this.process.id!
-                  element.seqNo = this.seqNo
-                  element.workOrderCode = this.selectWorkOder.workOrderCode!
-                  element.trackBy = 'S'
-                  element.itemSeq = this.scanCode
-                }
-                if ('BATCH' === result[0].codeType!) {
-                  this.modifyMaterialNumDialogController.open()
-                } else {
-                  result[0].stationId = this.currentStationId
-                  await ProcessRequest.post('/api/v1/process/itemRecord/add', result)
-                }
-                this.queryCollectHistory()
-              }
-            })
+            .key('CATCH_FOCUS')
             .onChange((value: string) => {
               this.scanCode = value
+              // 扫码完成(换行符触发)
+              // if (value.length > 0 && value.includes('\n')) {
+              //   setTimeout(() => {
+              //     this.handleScanInput()
+              //   }, 500)
+              // }
+            })
+            .onSubmit(() => {
+              // 回车键提交
+              this.handleScanInput()
             })
         }
         .height('52.8%')
@@ -155,20 +164,14 @@ export struct MaterialCollectView {
         .borderRadius($r('app.float.virtualSize_16'))
         .backgroundColor($r('app.color.000000'))
 
+        // 采集进度统计
         Column() {
-          Text(this.realNum + '/' + this.needNum)
+          Text(`${this.realNum}/${this.needNum}`)
             .fontColor($r('app.color.FFFFFF'))
             .fontSize($r('app.float.fontSize_16'))
             .fontWeight(FontWeight.Regular)
           Row() {
-            Row()
-              .width(((this.realNum * 100)/ this.needNum).toFixed(2) + '%')
-              .height('100%')
-              .borderRadius($r('app.float.virtualSize_24'))
-              .linearGradient({
-                angle: 90,
-                colors: [[$r('app.color.1050FF'), 0.0], [$r('app.color.73C3FF'), 1]]
-              })
+            Progress({ value: this.realNum, total: this.needNum, type: ProgressType.Linear })
           }
           .height('30%')
           .width('100%')
@@ -183,9 +186,15 @@ export struct MaterialCollectView {
       .height('13.5%')
       .width('93%')
       .justifyContent(FlexAlign.SpaceBetween)
-      // 需要采集物料展示,动态排列容器
+
+      // 需要采集物料展示(修复:字符串拼接语法)
       Scroll() {
-        Flex({ wrap: FlexWrap.Wrap, direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start}) {
+        Flex({
+          wrap: FlexWrap.Wrap,
+          direction: FlexDirection.Row,
+          justifyContent: FlexAlign.Start,
+          alignItems: ItemAlign.Start
+        }) {
           ForEach(this.itemArray, (item: OperationItem, index: number) => {
             Column() {
               Row() {
@@ -195,16 +204,13 @@ export struct MaterialCollectView {
                     .fontWeight(FontWeight.Medium)
                     .fontColor($r('app.color.FFFFFF'))
                     .maxLines(1)
-                  Text(item.itemCode!)
-                    .fontSize($r('app.float.fontSize_12'))
-                    .fontWeight(FontWeight.Lighter)
-                    .fontColor($r('app.color.FFFFFF'))
-                    .maxLines(1)
                 }
                 .width('45.5%')
                 .height('100%')
                 .justifyContent(FlexAlign.Center)
                 .alignItems(HorizontalAlign.Start)
+
+                // 完成状态图标
                 Row() {
                   if (item.realNum! >= item.needNum!) {
                     Image($r('app.media.process_complete_test'))
@@ -221,17 +227,21 @@ export struct MaterialCollectView {
               .height('45.8%')
               .width('100%')
               .justifyContent(FlexAlign.End)
+
+              // 物料编码和采集数量
               Row() {
-                Text(item.codeTypeStr ? item.codeTypeStr : '')
+                Text(item.itemCode!) // 修复:空值合并替代三元表达式
                   .fontSize($r('app.float.fontSize_16'))
                   .fontWeight(FontWeight.Regular)
                   .fontColor($r('app.color.FFFFFF'))
+
                 Row() {
-                  Text((item.realNum ? item.realNum : 0) + '/')
+                  // 修复:模板字符串避免赋值表达式错误
+                  Text(`${item.realNum ?? 0}/`)
                     .fontSize($r('app.float.fontSize_38'))
                     .fontWeight(FontWeight.Lighter)
                     .fontColor($r('app.color.FFFFFF'))
-                  Text((item.needNum ? item.needNum : 0) + item.unit!)
+                  Text(`${item.needNum ?? 0}${item.unit ?? ''}`)
                     .fontSize($r('app.float.fontSize_38'))
                     .fontWeight(FontWeight.Lighter)
                     .fontColor($r('app.color.FFFFFF'))
@@ -246,32 +256,19 @@ export struct MaterialCollectView {
             .width('32.8%')
             .height('25.2%')
             .borderRadius($r('app.float.virtualSize_16'))
-            .backgroundColor($r('app.color.20FFFFFF'))
-            .margin({ top: index > 2 ? '1%' : '0%', left: (index % 3) === 0 ? '0%' : '0.8%' })
-            .onClick(()=>{
-              if (this.scanState === 0) {
-                promptAction.showToast({
-                  message: '工序未开工,请先开工',
-                  duration: 1500,
-                  bottom: 100
-                })
-                return
-              }
-              this.scanMaterial = {
-                materialCode: item.itemCode!,
-                materialName: item.itemName!,
-                spec: item.itemModel!,
-                unitDictValue: item.unit!,
-                totalNum: item.needNum!,
-              }
-              this.addOrModifyCollect = 2
-              this.modifyMaterialNumDialogController.open()
+            .backgroundColor($r('app.color.20FFFFFF'))// 替换为实际颜色值(可选)
+            .margin({
+              top: index > 2 ? '1%' : '0%',
+              left: (index % 3) === 0 ? '0%' : '0.8%'
+            })
+            .onClick(() => {
+              // 可补充物料点击逻辑(如修改数量)
             })
           })
         }
         .width('100%')
       }
-      .scrollable(ScrollDirection.Vertical) // 垂直滚动
+      .scrollable(ScrollDirection.Vertical)
       .scrollBar(BarState.Auto)
       .width('93%')
       .height('84%')
@@ -279,6 +276,6 @@ export struct MaterialCollectView {
     }
     .width('100%')
     .height('100%')
+    //.backgroundColor($r('app.color.101010')) // 补充页面背景(可选)
   }
-
 }

+ 970 - 0
entry/src/main/ets/view/process/PhotoCollectView.ets

@@ -0,0 +1,970 @@
+/*
+ * 相机控制
+ * */
+import router from '@ohos.router';
+import image from '@ohos.multimedia.image';
+import fs from "@ohos.file.fs"
+import CommonEventManager from '@ohos.commonEventManager'
+import promptAction from '@ohos.promptAction';
+import { PreviewManager } from '../../common/util/PreviewManager';
+import { ConfirmDialog } from '../ConfirmDialog';
+import { ConfirmDialogParams } from '../../viewmodel/ConfirmDialogParam';
+import OperationComponent from '../../viewmodel/process/OperationComponent';
+
+const TAG = "sony_camera info"
+
+@Component
+export struct PhotoCollectView {
+  private scrollerPhoto: Scroller = new Scroller()
+  @Link opComponents: OperationComponent[]
+  @Link index:number
+  //
+  @State isExpanded: boolean = false
+  //闪光模式 0:自动 1:开启 2:关闭
+  @State selectedFlashMode:number = 0
+  @State uploadButtonClick:number =1
+  //选择的照片索引
+  @State selectedPhotoIndex:number = -1
+  //拍照按键缩放
+  @State shootButtonClick:number =1
+  // 旋转角度
+  @State rotateAngle: number = 0
+  // 照片缩放比例
+  @State scaleValue: number = 1
+  // 照片X轴偏移
+  @State offsetX: number = 0
+  // 照片Y轴偏移
+  @State offsetY: number = 0
+  // 照片上次缩放值
+  @State lastScale: number = 1
+  // 照片上次X偏移
+  @State lastOffsetX: number = 0
+  // 照片上次Y偏移
+  @State lastOffsetY: number = 0
+  //双指缩放的中心点X
+  @State pinchCenterX: number = 0;
+  //双指缩放的中心点Y
+  @State pinchCenterY: number = 0;
+  // 照片列表
+  //@State photoList:DrawingInfo[]=[]
+  // 获取本地live照片
+  @State commodityPixelMap: PixelMap | null = null;
+  // 拍照动作是否完成
+  @State isCapturing: boolean = false;
+  // 是否上传中
+  @State isUploading: boolean = false;
+  // 是否停止预览
+  @State isStopView: boolean = false;
+  // 控制帧率
+  @State readTimer:number = 0
+  // 预览操作
+  private previewManager: PreviewManager | null = null;
+  @State photoPixelMaps: photoInfo[] = []; // 存储所有照片的 PixelMap
+
+  // 加载照片并生成 PixelMap
+  loadPhotos = async () => {
+    const context = getContext(this);
+    console.info(TAG, '开始加载照片', context.filesDir);
+    try {
+      const localImageDir = `${context.filesDir}/`;
+      // 检查目录是否存在
+      if (!fs.accessSync(localImageDir)) {
+        console.warn(TAG, "目录不存在");
+        return;
+      }
+      // 获取目录下所有文件
+      const files = fs.listFileSync(localImageDir);
+      const newPixelMaps: photoInfo[] = [];
+      // 加载所有以image_开头的图片
+      for (const file of files) {
+        // 只处理以image_开头的文件
+        if (!file.startsWith('image_') || !file.endsWith('.jpg')) {
+          continue;
+        }
+        const filePath = `${localImageDir}${file}`;
+        try {
+          const imageSource = image.createImageSource(filePath);
+          const imageInfo = await imageSource.getImageInfo();
+          const scaleRatio = Math.min(600 / imageInfo.size.width, 800 / imageInfo.size.height);
+
+          const thumbnailOpts: image.InitializationOptions = {
+            size: {
+              width: Math.floor(imageInfo.size.width * scaleRatio),
+              height: Math.floor(imageInfo.size.height * scaleRatio)
+            }
+          }
+          const pixelMap = await imageSource.createPixelMap(thumbnailOpts);
+          const timestamp = this.parseTimestampFromFilename(file);
+          newPixelMaps.push({
+            pixelMap: pixelMap,
+            timestamp: timestamp,
+            filename: file
+          });
+          imageSource.release();
+        } catch (err) {
+          console.error(TAG, `加载图片 ${file} 失败:`, err);
+        }
+      }
+      // 按时间戳降序排序
+      newPixelMaps.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
+      this.photoPixelMaps = newPixelMaps;
+    } catch (err) {
+      console.error(TAG, "加载照片失败:", err);
+    }
+  };
+  private parseTimestampFromFilename(filename: string): string {
+    if (!filename.startsWith("image_") || !filename.endsWith(".jpg")) {
+      return "";
+    }
+    const dateTimePart = filename.substring(6, filename.length - 4);
+    if (dateTimePart.length !== 15) {
+      return "";
+    }
+    const datePart = dateTimePart.substring(0, 8);
+    const timePart = dateTimePart.substring(9);
+    const year = datePart.substring(0, 4);
+    const month = datePart.substring(4, 6);
+    const day = datePart.substring(6, 8);
+    const hour = timePart.substring(0, 2);
+    const minute = timePart.substring(2, 4);
+    const second = timePart.substring(4);
+    return `${year}/${month}/${day} ${hour}:${minute}:${second}`;
+  }
+
+  private releaseAllPixelMaps() {
+    this.photoPixelMaps.forEach(item => item.pixelMap?.release());
+    this.photoPixelMaps = [];
+  }
+
+
+  // 删除照片
+  deletePhoto = async (index: number) => {
+    try {
+      const context = getContext(this);
+      const photoToDelete = this.photoPixelMaps[index];
+      const filePath = `${context.filesDir}/${photoToDelete.filename}`;
+
+      console.info(TAG, `要删除文件: ${filePath}`);
+
+      // 1. 删除物理文件
+      fs.unlinkSync(filePath);
+      console.info(TAG, `已删除文件: ${filePath}`);
+
+      // 2. 释放PixelMap资源
+      photoToDelete.pixelMap.release();
+
+      // 3. 从数组中移除
+      const newPhotoList = [...this.photoPixelMaps];
+      newPhotoList.splice(index, 1);
+      this.photoPixelMaps = newPhotoList;
+
+      // 4. 处理选中的照片索引
+      if (this.photoPixelMaps.length === 0) {
+        // 如果所有照片都删完了
+        this.selectedPhotoIndex = -1;
+        this.startView();
+      } else {
+        // 还有照片剩余的情况
+        if (this.selectedPhotoIndex === index) {
+          // 当前删除的是正在显示的照片
+          if (index > 0) {
+            // 如果不是第一张,显示前一张
+            this.selectedPhotoIndex = index - 1;
+          } else {
+            // 如果是第一张,显示下一张(现在index=0,所以下一张也是0)
+            this.selectedPhotoIndex = 0;
+          }
+        } else if (this.selectedPhotoIndex > index) {
+          // 删除的照片在当前显示照片之前,需要调整索引
+          this.selectedPhotoIndex -= 1;
+        }
+        // 如果删除的照片在当前显示照片之后,不需要调整索引
+      }
+
+      promptAction.showToast({
+        message: '照片删除成功',
+        duration: 2000
+      });
+    } catch (err) {
+      console.error(TAG, "删除照片失败:", err.code);
+      promptAction.showToast({
+        message: '删除照片失败',
+        duration: 2000
+      });
+    }
+  };
+
+  //创建订阅者
+  subscriber: CommonEventManager.CommonEventSubscriber | null = null;
+  //订阅相机回调
+  subscribeInfo: CommonEventManager.CommonEventSubscribeInfo = { events: ["sonycamera_callback"] };
+
+  //提示确认弹窗
+  commonDialogController: CustomDialogController | null = null;
+  async showConfirmDialog(params: ConfirmDialogParams) {
+    if (this.commonDialogController) {
+      this.commonDialogController.close()
+    }
+
+    this.commonDialogController = new CustomDialogController({
+      builder: ConfirmDialog({
+        title: params.title || '提示',
+        message: params.message,
+        onConfirm: params.onConfirm
+      }),
+      cancel: () => console.log('用户取消操作'),
+      customStyle: true,
+      autoCancel:false,
+      maskColor: 'rgba(0,0,0,0.6)'
+    });
+
+    this.commonDialogController.open();
+  }
+
+  //订阅回调(code=3代表连接成功,code=2代表拍照成功)
+  createSubscriber = async () => {
+    this.subscriber = await CommonEventManager.createSubscriber(this.subscribeInfo);
+    if (this.subscriber) {
+      console.info(TAG, "创建订阅回调成功");
+      CommonEventManager.subscribe(this.subscriber, (err, data) => {
+        if (err?.code) {
+          console.error(TAG, "SubscribeCallBack err=" + JSON.stringify(err));
+          return;
+        }
+        console.info(TAG, "SubscribeCallBack data=" + JSON.stringify(data));
+        if (data?.code !== undefined) {
+          switch (data.code) {
+            case 2:
+              this.loadPhotos()
+              this.isCapturing =false
+              this.startView(); // 拍照成功
+              break;
+            case 3:
+              console.info(TAG, "开始预览");
+              this.startView(); // 连接成功
+              break;
+            case -1:
+              console.info(TAG,'连接故障')
+              break;
+            case 5:
+              console.info(TAG,'暂停预览')
+              break;
+          }
+        }
+        //0001:自动闪光 0002:关闭闪光 0003:开启闪光
+        if (data?.parameters?.flash_mode) {
+          const flashMode:string = data.parameters.flash_mode
+          console.info(TAG, `收到闪光模式: ${flashMode}`);
+          switch (flashMode) {
+            case '0001':
+              this.selectedFlashMode = 0
+              break;
+            case '0002':
+              this.selectedFlashMode = 2
+              break;
+            case '0003':
+              this.selectedFlashMode = 1
+              break;
+            default:
+              console.warn(TAG, `未知闪光模式: ${flashMode}`);
+          }
+        }
+      });
+    }
+  };
+
+
+  //旋转照片
+  private rotateImage(angle: number) {
+    this.offsetX = 0;
+    this.offsetY = 0;
+    this.rotateAngle += angle
+    if (this.rotateAngle >= 360) {
+      this.rotateAngle -= 360
+    } else if (this.rotateAngle < 0) {
+      this.rotateAngle += 360
+    }
+    if(this.rotateAngle==90||this.rotateAngle==270)
+    {
+      this.scaleValue=0.667
+    }else {
+      this.scaleValue=1
+    }
+  }
+
+  // 重置图片变换
+  private resetImageTransform() {
+    this.rotateAngle = 0
+    this.scaleValue = 1
+    this.offsetX = 0
+    this.offsetY = 0
+    this.lastScale = 1
+    this.lastOffsetX = 0
+    this.lastOffsetY = 0
+  }
+
+  //连接相机
+  connectCamera = async () => {
+    CommonEventManager.publish("opensession", (err) => {
+      if (err?.code) {
+        console.info(TAG,"Publish openSession err=" + JSON.stringify(err))
+      } else {
+        console.info(TAG,"Publish openSession succeed ")
+        this.queryFlashMode();
+      }
+    })
+  }
+  //查询闪光模式
+  queryFlashMode = async () => {
+    CommonEventManager.publish("queryflashmode", (err) => {
+      if (err?.code) {
+        console.info(TAG,"Publish queryflashmode err=" + JSON.stringify(err))
+      } else {
+        console.info(TAG,"Publish queryflashmode succeed ")
+      }
+    })
+  }
+
+  //开始预览
+  startView=async()=>{
+    CommonEventManager.publish("startview", (err) => {
+      if (err?.code) {
+        console.error(TAG, JSON.stringify(err));
+      } else {
+        console.info(TAG, 'publish startview succeed');
+        this.isStopView =false;
+        this.liveShow();
+      }
+    });
+  }
+
+  //停止预览
+  stopView=async()=>{
+    CommonEventManager.publish("stopview", (err) => {
+      if (err?.code) {
+        console.error(TAG, JSON.stringify(err));
+      } else {
+        this.isStopView =true;
+        console.info(TAG, 'publish stopview succeed');
+        if (this.readTimer) {
+          clearInterval(this.readTimer);
+          this.readTimer = 0 ;
+        }
+      }
+    });
+  }
+
+  //重连相机
+  reconnectCamera=async()=>{
+    this.showConfirmDialog({
+      title: '重连USB',
+      message: `请重连USB后点击确定!`,
+      onConfirm: async()=> {
+        await new Promise<void>((resolve, reject) => {
+          CommonEventManager.publish("stopview", (err) => {
+            if (err) return reject(err);
+            CommonEventManager.publish("closesession", (err) => {
+              err ? reject(err) : resolve();
+            });
+          });
+        });
+        await new Promise<void>((resolve, reject) => {
+          CommonEventManager.publish("reconnect", (err) => {
+            if (err) return reject(err);
+            resolve();
+          });
+        });
+        promptAction.showToast({
+          message: '相机正在重连中...',
+          duration: 3000,
+          bottom: 500
+        });
+        await sleep(3000);
+        await this.connectCamera()
+        //await this.liveShow()
+      }
+    });
+  }
+
+  liveShow = async () => {
+    let index = 0;
+    let retryCount = 0;
+    const MAX_RETRIES = 1000; // 最大重试次数
+
+    const previewLoop = async () => {
+      if (!this.isStopView && !this.isCapturing) {
+        try {
+          const success = await this.previewManager!.processFrame(index);
+          if (success) {
+            this.commodityPixelMap = await this.previewManager!.getActiveBuffer();
+            retryCount = 0;
+          } else {
+            retryCount++;
+            console.warn(TAG, "processFrame失败");
+          }
+        } catch (error) {
+          retryCount++;
+          console.warn(TAG, "预览更新失败:", error);
+        }
+      }
+
+      if (retryCount === MAX_RETRIES) {
+          clearInterval(this.readTimer)
+          this.readTimer = 0;
+          console.info(TAG,"GG")
+          return;
+          //this.reconnectCamera();
+      }
+      if (this.readTimer !== 0) { // 检查是否应该继续循环
+        this.readTimer = setTimeout(previewLoop, 50);
+      }
+    };
+
+    this.readTimer = setTimeout(previewLoop, 50);
+  };
+
+  //断开相机(停止预览->关闭连接)
+  disconnectCamera = async () => {
+    if(!this.isStopView)
+    {
+     await this.stopView()
+    }
+    CommonEventManager.publish("closesession", (err) => {
+      if (err?.code) {
+        console.info(TAG,"Publish closesession err=" + JSON.stringify(err))
+      } else {
+        console.info(TAG,"Publish closesession succeed ")
+      }
+    })
+  }
+
+  //拍照(停止预览->拍照->开始预览)
+  takePhoto = async () => {
+    this.isStopView = true;
+    this.isCapturing = true;
+    CommonEventManager.publish("stopview", (err) => {
+      if (err?.code) {
+        console.info(TAG,"Publish stopview err=" + JSON.stringify(err));
+      } else {
+        console.info(TAG,"Publish Publish stopview succeed");
+        CommonEventManager.publish("shootandsave", (err) => {
+          if (err?.code) {
+            console.info(TAG,"Publish  shootandsave error=" + JSON.stringify(err));
+          } else {
+            console.info(TAG,"Publish Publish shootandsave succeed");
+          }
+        });
+      }
+    });
+  };
+
+  //设置闪光模式
+  setFlashMode = (mode: 'openflash' | 'closeflash' | 'autoflash') => {
+    this.isStopView = true;
+    CommonEventManager.publish("stopview", (err) => {
+      if (err?.code) {
+        console.info(TAG,"Publish stopview err=" + JSON.stringify(err));
+      } else {
+        console.info(TAG,"Publish Publish stopview succeed");
+        CommonEventManager.publish(mode, (err) => {
+          if (err?.code) {
+            console.info(TAG,"Publish  flashmode error=" + JSON.stringify(err));
+          } else {
+            console.info(TAG,"Publish Publish flashmode succeed");
+            CommonEventManager.publish("startview", (err) => {
+              this.isStopView = false;
+              if (err?.code) {
+                console.info(TAG,"Publish  startview error=" + JSON.stringify(err));
+              }else{
+                console.info(TAG,"Publish Publish startview succeed");
+              }
+            })
+          }
+        });
+      }
+    });
+  }
+
+  private adjustOffsetWithAnimation() {
+    const isRotated = (this.rotateAngle === 90 || this.rotateAngle === 270);
+    //旋转90度或者70度  宽度0.667倍,长度超过1.5倍才拖动
+    let moveScaleY = (this.scaleValue - (isRotated ? 0.667 : 1)) / 2;
+    let moveScaleX = (this.scaleValue - (isRotated ? 1.50 : 1)) / 2;
+    let maxOffsetX = (this.scaleValue<1.5&&isRotated) ?this.offsetX: (isRotated ? 506 : 760) * moveScaleX;
+    let maxOffsetY = (isRotated ? 760 : 506) * moveScaleY; //rk3588
+    // let maxOffsetX = (this.scaleValue<1.5&&isRotated) ?this.offsetX: (isRotated ? 1018 : 1524) * moveScaleX;
+    // let maxOffsetY = (isRotated ? 1524 : 1018) * moveScaleY; //rk3568
+    //console.info(TAG,"maxOffsetX",maxOffsetX,"scale",this.scaleValue,"offsetx",this.offsetX)
+    const clampedX = Math.max(-maxOffsetX, Math.min(maxOffsetX, this.offsetX));
+    const clampedY = Math.max(-maxOffsetY, Math.min(maxOffsetY, this.offsetY));
+    if (this.offsetX !== clampedX || this.offsetY !== clampedY) {
+      animateTo({
+        duration: 100,
+        curve: Curve.EaseOut
+      }, () => {
+        this.offsetX = clampedX;
+        this.offsetY = clampedY;
+      });
+    }
+  }
+
+  //上传照片
+  uploadPhoto=()=>{
+
+  }
+  async aboutToAppear() {
+    this.previewManager = new PreviewManager(getContext(this));
+    this.loadPhotos();
+    await this.createSubscriber();
+    await sleep(50)
+    await this.connectCamera();
+  }
+
+  aboutToDisappear(): void {
+    this.disconnectCamera()
+    if (this.previewManager) {
+      this.previewManager.release();
+      this.previewManager = null
+    }
+    if (this.subscriber) {
+      CommonEventManager.unsubscribe(this.subscriber);
+    }
+    this.releaseAllPixelMaps()
+    if (this.commodityPixelMap) {
+      this.commodityPixelMap.release();
+      this.commodityPixelMap = null;
+    }
+  }
+  build() {
+    Row() {
+      Stack(){
+        if (this.commodityPixelMap) {
+          if (this.selectedPhotoIndex === -1) {
+            Image(this.commodityPixelMap)
+              .width('100%')
+              .height('100%')
+              .objectFit(ImageFit.Fill)
+          }
+        }
+        if(this.isCapturing||this.isUploading){
+          Column() {
+            Text(this.isCapturing?'正在拍照中...':"正在上传中...")
+              .fontSize($r('app.float.fontSize_30'))
+              .margin({bottom:'10%'})
+            LoadingProgress()
+              .color(Color.Blue)
+              .width('25%')
+              .width('25%')
+          }
+          .height('30%')
+          .width('25%')
+          .backgroundColor(Color.White)
+          .borderRadius($r('app.float.virtualSize_16'))
+          .justifyContent(FlexAlign.Center)
+        }
+        if(this.selectedPhotoIndex === -1){
+          Row() {
+            Image(
+              this.selectedFlashMode === 0 ? $r('app.media.process_flash_auto') :
+                this.selectedFlashMode === 1 ? $r('app.media.process_flash_open') :
+                $r('app.media.process_flash_close')
+            )
+              .width($r('app.float.virtualSize_48'))
+              .height($r('app.float.virtualSize_48'))
+              .enabled(!this.isCapturing)
+              .onClick(() => {
+                this.isExpanded = !this.isExpanded
+              })
+              .margin({right:'5%'})
+            if (this.isExpanded) {
+              Row() {
+                Row(){
+                  Text('自动')
+                    .fontSize($r('app.float.fontSize_24'))
+                    .fontColor(this.selectedFlashMode===0?$r('app.color.FFFFFF'):$r('app.color.60FFFFFF'))
+                }
+                .width('33.3%')
+                .height('100%')
+                .justifyContent(FlexAlign.Center)
+                .borderRadius($r('app.float.virtualSize_16'))
+                .backgroundColor(this.selectedFlashMode===0?$r('app.color.0A84FF'):$r('app.color.60000000'))
+                .onClick(() => {
+                  this.setFlashMode('autoflash')
+                  this.isExpanded = false
+                  this.selectedFlashMode = 0
+                })
+                Row(){
+                  Text('开启')
+                    .fontSize($r('app.float.fontSize_24'))
+                    .fontColor(this.selectedFlashMode===1?$r('app.color.FFFFFF'):$r('app.color.60FFFFFF'))
+                }
+                .width('33.3%')
+                .height('100%')
+                .justifyContent(FlexAlign.Center)
+                .borderRadius($r('app.float.virtualSize_16'))
+                .backgroundColor(this.selectedFlashMode===1?$r('app.color.0A84FF'):$r('app.color.60000000'))
+                .onClick(() => {
+                  this.setFlashMode('openflash')
+                  this.isExpanded = false
+                  this.selectedFlashMode = 1
+                })
+
+                Row(){
+                  Text('关闭')
+                    .fontSize($r('app.float.fontSize_24'))
+                    .fontColor(this.selectedFlashMode===2?$r('app.color.FFFFFF'):$r('app.color.60FFFFFF'))
+                }
+                .width('33.3%')
+                .height('100%')
+                .justifyContent(FlexAlign.Center)
+                .borderRadius($r('app.float.virtualSize_16'))
+                .backgroundColor(this.selectedFlashMode===2?$r('app.color.0A84FF'):$r('app.color.60000000'))
+                .onClick(() => {
+                  this.setFlashMode('closeflash')
+                  this.isExpanded = false
+                  this.selectedFlashMode = 2
+                })
+              }
+              .animation({ duration: 300, curve: Curve.EaseOut })
+              .backgroundColor($r('app.color.60000000'))
+              .borderRadius($r('app.float.virtualSize_16'))
+              .width('85%')
+              .height('100%')
+            }
+          }
+          .justifyContent(FlexAlign.Start)
+          .alignItems(VerticalAlign.Bottom)
+          .position({ x: '2%', y: '92%' })
+          .height('5%')
+          .width('24%')
+          Image(this.shootButtonClick===1?$r('app.media.process_no_shoot'):$r('app.media.process_shoot'))
+            .width($r('app.float.virtualSize_88'))
+            .height($r('app.float.virtualSize_88'))
+            .scale({ x: this.shootButtonClick, y: this.shootButtonClick })
+            .borderRadius($r('app.float.fontSize_16'))
+            .enabled(!this.isCapturing)
+            .animation({
+              duration: 200,
+              curve: Curve.Linear
+            })
+            .onClick(() => {
+              this.shootButtonClick = 0.9;
+              setTimeout(() => {
+                this.shootButtonClick = 1;
+              }, 200);
+              this.takePhoto();
+            })
+            .position({ x: '48%', y: '90%' })
+          Row(){
+            Text("重连相机")
+              .fontColor($r('app.color.FFFFFF'))
+              .fontSize($r('app.float.fontSize_24'))
+          }
+          .width('10%')
+          .height('6%')
+          .backgroundColor($r('app.color.60000000'))
+          .position({ x: '88%', y: '91%' })
+          .borderRadius($r('app.float.virtualSize_16'))
+          .enabled(!this.isCapturing)
+          .justifyContent(FlexAlign.Center)
+          .onClick(()=>{
+            this.reconnectCamera()
+          })
+        }
+        else{
+          Stack() {
+            Image(this.photoPixelMaps[this.selectedPhotoIndex].pixelMap)
+              .width('100%')
+              .height('100%')
+              .autoResize(true)
+              // .onComplete((event) => {
+              //   console.info(TAG,"width:"+event!.componentWidth +"height:"+ event!.componentHeight)
+              // })  // 获取Image组件的长宽(除以1.5获取vp)
+              .objectFit(ImageFit.Fill)
+              .rotate({ angle: this.rotateAngle })
+              .scale({ x: this.scaleValue, y: this.scaleValue })
+              .borderRadius($r('app.float.virtualSize_16'))
+              .translate({ x: this.offsetX, y: this.offsetY })
+              .gesture(
+                GestureGroup(GestureMode.Exclusive,
+                  PinchGesture()
+                    .onActionStart((event: GestureEvent) => {
+                      this.lastScale = this.scaleValue;
+                      this.lastOffsetX = this.offsetX;
+                      this.lastOffsetY = this.offsetY;
+                      // 记录双指中心点(相对于图片中心)
+                      this.pinchCenterX = event.pinchCenterX - 380 - 760 / 2;//rk3588
+                      this.pinchCenterY = event.pinchCenterY - 130 - 506 / 2;//rk3588
+                      // this.pinchCenterX = event.pinchCenterX - 1016 / 2; //rk3568
+                      // this.pinchCenterY = event.pinchCenterY - 678 / 2; //rk3568
+                     // console.info(TAG,this.pinchCenterX,TAG,this.pinchCenterY)
+                    })
+                    .onActionUpdate((event: GestureEvent) => {
+                      let newScale = this.lastScale * event.scale;
+                      //保持双指中心点不变
+                      const scaleRatio = newScale / this.lastScale;
+                      const newOffsetX = this.lastOffsetX + (1 - scaleRatio) * this.pinchCenterX;
+                      const newOffsetY = this.lastOffsetY + (1 - scaleRatio) * this.pinchCenterY;
+
+                      this.offsetX = newOffsetX;
+                      this.offsetY = newOffsetY;
+                      this.scaleValue = newScale;
+                    })
+                    .onActionEnd(() => {
+                      // 缩放最小比例为1
+                      if (this.scaleValue < 1) {
+                        // 旋转90°或者270°的最小缩小比例为0.667
+                        if(this.rotateAngle==90||this.rotateAngle==270) {
+                          if(this.scaleValue<0.667){
+                            this.scaleValue = 0.667
+                          }
+                        } else {
+                          this.scaleValue = 1
+                        }
+                      }
+                      // 缩放最大比例为3
+                      if (this.scaleValue > 3) this.scaleValue = 3
+                     this.adjustOffsetWithAnimation()
+                    }),
+
+                  // 单指滑动手势
+                  PanGesture()
+                    .onActionStart(() => {
+                      if(this.rotateAngle === 90 || this.rotateAngle === 270)
+                      {
+                        if (this.scaleValue <= 0.667)
+                        {
+                          return;
+                        }
+                      }else{
+                        if (this.scaleValue <= 1) return;
+                      }
+                      this.lastOffsetX = this.offsetX;
+                      this.lastOffsetY = this.offsetY;
+                    })
+                    .onActionUpdate((event: GestureEvent) => {
+                      if(this.rotateAngle === 90 || this.rotateAngle === 270)
+                      {
+                        if (this.scaleValue <= 0.667)
+                        {
+                          return;
+                        }
+                      }else{
+                        if (this.scaleValue <= 1) return;
+                      }
+                      let dx = event.offsetX;
+                      let dy = event.offsetY;
+                      const sensitivity = 0.5 * this.scaleValue;
+                      // 临时计算新位置
+                      let newOffsetX = this.lastOffsetX;
+                      let newOffsetY = this.lastOffsetY;
+                      newOffsetX += dx * sensitivity;
+                      newOffsetY += dy * sensitivity;
+                      this.offsetX = newOffsetX;
+                      this.offsetY = newOffsetY;
+                      //console.info(TAG,this.offsetX,TAG,this.offsetY)
+                    })
+                    .onActionEnd(() => {
+                      const isRotated = (this.rotateAngle === 90 || this.rotateAngle === 270);
+                      if(isRotated)
+                      {
+                        if(this.scaleValue<=1.5)
+                        {
+                          this.offsetX = 0
+                        }
+                      }else{
+                        if (this.scaleValue <= 1) {
+                          // 如果缩放比例<=1,直接重置位置
+                          this.offsetX = 0;
+                          this.offsetY = 0;
+                          return;
+                        }
+                      }
+                      this.adjustOffsetWithAnimation()
+                    })
+                )
+              )
+          }
+          .width('100%')
+          .height('100%')
+          .borderRadius($r('app.float.virtualSize_16'))
+          .clip(true)
+          Row()
+          {
+            Row(){
+              Image($r('app.media.process_back_camera'))
+                .width($r('app.float.virtualSize_80'))
+                .height($r('app.float.virtualSize_80'))
+                .onClick(()=>{
+                  this.selectedPhotoIndex=-1
+                  this.startView()
+                })
+            }
+            .width('10%')
+            .justifyContent(FlexAlign.Start)
+            Row({space:20}){
+              Image($r("app.media.process_photo_reset"))
+                .width($r('app.float.virtualSize_80'))
+                .height($r('app.float.virtualSize_80'))
+                .onClick(()=>{
+                  this.resetImageTransform()
+                })
+              Image($r('app.media.process_photo_turn_left'))
+                .width($r('app.float.virtualSize_80'))
+                .height($r('app.float.virtualSize_80'))
+                .onClick(()=>{
+                  this.rotateImage(-90)
+                })
+              Image($r('app.media.process_photo_turn_right'))
+                .width($r('app.float.virtualSize_80'))
+                .height($r('app.float.virtualSize_80'))
+                .onClick(()=>{
+                  this.rotateImage(90)
+                })
+              Image($r('app.media.process_photo_delete'))
+                .width($r('app.float.virtualSize_80'))
+                .height($r('app.float.virtualSize_80'))
+                .onClick(()=>{
+                  this.showConfirmDialog({
+                    title: '删除照片',
+                    message: `确定要删除照片吗?`,
+                    onConfirm: ()=> {
+                      this.deletePhoto(this.selectedPhotoIndex);
+                    }
+                  });
+                })
+            }.width('88%')
+            .justifyContent(FlexAlign.End)
+            .margin({right :'2%'})
+          }.width('98%')
+          .height('10%')
+          .position({x:'2%',y:'90%'})
+        }
+      }
+      .width('86%')
+      .height('100%')
+      .backgroundColor($r('app.color.000000'))
+      .border({width:2})
+      Column(){
+        List({ space: 8,scroller:this.scrollerPhoto }) {
+          ForEach(this.photoPixelMaps, (item:photoInfo, index) => {
+            ListItem() {
+              Column({space:4}){
+                Column(){
+                  Image(item.pixelMap)
+                    .objectFit(ImageFit.Fill)
+                    .borderRadius($r('app.float.virtualSize_16'))
+                    .height('97%')
+                    .width('98%')
+                    .opacity(index === this.selectedPhotoIndex ? 0.8 : 1)  // 20% 透明度
+                  Text(item.timestamp)
+                    .fontSize($r('app.float.fontSize_12'))
+                    .fontColor($r('app.color.FFFFFF'))
+                    .width('100%')
+                    .textAlign(TextAlign.Start)
+                }
+                .backgroundColor(index === this.selectedPhotoIndex ? $r('app.color.30D158') : '')
+                .width('90%')
+                .justifyContent(FlexAlign.Center)
+                .alignItems(HorizontalAlign.Center)
+                .borderRadius($r('app.float.virtualSize_16'))
+                .height('85%')
+                // Text(`${item.updated}`)
+                //   .fontSize($r('app.float.fontSize_12'))
+                //   .fontColor($r('app.color.FFFFFF'))
+                //   .width('90%')
+                //   .textAlign(TextAlign.Start)
+              }
+              .width('100%')
+              .height('100%')
+              .justifyContent(FlexAlign.Start)
+              .alignItems(HorizontalAlign.Center)
+              .enabled(!this.isCapturing)
+              .onClick(()=>{
+                this.selectedPhotoIndex = index;
+                this.resetImageTransform()
+                this.stopView();
+
+              })
+            }.height('19%')
+            .margin({bottom:'2%'})
+          })
+        }
+        .width('100%')
+        .margin({top:'2%',bottom:'2%'})
+        .height('88.6%')
+        Row({space: 4}) {
+          Image($r("app.media.error_upload"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+          Text('上传照片')
+            .fontColor($r('app.color.0A84FF'))
+            .fontSize($r('app.float.fontSize_24'))
+            .fontWeight(FontWeight.Medium)
+        }
+        .width('90%')
+        .height('7.4%')
+        .justifyContent(FlexAlign.Center)
+        .backgroundColor($r('app.color.20FFFFFF'))
+        .borderRadius($r('app.float.fontSize_16'))
+        .scale({ x: this.uploadButtonClick, y: this.uploadButtonClick })
+        .animation({
+          duration: 200,
+          curve: Curve.Linear
+        })
+        .onClick(async()=>{
+          this.uploadButtonClick = 0.9;
+          setTimeout(() => {
+            this.uploadButtonClick = 1;
+          }, 200);
+          if(this.photoPixelMaps.length===0) {
+            promptAction.showToast({
+              message: '上传列表为空',
+              duration: 1500,
+              bottom: 100
+            })
+            return
+          }
+          await this.showConfirmDialog({
+            title: '上传确认',
+            message: `是否上传所有照片!`,
+            onConfirm: async()=> {
+              this.isUploading = true
+              await sleep(3000);
+              this.isUploading = false
+              await this.showConfirmDialog({
+                title: '工步确认',
+                message: `图像采集收否已完成?`,
+                onConfirm: async()=> {
+                  this.opComponents[this.index].isComplete=true
+                  this.index++
+                  this.disconnectCamera();
+                }
+              });
+              //await this.liveShow()
+            }
+          });
+        })
+      }
+      .width('14%')
+      .height('100%')
+    }
+    .width('100%')
+    .height('100%')
+    .backgroundColor($r('app.color.10FFFFFF'))
+    .borderRadius($r('app.float.virtualSize_16'))
+    .borderWidth(4)
+  }
+}
+
+function sleep(ms: number): Promise<void> {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
+
+
+
+interface photoInfo {
+  pixelMap: PixelMap;
+  timestamp: string;
+  filename: string;
+}

+ 137 - 0
entry/src/main/ets/view/process/RecordItemsView.ets

@@ -0,0 +1,137 @@
+import ProcessRequest from '../../common/util/request/ProcessRequest'
+import OperationItem from '../../viewmodel/OperationItem'
+import ProcessInfo from '../../viewmodel/process/ProcessInfo'
+import ProcessMaterial from '../../viewmodel/process/ProcessMaterial'
+import RequestParamModel from '../../viewmodel/RequestParamModel'
+import WorkOrderInfo from '../../viewmodel/WorkOrderInfo'
+import promptAction from '@ohos.promptAction'
+import { ModifyMaterialNumDialog } from '../ModifyMaterialNumDialog'
+import PageInfo from '../../viewmodel/PageInfo'
+import OperationComponent from '../../viewmodel/process/OperationComponent'
+import RecordItem from '../../viewmodel/process/RecordItem'
+import { RecordItemDialog } from '../RecordItemDialog'
+
+// 补充缺失的UI相关导入(根据实际项目调整)
+
+
+// 物料采集工序
+@Component
+export struct RecordItemsView {
+  @Link recordItems:RecordItem[]
+  @State isEditRecord:boolean = false
+  @State selectRecordItem:RecordItem={}
+  @State selectDefectIndex :number = -1
+  @Link opComponents: OperationComponent[]
+  @Link index:number
+  aboutToAppear() {
+
+  }
+
+
+  build() {
+    Column() {
+      Row() {
+        Text('记录项')
+          .fontSize($r('app.float.fontSize_24'))
+          .fontWeight(FontWeight.Medium)
+          .fontColor($r('app.color.FFFFFF'))
+      }
+      .height('10%')
+      .width('96%')
+      // 不良类型记录列表
+      List({space: 6}) {
+        ForEach(this.recordItems, (item: RecordItem, index: number) => {
+          ListItem() {
+            Column() {
+              Text('标题:'+(item.title ? item.title!: ''))
+                .fontColor($r('app.color.FFFFFF'))
+                .fontSize($r('app.float.fontSize_16'))
+                .fontWeight(FontWeight.Bold)
+                .height($r('app.float.virtualSize_48'))
+              Text('内容:' + (item.content ? item.content : ''))
+                .fontColor($r('app.color.FFFFFF'))
+                .fontSize($r('app.float.fontSize_16'))
+                .fontWeight(FontWeight.Lighter)
+                .padding({bottom: 10})
+            }
+            .width('92%')
+            .alignItems(HorizontalAlign.Start)
+          }
+          .backgroundColor($r('app.color.20FFFFFF'))
+          .borderRadius($r('app.float.fontSize_16'))
+          .width('100%')
+          .onClick(()=>{
+            this.selectDefectIndex = index;
+            this.selectRecordItem = item;
+            this.isEditRecord = true;
+            this.recordController.open()
+
+          })
+        })
+      }
+      .width('90%')
+      .height('80%')
+      .alignListItem(ListItemAlign.Center)
+      .margin({top: 10})
+
+      Row(){
+
+        Row() {
+          Image($r('app.media.general_add'))
+            .width($r('app.float.virtualSize_32'))
+            .height($r('app.float.virtualSize_32'))
+            .fillColor($r('app.color.0A84FF'))
+        }
+        .height('100%')
+        .width('40%')
+        .margin({left:'30%'})
+        .borderRadius($r('app.float.virtualSize_16'))
+        .backgroundColor($r('app.color.20FFFFFF'))
+        .justifyContent(FlexAlign.Center)
+        .onClick(()=>{
+          this.isEditRecord = false;
+          this.recordController.open()
+
+        })
+        Row({space: 4}) {
+          Image($r("app.media.next_step"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+            .fillColor($r('app.color.0A84FF'))
+          Text('下一步')
+            .fontColor($r('app.color.0A84FF'))
+            .fontSize($r('app.float.fontSize_24'))
+            .fontWeight(FontWeight.Medium)
+        }
+        .width('10%')
+        .height('100%')
+        .justifyContent(FlexAlign.Center)
+        .margin({left:'10%'})
+        .backgroundColor($r('app.color.20FFFFFF'))
+        .borderRadius($r('app.float.fontSize_16'))
+        .onClick(()=>{
+          this.opComponents[this.index].isComplete=true
+          this.index++
+
+        })
+      } .height('7.1%')
+      .width('100%')
+    }
+    .width('100%')
+    .height('100%')
+  }
+
+
+  recordController: CustomDialogController = new CustomDialogController({
+    builder: RecordItemDialog({
+      isEdit: this.isEditRecord,
+      recordItems:this.recordItems,
+      recordItem:this.isEditRecord ? this.selectRecordItem : {},
+      RecordIndex:this.selectDefectIndex,
+    }),
+    autoCancel: true, // 点击遮罩关闭
+    customStyle: true,
+    alignment:DialogAlignment.Center,
+    maskColor: 'rgba(0,0,0,0.8)',  // 黑色遮罩
+  })
+}

+ 170 - 0
entry/src/main/ets/view/process/ScanStartWorkView.ets

@@ -0,0 +1,170 @@
+import {LoginStatus} from '../../viewmodel/process/EnumerationType'
+import CardReader from '../../viewmodel/device/CardReader'
+import {ProcessStatus} from '../../viewmodel/process/EnumerationType'
+@Component
+export struct ScanStartWorkView {
+  @State LoginStatus: LoginStatus = LoginStatus.INITIAL
+  @StorageProp('CardReader') cardReader: CardReader = {}
+  @State isConnected: boolean = false
+  @Link currentProcessStatus: ProcessStatus
+  @Link selectComponentID:number
+  private timerId: number = 0
+  // 根据状态获取提示文字
+  getStatusText(): string {
+    switch (this.LoginStatus) {
+      case LoginStatus.INITIAL:
+        return "请使用工作卡贴近读卡器"
+      case LoginStatus.SUCCESS:
+        return "开工成功!"
+      case LoginStatus.LOGGING_IN:
+        return "正在验证中..."
+      case LoginStatus.FAILED:
+        return "验证失败,请重试"
+      default:
+        return "请使用工作卡贴近读卡器"
+    }
+  }
+
+  private delay(ms: number): Promise<void> {
+    return new Promise((resolve) => setTimeout(resolve, ms));
+  }
+
+  timerIds(): void {
+
+    this.timerId = setInterval(async (): Promise<void> => {  // 添加 async
+      const rfidCard = (this.cardReader.RfidCardNum1 || '') + (this.cardReader.RfidCardNum2 || '');
+      console.info("sssssss121"+rfidCard)
+      if (rfidCard === '') {
+        this.LoginStatus = LoginStatus.INITIAL;
+        return;
+      }
+      this.LoginStatus = LoginStatus.LOGGING_IN;
+
+      // 使用 await
+      await this.delay(1500);
+
+      if (rfidCard === '3b530bb') {
+        this.LoginStatus = LoginStatus.SUCCESS;
+        // 等待1秒显示成功状态
+        await this.delay(1000);
+        this.navigateToTarget();
+        this.currentProcessStatus = ProcessStatus.START
+        this.selectComponentID = 0;
+      } else {
+        this.LoginStatus = LoginStatus.FAILED;
+        // 等待1秒显示失败状态
+        await this.delay(1000);
+        this.LoginStatus = LoginStatus.INITIAL;
+      }
+    }, 3000);
+  }
+
+  private navigateToTarget(): void {
+    clearInterval(this.timerId);
+    this.timerId = 0;
+  }
+
+  aboutToAppear(): void {
+    this.LoginStatus = LoginStatus.INITIAL
+    this.timerIds()
+  }
+
+  getStatusImage(): Resource {
+    switch (this.LoginStatus) {
+      case LoginStatus.INITIAL:
+        return $r("app.media.id_card_white")
+      case LoginStatus.SUCCESS:
+        return $r("app.media.id_card_green")
+      case LoginStatus.FAILED:
+        return $r("app.media.id_card_red") // 需要你有对应的红色图片
+      case LoginStatus.LOGGING_IN:
+        return $r("app.media.id_card_yellow") // 需要你有对应的黄色图片
+      default:
+        return $r("app.media.id_card_green")
+    }
+  }
+  // 根据登录状态获取边框颜色
+  getBorderColor(): string {
+    switch (this.LoginStatus) {
+      case LoginStatus.INITIAL:
+        return '#FFFFFF' // 白色 - 初始状态
+      case LoginStatus.SUCCESS:
+        return '#7ed321' // 绿色 - 登录成功
+      case LoginStatus.LOGGING_IN:
+        return '#f8e71c' // 黄色 - 正在登录
+      case LoginStatus.FAILED:
+        return '#f81c1c' // 红色 - 登录失败
+      default:
+        return '#FFFFFF' // 默认白色
+    }
+  }
+  build() {
+    Column(){
+      Column(){
+        Text("请刷卡开工!")
+          .fontSize($r('app.float.fontSize_48'))
+          .fontColor($r('app.color.FFFFFF'))
+          .fontWeight(FontWeight.Bold)
+      }.height('30%')
+      .justifyContent(FlexAlign.Center)
+      Column(){
+        Image(this.getStatusImage())
+          .width($r('app.float.virtualSize_156'))
+          .height($r('app.float.virtualSize_156'))
+        Text(this.getStatusText())
+          .fontSize($r('app.float.fontSize_30'))
+          .fontColor($r('app.color.FFFFFF'))
+          .fontWeight(FontWeight.Regular)
+          .margin({ top:'1%'})
+      }.height('40%')
+      .width('30%')
+      .borderWidth('4px')
+      .justifyContent(FlexAlign.Center)
+      .borderRadius($r('app.float.fontSize_16'))
+      //green == #7ed321,yellow ==#f8e71c ,red=#f81c1c
+      .borderColor(this.getBorderColor())
+      Column(){
+        Row(){
+          Image($r('app.media.tips'))
+            .width($r('app.float.virtualSize_32'))
+            .height($r('app.float.virtualSize_32'))
+          Text("操作指引")
+            .fontSize($r('app.float.fontSize_30'))
+            .fontColor($r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Bold)
+            .margin({ top:'1%',left:'2%'})
+        }
+        .alignItems(VerticalAlign.Center)
+        .height('20%')
+        Row(){
+          Image($r("app.media.check_one"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+          Text("将你的员工卡贴近读卡器感应区")
+            .fontSize($r('app.float.fontSize_24'))
+            .fontColor($r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Lighter)
+            .margin({ top:'1%',left:'2%'})
+        }
+        .alignItems(VerticalAlign.Center)
+        Row(){
+          Image($r("app.media.check_one"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+          Text("验证成功后进入产品扫码界面")
+            .fontSize($r('app.float.fontSize_24'))
+            .fontColor($r('app.color.FFFFFF'))
+            .fontWeight(FontWeight.Lighter)
+            .margin({ top:'1%',left:'2%'})
+        }
+        .alignItems(VerticalAlign.Center)
+      }.height('35%')
+      .width('30%')
+      .margin({top:'5%'})
+      .alignItems(HorizontalAlign.Start)
+    }
+    .width('100%')
+    .height('100%')
+  }
+
+}

+ 62 - 90
entry/src/main/ets/view/process/SelfInspectView.ets

@@ -7,73 +7,48 @@ import PageInfo from '../../viewmodel/PageInfo'
 import { DefectRecordDialog } from '../DefectRecordDialog'
 import DictValue from '../../viewmodel/DictValue'
 import ProcessDefectRecord from '../../viewmodel/process/ProcessDefectRecord'
+import OperationComponent from '../../viewmodel/process/OperationComponent'
 
 // 自检工序
 @Component
 export struct SelfInspectView {
+  @Link opComponents: OperationComponent[]
+  @Link index:number
   // 点检列表
-  @State checkArray: ProcessCheck[] = []
+  @Link checkArray: ProcessCheck[]
   @State selectCheck: number = -1
   // 不良记录列表
-  @State defectRecords: ProcessDefectRecord[] = []
+  @Link defectRecords: ProcessDefectRecord[]
   // 不良类型(数据字典)
   @State defectTypes: DictValue[] = []
-  // 扫码开工状态(0:未开工 1:已开工)
-  @Link @Watch('queryByScanState') scanState: number
-  // 当前流转卡号
-  @Link seqNo: string
-  // 选中工序id
-  @Link selectOperationId: string
-  // 扫码开工后的生产过程信息
-  @Link process: ProcessInfo
-  // 是否是修改不良类型记录
+  @State isAllCheck:boolean = false
+  // // 扫码开工状态(0:未开工 1:已开工)
+  @State scanState:number =1
+  @State selectDefectIndex:number = -1
+
   editDefectRecord: boolean = false
   // 修改时选中的不良类型记录
   selectDefectRecord: ProcessDefectRecord = {}
 
   defectTypeDictCode: string = 'defect_mana'
 
-  // 根据开工状态查询 工序点检项/工序点检历史操作
-  async queryByScanState() {
-    if (this.scanState === 1) {
-      this.checkArray = await ProcessRequest.post('/api/v1/process/check/list', {
-        operationId: this.selectOperationId,
-        processId: this.process.id!,
-        seqNo: this.seqNo
-      } as RequestParamModel)
-      this.queryDefectRecord()
-    } else {
-      let result = await ProcessRequest.post('/api/v1/op/operationCheck/page', {
-        operationId: this.selectOperationId,
-        pageNo: 1,
-        pageSize: 999999
-      } as RequestParamModel) as PageInfo;
-      this.checkArray = result.records as ProcessCheck[] || []
-    }
-  }
-
-  async queryDefectRecord() {
-    if (this.seqNo) {
-      this.defectRecords = await ProcessRequest.post('/api/v1/process/defectRecord/list', {
-        seqNo: this.seqNo
-      } as RequestParamModel)
-      if (this.defectRecords && this.defectTypes) {
-        for (const element of this.defectRecords) {
-          for (const dict of this.defectTypes) {
-            if (element.defectType === dict.dictValue) {
-              element.defectTypeLabel = dict.dictLabel
-              break
-            }
-          }
-        }
+  allChecksCompleted(): boolean {
+    for (let i = 0; i < this.checkArray.length; i++) {
+      const item = this.checkArray[i]
+      if (!item || item.isCheck !== true) {
+        console.log(`项目 ${i} 未完成:`, item)
+        return false
       }
     }
+
+    console.log('所有点检项已完成')
+    return true
   }
 
+
   async aboutToAppear() {
-    this.queryByScanState()
-    this.defectTypes = await ProcessRequest.get(`/api/v1/sys/dictData/queryByType/${this.defectTypeDictCode}`)
-    this.queryDefectRecord()
+    this.isAllCheck = this.allChecksCompleted()
+
   }
 
   build() {
@@ -103,24 +78,14 @@ export struct SelfInspectView {
                       .fontSize($r('app.float.fontSize_16'))
                       .fontWeight(FontWeight.Regular)
                       .fontColor($r('app.color.FFFFFF'))
-                    Toggle({ type: ToggleType.Switch, isOn: item.result === '1' ? true : false })
+                    Toggle({ type: ToggleType.Switch, isOn: item.isCheck  })
                       .selectedColor($r('app.color.30D158'))
                       .switchPointColor($r('app.color.FFFFFF'))
-                      .enabled(this.scanState === 1 ? true : false)
-                      .onChange(async (isOn: boolean) => {
+                      //.enabled(this.scanState === 1 ? true : false)
+                      .onChange( (isOn: boolean) => {
                         this.selectCheck = index
-                        if (this.scanState === 0) {
-                          promptAction.showToast({
-                            message: '工序未开工,请先开工',
-                            duration: 1500,
-                            bottom: 100
-                          })
-                          return
-                        }
-                        await ProcessRequest.post('/api/v1/process/check/update', {
-                          id: item.id,
-                          result: isOn ? '1': '2'
-                        } as RequestParamModel)
+                        this.checkArray[index].isCheck = isOn
+                        this.isAllCheck = this.allChecksCompleted()
                       })
                   }
                   .height('100%')
@@ -133,18 +98,6 @@ export struct SelfInspectView {
                     .fontSize($r('app.float.fontSize_16'))
                     .fontWeight(FontWeight.Lighter)
                     .fontColor($r('app.color.FFFFFF'))
-                  Text('标准值:' + item.standard ? item.standard : '')
-                    .fontSize($r('app.float.fontSize_16'))
-                    .fontWeight(FontWeight.Lighter)
-                    .fontColor($r('app.color.FFFFFF'))
-                  Text('上限值:' + (item.upper ? item.upper : ' '))
-                    .fontSize($r('app.float.fontSize_16'))
-                    .fontWeight(FontWeight.Lighter)
-                    .fontColor($r('app.color.FFFFFF'))
-                  Text('下限值:' + (item.lower ? item.lower : ' '))
-                    .fontSize($r('app.float.fontSize_16'))
-                    .fontWeight(FontWeight.Lighter)
-                    .fontColor($r('app.color.FFFFFF'))
                 }
                 .width('95.3%')
                 .alignItems(HorizontalAlign.Start)
@@ -197,14 +150,7 @@ export struct SelfInspectView {
         .backgroundColor($r('app.color.20FFFFFF'))
         .borderRadius($r('app.float.fontSize_16'))
         .onClick(()=>{
-          if(this.scanState === 0) {
-            promptAction.showToast({
-              message: '工序未开工,请先开工',
-              duration: 1500,
-              bottom: 100
-            })
-            return
-          }
+          this.editDefectRecord = false
           this.defectRecordController.open()
         })
         // 不良类型记录列表
@@ -212,7 +158,7 @@ export struct SelfInspectView {
           ForEach(this.defectRecords, (item: ProcessDefectRecord, index: number) => {
             ListItem() {
               Column() {
-                Text(item.defectTypeLabel ? item.defectTypeLabel! + '(' + item.bugName! + ')' : '')
+                Text(item.defectType ? item.defectType! + '(' + item.bugName! + ')' : '')
                   .fontColor($r('app.color.FFFFFF'))
                   .fontSize($r('app.float.fontSize_16'))
                   .fontWeight(FontWeight.Bold)
@@ -231,15 +177,44 @@ export struct SelfInspectView {
             .width('100%')
             .onClick(()=>{
               this.selectDefectRecord = item
+              this.selectDefectIndex =index
               this.editDefectRecord = true
               this.defectRecordController.open()
             })
           })
         }
         .width('100%')
-        .height('77.9%')
+        .height('70.8%')
         .alignListItem(ListItemAlign.Center)
         .margin({top: 10})
+        Row({space: 4}) {
+          Image($r("app.media.next_step"))
+            .width($r('app.float.virtualSize_24'))
+            .height($r('app.float.virtualSize_24'))
+            .fillColor($r('app.color.0A84FF'))
+          Text('下一步')
+            .fontColor($r('app.color.0A84FF'))
+            .fontSize($r('app.float.fontSize_24'))
+            .fontWeight(FontWeight.Medium)
+        }
+        .width('28.2%')
+        .height('7.1%')
+        .justifyContent(FlexAlign.Center)
+        .backgroundColor(this.isAllCheck ?$r('app.color.20FFFFFF'):$r('app.color.20000000'))
+        .borderRadius($r('app.float.fontSize_16'))
+        .onClick(()=>{
+          if (!this.isAllCheck) {
+            promptAction.showToast({
+              message: '请完成所有点检项后再进行下一步',
+              duration: 1500,
+              bottom: 100
+            })
+            return
+          }
+          this.opComponents[this.index].isComplete=true
+          this.index++
+
+        })
       }
       .height('100%')
       .width('35.4%')
@@ -255,12 +230,9 @@ export struct SelfInspectView {
   defectRecordController: CustomDialogController = new CustomDialogController({
     builder: DefectRecordDialog({
       isEdit: this.editDefectRecord,
-      defectTypes: this.defectTypes,
-      defectRecord: this.selectDefectRecord,
-      seqNo: this.seqNo,
-      selectOperationId: this.selectOperationId,
-      process: this.process,
-      defectRecords: this.defectRecords,
+      defectRecords:this.defectRecords,
+      defectRecord:this.editDefectRecord ? this.selectDefectRecord : {},
+      defectIndex:this.selectDefectIndex,
     }),
     autoCancel: true, // 点击遮罩关闭
     customStyle: true,

File diff suppressed because it is too large
+ 368 - 0
entry/src/main/ets/view/process/WeldView.ets


+ 79 - 0
entry/src/main/ets/view/yuyinzhushou.ets

@@ -0,0 +1,79 @@
+
+@Component
+export struct VoiceAssistant {
+  @State isShowAssistant: boolean = true
+  @State voiceText: string = ""
+  @State isListening: boolean = true
+  // 添加缩放动画状态
+  @State scaleValue: number = 1.0
+  @State isScalingUp: boolean = true
+
+  aboutToAppear() {
+    this.startBreathingAnimation()
+  }
+
+  startBreathingAnimation() {
+    // 使用setInterval实现呼吸动画
+    setInterval(() => {
+      if (this.isScalingUp) {
+        this.scaleValue = 1.2
+      } else {
+        this.scaleValue = 1.0
+      }
+     // this.isScalingUp = !this.isScalingUp
+    }, 1000) // 每1秒切换一次
+  }
+
+  build() {
+    Stack() {
+      // 只在显示时才渲染
+      if (this.isShowAssistant) {
+        Column() {
+          Column(){
+
+          }
+          .width('100%')
+          .height('70%')
+          .backgroundColor(Color.Transparent)
+          .onClick(() => {
+            this.isShowAssistant = false
+          })
+          Row() {
+            Image($r('app.media.state_microphone'))
+              .fillColor($r('app.color.FFFFFF'))
+              .width(50)
+              .height(50)
+              .scale({ x: this.scaleValue, y: this.scaleValue })
+              .animation({ // 添加动画修饰器
+                duration: 1000,
+                curve: Curve.EaseInOut,
+                iterations: -1,
+                playMode: PlayMode.Alternate
+              })
+            Text('')
+
+            // TextInput({ placeholder: '' })
+            //   .type(InputType.Normal)
+            //   .placeholderFont({ size: $r('app.float.fontSize_16') })
+            //   .placeholderColor($r('app.color.30FFFFFF'))
+            //   .fontSize($r('app.float.fontSize_16'))
+            //   .fontColor($r('app.color.FFFFFF'))
+            //   //.enableKeyboardOnFocus(false)
+            //   .layoutWeight(1) // 占据剩余空间
+              // .onClick((event: ClickEvent) => {
+              //   event.; // 关键!阻止事件冒泡到透明背景层
+              // })
+          }
+          .width('90%')
+          .padding(10)
+          .backgroundColor($r('app.color.000000')) // 半透明背景
+          .borderRadius(20)
+        }
+        .width('100%')
+        .height('100%')
+        .justifyContent(FlexAlign.End) // 内容底部对齐
+        .padding(20)
+      }
+    }
+  }
+}

+ 17 - 0
entry/src/main/ets/viewmodel/process/EnumerationType.ets

@@ -0,0 +1,17 @@
+export enum LoginStatus {
+  INITIAL = 0,
+  SUCCESS = 1,
+  LOGGING_IN = 2,
+  FAILED = 3
+}
+export enum ProcessCurrentView {
+  WORK_ORDER_VIEW = 0,
+  SCAN_PRODUCT_VIEW = 1,
+  WORK_STEP_VIEW = 2,
+}
+export enum ProcessStatus {
+  INITIAL = 0,
+  START = 1,
+  STOP = 2,
+  END = 3,
+}

+ 2 - 1
entry/src/main/ets/viewmodel/process/OperationComponent.ets

@@ -1,7 +1,7 @@
 // 工序组件
 export default class OperationComponent {
   // 组件id
-  id?: number | string
+  id?: number
   // 工艺路线id
   processRouteId?: string
   // 工序id
@@ -16,4 +16,5 @@ export default class OperationComponent {
   compentType?: string
   // 排序标识
   sortNum?: number
+  isComplete?:boolean
 }

+ 2 - 0
entry/src/main/ets/viewmodel/process/ProcessCheck.ets

@@ -34,4 +34,6 @@ export default class ProcessCheck {
   operationCode?: string;
   // 工序名称
   operationName?: string;
+  //是否检查
+  isCheck?:boolean
 }

+ 9 - 0
entry/src/main/ets/viewmodel/process/RecordItem.ets

@@ -0,0 +1,9 @@
+// 生产过程点检
+export default class RecordItem {
+  // 主键id
+  id?: string;
+  //  标题
+  title?: string;
+  // 内容
+  content?: string;
+}

File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/check_one.svg


+ 1 - 0
entry/src/main/resources/base/media/continue.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 24V11.8756L25.5 17.9378L36 24L25.5 30.0622L15 36.1244V24Z" fill="none" stroke="#0A84FF" stroke-width="4" stroke-linejoin="round"/></svg>

File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/devices_all.svg


+ 1 - 0
entry/src/main/resources/base/media/double_left.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M24 36L12 24L24 12" stroke="#0A84FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M36 36L24 24L36 12" stroke="#0A84FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>

+ 1 - 0
entry/src/main/resources/base/media/double_right.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 12L24 24L12 36" stroke="#0A84FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M24 12L36 24L24 36" stroke="#0A84FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>

File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/error_upload.svg


File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/id_card_green.svg


File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/id_card_red.svg


File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/id_card_white.svg


File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/id_card_yellow.svg


+ 1 - 0
entry/src/main/resources/base/media/next_step.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4 40.8361C8.89307 34.8632 13.2383 31.4739 17.0356 30.6682C20.8329 29.8625 24.4483 29.7408 27.8818 30.303V41L44 23.5453L27.8818 7V17.167C21.5333 17.2172 16.1362 19.4948 11.6905 24C7.24474 28.5052 4.68126 34.1172 4 40.8361Z" fill="none" stroke="#0A84FF" stroke-width="4" stroke-linejoin="round"/></svg>

File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/thermometer.svg


File diff suppressed because it is too large
+ 1 - 0
entry/src/main/resources/base/media/tips.svg


+ 2 - 1
entry/src/main/resources/base/profile/main_pages.json

@@ -2,6 +2,7 @@
   "src": [
     "pages/DeviceControllerPage",
     "pages/ProcessIndex",
-    "pages/CameraView"
+    "pages/CameraView",
+    "pages/Login"
   ]
 }

+ 7 - 1
oh-package-lock.json5

@@ -2,7 +2,8 @@
   "lockfileVersion": 2,
   "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
   "specifiers": {
-    "@ohos/hypium@1.0.13": "@ohos/hypium@1.0.13"
+    "@ohos/hypium@1.0.13": "@ohos/hypium@1.0.13",
+    "@shimo/sdk-client@latest": "@shimo/sdk-client@1.1.0"
   },
   "packages": {
     "@ohos/hypium@1.0.13": {
@@ -10,6 +11,11 @@
       "integrity": "sha512-d0+XvDeAYk5Vgl6JQ8Q1G+NPmTyJI8qgZ1PwPfcUbx/dfyKVAAv9lz1XtVNhYypyWEKqAzu8zMAC9GuHo2Y53Q==",
       "registryType": "ohpm",
       "shasum": "88d8dda420097efb98d770bf59616faef4682f06"
+    },
+    "@shimo/sdk-client@1.1.0": {
+      "resolved": "https://ohpm.openharmony.cn/ohpm/@shimo/sdk-client/-/sdk-client-1.1.0.har",
+      "integrity": "sha512-O8SZgQVwPbbIVDTaDiHpQYIrv49Qk8pUUa+ti217FK2Dmr7mb3ByPYZK8RGV0oVh0L4U1s36nJgZRimk6x4LXA==",
+      "registryType": "ohpm"
     }
   }
 }

+ 5 - 2
oh-package.json5

@@ -1,5 +1,5 @@
 {
-  "name": "hj_openharmony_process",
+  "name": "example.rearendapp",
   "version": "1.0.0",
   "description": "Please describe the basic information.",
   "main": "",
@@ -8,5 +8,8 @@
   "devDependencies": {
     "@ohos/hypium": "1.0.13"
   },
-  "dynamicDependencies": {}
+  "dynamicDependencies": {},
+  "dependencies": {
+    "@shimo/sdk-client": "^1.1.0"
+  }
 }