소스 검색

1. 首页开发完成
2. 对接消息个数接口
3. 对接任务统计接口
4. 对接任务列表接口
5. 对接工作列表接口

bjb 4 달 전
부모
커밋
1cf33bb31b
29개의 변경된 파일1063개의 추가작업 그리고 271개의 파일을 삭제
  1. 13 1
      build-profile.json5
  2. 100 0
      entry/src/main/ets/api/req/ApiRequest.ets
  3. 0 38
      entry/src/main/ets/api/req/ReqApi.ets
  4. 8 0
      entry/src/main/ets/api/req/ReqJobs.ets
  5. 8 0
      entry/src/main/ets/api/req/ReqMessages.ets
  6. 6 0
      entry/src/main/ets/api/req/ReqPage.ets
  7. 8 0
      entry/src/main/ets/api/req/ReqTasks.ets
  8. 41 0
      entry/src/main/ets/api/rsp/Job.ets
  9. 10 0
      entry/src/main/ets/api/rsp/Message.ets
  10. 3 0
      entry/src/main/ets/api/rsp/Node.ets
  11. 4 0
      entry/src/main/ets/api/rsp/Page.ets
  12. 18 0
      entry/src/main/ets/api/rsp/Task.ets
  13. 6 0
      entry/src/main/ets/api/rsp/TaskStatistics.ets
  14. 3 3
      entry/src/main/ets/components/CardContainer.ets
  15. 40 13
      entry/src/main/ets/pages/PageHome.ets
  16. 135 114
      entry/src/main/ets/pages/PageHomeComponents/TabHome.ets
  17. 208 73
      entry/src/main/ets/pages/PageHomeComponents/TabJobs.ets
  18. 23 1
      entry/src/main/ets/pages/PageHomeComponents/TabSettings.ets
  19. 246 0
      entry/src/main/ets/pages/PageHomeComponents/TabTask.ets
  20. 1 1
      entry/src/main/ets/pages/PageLogin.ets
  21. 4 3
      entry/src/main/ets/pages/PageMessage.ets
  22. 2 2
      entry/src/main/ets/utils/HttpClient.ets
  23. 168 5
      entry/src/main/ets/vm/VMHome.ets
  24. 2 2
      entry/src/main/ets/vm/VMLogin.ets
  25. 1 1
      entry/src/main/ets/vm/VMMessage.ets
  26. 0 11
      entry/src/main/ets/vm/VMTabMessage.ets
  27. 1 1
      entry/src/main/resources/base/element/float.json
  28. 1 0
      entry/src/main/resources/base/media/tasks.svg
  29. 3 2
      entry/src/main/resources/base/profile/main_pages.json

+ 13 - 1
build-profile.json5

@@ -1,7 +1,19 @@
 {
   "app": {
     "signingConfigs": [
-
+      {
+        "name": "default",
+        "type": "HarmonyOS",
+        "material": {
+          "certpath": "C:\\Users\\ISCS\\.ohos\\config\\default_HMOS_Bozzys_HP5OM4eVV84UM2fMSmeCbI2qYo1z8QX2kkiC2cONM8Y=.cer",
+          "keyAlias": "debugKey",
+          "keyPassword": "0000001A2E0FAB09F30D6A78FE1D242FADB6B017E885A6423C87DB520BDC0EA8B6014695C81632A0F4E2",
+          "profile": "C:\\Users\\ISCS\\.ohos\\config\\default_HMOS_Bozzys_HP5OM4eVV84UM2fMSmeCbI2qYo1z8QX2kkiC2cONM8Y=.p7b",
+          "signAlg": "SHA256withECDSA",
+          "storeFile": "C:\\Users\\ISCS\\.ohos\\config\\default_HMOS_Bozzys_HP5OM4eVV84UM2fMSmeCbI2qYo1z8QX2kkiC2cONM8Y=.p12",
+          "storePassword": "0000001ACC5BBF741589739699304AD2B84949369D52A5E550847817D807DEB5744620F527C98730F76C"
+        }
+      }
     ],
     "products": [
       {

+ 100 - 0
entry/src/main/ets/api/req/ApiRequest.ets

@@ -0,0 +1,100 @@
+import { Request } from '../../utils/HttpClient';
+import { Rsp } from '../rsp/Rsp';
+import { Login } from '../rsp/Login';
+import { ReqLogin } from './ReqLogin';
+import { Permission } from '../rsp/Permission';
+import { TaskStatistics } from '../rsp/TaskStatistics';
+import { Page } from '../rsp/Page';
+import { Job } from '../rsp/Job';
+import { ReqJobs } from './ReqJobs';
+import { Message } from '../rsp/Message';
+import { ReqMessages } from './ReqMessages';
+import { ReqTasks } from './ReqTasks';
+import { Task } from '../rsp/Task';
+
+export class ApiRequest {
+  /**
+   * 登录接口
+   *
+   * @param username  用户名
+   * @param pwd       密码
+   * @returns
+   */
+  static login(username: string, pwd: string): Promise<Rsp<Login>> {
+    const req = new ReqLogin(username, pwd)
+    return Request.post("/admin-api/system/auth/login", req)
+  }
+
+  /**
+   * 刷新token操作
+   *
+   * @param refreshToken
+   *
+   * @returns
+   */
+  static refreshToken(refreshToken: string): Promise<Rsp<Login>> {
+    return Request.post("/admin-api/system/auth/refresh-token?refreshToken=" + refreshToken)
+  }
+
+  /**
+   * 获取用户权限信息
+   *
+   * @returns
+   */
+  static getUserPermission(): Promise<Rsp<Permission>> {
+    return Request.get("/admin-api/system/auth/get-permission-info")
+  }
+
+  /**
+   * 获取首页任务状态的统计数据
+   *
+   * @returns
+   */
+  static getTaskStatistics(): Promise<Rsp<TaskStatistics>> {
+    return Request.get("/admin-api/adroid/iscs/workflow/getAppHomeStatistics")
+  }
+
+  /**
+   * 获取消息列表
+   *
+   * @returns
+   */
+  static getMessages(params: ReqMessages): Promise<Rsp<Page<Message>>> {
+    return Request.get("/admin-api/system/app-notify-message/my-page", params)
+  }
+
+  /**
+   * 获取未读消息数
+   *
+   * @returns
+   */
+  static getMessagesUnread(): Promise<Rsp<number>> {
+    return Request.get("/admin-api/system/app-notify-message/get-unread-count")
+  }
+
+  /**
+   * 获取作业列表数据
+   *
+   * app /admin-api/adroid/iscs/workflow/getAppMyTicketPage
+   * web /admin-api/iscs/workflow-work/getWorkflowWorkPage
+   *
+   * @param params
+   *
+   * @returns
+   */
+  static getJobs(params: ReqJobs): Promise<Rsp<Page<Job>>> {
+    return Request.get("/admin-api/adroid/iscs/workflow/getAppMyTicketPage", params)
+  }
+
+  /**
+   * 获取任务列表数据
+   * app /admin-api/adroid/iscs/workflow/getAppMyWorkPage
+   * web /admin-api/iscs/workflow-work/getMyWorkPage
+   *
+   * @param params
+   *
+   */
+  static getTasks(params: ReqTasks): Promise<Rsp<Page<Task>>> {
+    return Request.get("/admin-api/adroid/iscs/workflow/getAppMyWorkPage", params)
+  }
+}

+ 0 - 38
entry/src/main/ets/api/req/ReqApi.ets

@@ -1,38 +0,0 @@
-import { Request } from '../../utils/HttpClient';
-import { Rsp } from '../rsp/Rsp';
-import { Login } from '../rsp/Login';
-import { ReqLogin } from './ReqLogin';
-import { Permission } from '../rsp/Permission';
-
-export class ReqApi {
-  /**
-   * 登录接口
-   *
-   * @param username  用户名
-   * @param pwd       密码
-   * @returns
-   */
-  static login(username: string, pwd: string): Promise<Rsp<Login>> {
-    const req = new ReqLogin(username, pwd)
-    return Request.post("/admin-api/system/auth/login", req)
-  }
-
-  /**
-   * 获取用户权限信息
-   *
-   * @returns
-   */
-  static getUserPermission(): Promise<Rsp<Permission>> {
-    return Request.get("/admin-api/system/auth/get-permission-info")
-  }
-
-  /**
-   * 刷新token操作
-   *
-   * @param refreshToken
-   * @returns
-   */
-  static refreshToken(refreshToken: string): Promise<Rsp<Login>> {
-    return Request.post("/admin-api/system/auth/refresh-token?refreshToken=" + refreshToken)
-  }
-}

+ 8 - 0
entry/src/main/ets/api/req/ReqJobs.ets

@@ -0,0 +1,8 @@
+import { ReqPage } from './ReqPage';
+
+/**
+ * 请求作业列表数据构造器
+ */
+export class ReqJobs extends ReqPage {
+  public status: string | null = null
+}

+ 8 - 0
entry/src/main/ets/api/req/ReqMessages.ets

@@ -0,0 +1,8 @@
+import { ReqPage } from './ReqPage';
+
+/**
+ * 请求作业列表数据构造器
+ */
+export class ReqMessages extends ReqPage {
+
+}

+ 6 - 0
entry/src/main/ets/api/req/ReqPage.ets

@@ -0,0 +1,6 @@
+export class ReqPage {
+  // 当前页面 1开始
+  public pageNo: number = 0
+  // 页面数据大小
+  public pageSize: number = 0
+}

+ 8 - 0
entry/src/main/ets/api/req/ReqTasks.ets

@@ -0,0 +1,8 @@
+import { ReqPage } from './ReqPage';
+
+/**
+ * 请求任务列表数据构造器
+ */
+export class ReqTasks extends ReqPage {
+  public approvalStatus: string | null = null
+}

+ 41 - 0
entry/src/main/ets/api/rsp/Job.ets

@@ -0,0 +1,41 @@
+import { Node } from './Node'
+
+export class Job {
+  // 作业Id
+  id: number = -1
+  // 作业编号
+  orderNo: string = ""
+  // 作业名称
+  name: string = ""
+  // 作业类型
+  type: string = ""
+  // 作业类型名称,服务端不返回,本地使用
+  typeName: string = ""
+  // 紧急等级
+  urgencyLevel: string = ""
+  // sopId
+  designId: number = -1
+  // 设计模板
+  designName: string = ""
+  // SOPInfo
+  designContent: string | null = null
+  // 描述
+  description: string = ""
+  // 创建者id
+  initiatorId: number = -1
+  // 创建者名称
+  initiatorName: string = ""
+  // 创建者创建时间
+  initiatorTime: number = -1
+  // 作业状态
+  status: string = ""
+  // 创建时间
+  createTime: number = -1
+  currentNodeId: string | null = null
+  currentNodeName: string | null = null
+  completionTime: number | null = null
+  cancellationTime: number | null = null
+  cancellationReason: string | null = null
+  workflowWorkNodeDOList: Node[] | null = null
+}
+

+ 10 - 0
entry/src/main/ets/api/rsp/Message.ets

@@ -0,0 +1,10 @@
+export class Message {
+  id: number = 0
+  userId: number = 0
+  userType: number = 0
+  readStatus: Boolean = false
+  createTime: number = -1
+  title: string | null = null
+  templateContent: string = ""
+  isTitle: boolean = false
+}

+ 3 - 0
entry/src/main/ets/api/rsp/Node.ets

@@ -0,0 +1,3 @@
+export class Node {
+
+}

+ 4 - 0
entry/src/main/ets/api/rsp/Page.ets

@@ -0,0 +1,4 @@
+export class Page<T> {
+  total: number = 0
+  list: T[] = []
+}

+ 18 - 0
entry/src/main/ets/api/rsp/Task.ets

@@ -0,0 +1,18 @@
+export class Task {
+  workId: number = 0
+  nodeId: number = 0
+  orderNo: string = ""
+  name: string = ""
+  urgencyLevel: string = ""
+  completionTime: number | null = null
+  cancellationTime: number | null = null
+  cancellationReason: string | null = null
+  // 发起人
+  initiatorName: string | null = null
+  // 当前执行人
+  workerUserName: string | null = null
+  workTime: number | null = null
+  currentNodeId: string | null = null
+  currentNodeName: string | null = null
+  approvalStatus: string = ""
+}

+ 6 - 0
entry/src/main/ets/api/rsp/TaskStatistics.ets

@@ -0,0 +1,6 @@
+export class TaskStatistics {
+  // 进行中
+  inProgressCount: number = 0
+  // 已完成
+  completedCount: number = 0
+}

+ 3 - 3
entry/src/main/ets/components/CardContainer.ets

@@ -3,10 +3,10 @@ export struct CardContainer {
   @Prop radius: number | string = 16
   @Prop bgColor: string = '#FFFFFF'
   @Prop shadowColor: string = '#000000'
-  @Prop shadowOpacity: number = 0.2
-  @Prop blurRadius: number = 50
+  @Prop shadowOpacity: number = 0.1
+  @Prop blurRadius: number = 40
   @Prop cardColor: Color = Color.White
-  @Prop paddings: number = 0
+  @Prop paddings: Padding | Length = 0
   @Prop margins: Margin = {}
   // 是否裁剪超出部分
   @Prop needClip: boolean = true

+ 40 - 13
entry/src/main/ets/pages/PageHome.ets

@@ -3,7 +3,7 @@ import { Storage } from '../utils/Storage'
 import { VMHome } from '../vm/VMHome'
 import { TabHome } from './PageHomeComponents/TabHome'
 import { TabJobs } from './PageHomeComponents/TabJobs'
-import { TabMessage } from './PageHomeComponents/TabMessage'
+import { TabTasks } from './PageHomeComponents/TabTask'
 import { TabSettings } from './PageHomeComponents/TabSettings'
 
 @Entry
@@ -33,25 +33,45 @@ struct PageHome {
       TabContent() {
         TabHome({ vm: this.vm })
       }
-      .tabBar(this.TabBuilder(0, "首页", $r('app.media.home')))
+      .tabBar(this.TabBuilder({
+        label: "首页",
+        icon: $r('app.media.home'),
+        select: this.vm.tabIndex == 0,
+        num: 0
+      }))
       .clip(false)
 
       TabContent() {
-        TabJobs()
+        TabJobs({ vm: this.vm })
       }
-      .tabBar(this.TabBuilder(1, "作业", $r('app.media.jobs')))
+      .tabBar(this.TabBuilder({
+        label: "作业",
+        icon: $r('app.media.jobs'),
+        select: this.vm.tabIndex == 1,
+        num: this.vm.jobProgressCount
+      }))
       .clip(false)
 
       TabContent() {
-        TabMessage()
+        TabTasks({ vm: this.vm })
       }
-      .tabBar(this.TabBuilder(2, "消息", $r('app.media.message')))
+      .tabBar(this.TabBuilder({
+        label: "任务",
+        icon: $r('app.media.tasks'),
+        select: this.vm.tabIndex == 2,
+        num: this.vm.taskProgressCount
+      }))
       .clip(false)
 
       TabContent() {
         TabSettings({ vm: this.vm })
       }
-      .tabBar(this.TabBuilder(3, "设置", $r("app.media.settings")))
+      .tabBar(this.TabBuilder({
+        label: "设置",
+        icon: $r('app.media.settings'),
+        select: this.vm.tabIndex == 3,
+        num: 0
+      }))
       .clip(false)
     }
     .width('100%')
@@ -69,17 +89,17 @@ struct PageHome {
   }
 
   @Builder
-  TabBuilder(id: number, text: string, icon: Resource) {
+  TabBuilder(tab: HomeTabItem) {
     Stack() {
       Column() {
-        Image(icon).width(20).height(20).fillColor(id == this.vm.tabIndex ? "#1E90FF" : "#333333")
-        Text(text)
+        Image(tab.icon).width(20).height(20).fillColor(tab.select ? "#1E90FF" : "#333333")
+        Text(tab.label)
           .fontSize(12)
-          .fontColor(id == this.vm.tabIndex ? "#1E90FF" : "#333333")
+          .fontColor(tab.select ? "#1E90FF" : "#333333")
           .margin({ top: 5 })
       }.width("100%").height("100%").justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
 
-      Text("99")
+      Text(tab.num > 99 ? "99+" : `${tab.num}`)
         .backgroundColor("#FF4500")
         .borderRadius("50%")
         .fontColor(Color.White)
@@ -87,7 +107,14 @@ struct PageHome {
         .position({ top: 2, left: "55%" })
         .constraintSize({ minWidth: 15, minHeight: 15 })
         .textAlign(TextAlign.Center)
-        .visibility(Visibility.Hidden)
+        .visibility(tab.num <= 0 ? Visibility.Hidden : Visibility.Visible)
     }.width("100%").height(56)
   }
+}
+
+class HomeTabItem {
+  public label: string = ""
+  public icon: ResourceStr | undefined = undefined
+  public select: boolean = false
+  public num: number = 0
 }

+ 135 - 114
entry/src/main/ets/pages/PageHomeComponents/TabHome.ets

@@ -1,3 +1,7 @@
+import { Job } from '../../api/rsp/Job';
+import { Message } from '../../api/rsp/Message';
+import { Task } from '../../api/rsp/Task';
+import { CardContainer } from '../../components/CardContainer';
 import { VMHome } from '../../vm/VMHome';
 
 /**
@@ -53,7 +57,7 @@ export struct TabHome {
 
         Stack() {
           Image($r("app.media.bell")).width(19).height(19).fillColor(Color.White)
-          Text("99")
+          Text(this.vm.messageUnreadCount > 99 ? "99+" : `${this.vm.messageUnreadCount}`)
             .backgroundColor("#FF4500")
             .borderRadius("50%")
             .fontColor(Color.White)
@@ -61,19 +65,22 @@ export struct TabHome {
             .position({ top: -5, left: "52%" })
             .constraintSize({ minWidth: 15, minHeight: 15 })
             .textAlign(TextAlign.Center)
+            .padding({ left: 2, right: 2 })
+            .visibility(this.vm.messageUnreadCount == 0 ? Visibility.Hidden : Visibility.Visible)
         }.width(36).height(24).onClick(() => {
+          this.getUIContext().getRouter().pushUrl({ url: "pages/PageMessage" }).catch()
         })
 
-        Stack() {
-          Image($r("app.media.settings")).width(18).height(18).fillColor(Color.White)
-        }.width(36).height(24).onClick(() => {
-          // const am = abilityAccessCtrl.createAtManager()
-          // am.requestPermissionsFromUser(this.getUIContext().getHostContext(), ["ohos.permission.ACCESS_BLUETOOTH"]).then((data) => {
-          //   console.log("权限请求", JSON.stringify(data))
-          // })
-          // const bm = new BleManager("CC:BA:97:21:71:CA")
-          // bm.connect()
-        })
+        // Stack() {
+        //   Image($r("app.media.settings")).width(18).height(18).fillColor(Color.White)
+        // }.width(36).height(24).onClick(() => {
+        //   // const am = abilityAccessCtrl.createAtManager()
+        //   // am.requestPermissionsFromUser(this.getUIContext().getHostContext(), ["ohos.permission.ACCESS_BLUETOOTH"]).then((data) => {
+        //   //   console.log("权限请求", JSON.stringify(data))
+        //   // })
+        //   // const bm = new BleManager("CC:BA:97:21:71:CA")
+        //   // bm.connect()
+        // })
       }
       .width("100%")
       .padding({
@@ -94,7 +101,7 @@ export struct TabHome {
   @Builder
   TODOStatus() {
     Column() {
-      Text("中午好,今天有2个待办任务")
+      Text(`今天有${this.vm.taskProgressCount}个待办任务`)
         .width("100%")
         .height(51)
         .backgroundColor("#E6F7FF")
@@ -103,37 +110,29 @@ export struct TabHome {
         .textAlign(TextAlign.Center)
       Row() {
         Column() {
-          Text("2").fontSize(24).fontColor("#FF4500").fontWeight(FontWeight.Bold)
-          Text("待处理").fontSize(12).fontColor("#333333").margin({ top: 10, bottom: 5 })
-          Image($r("app.media.job_todo")).width(18).height(18).fillColor(Color.Black)
-        }
-        .margin(5)
-        .layoutWeight(1)
-        .aspectRatio(1)
-        .backgroundColor("#FFF5EB")
-        .borderRadius(12)
-        .justifyContent(FlexAlign.Center)
-
-        Column() {
-          Text("5").fontSize(24).fontColor("#FFA500").fontWeight(FontWeight.Bold)
-          Text("进行中").fontSize(12).fontColor("#333333").margin({ top: 10, bottom: 5 })
-          Image($r("app.media.job_ing")).width(18).height(18).fillColor(Color.Black)
+          Text(`${this.vm.taskProgressCount}`).fontSize(24).fontColor("#FFA500").fontWeight(FontWeight.Bold)
+          Row() {
+            Image($r("app.media.job_ing")).width(18).height(18).fillColor(Color.Black)
+            Text("进行中").fontSize(14).fontColor($r("app.color.text")).fontWeight(FontWeight.Bold).margin({ left: 5 })
+          }.margin({ top: 8 })
         }
         .margin(5)
         .layoutWeight(1)
-        .aspectRatio(1)
+        .height(80)
         .backgroundColor("#FFF5EB")
         .borderRadius(12)
         .justifyContent(FlexAlign.Center)
 
         Column() {
-          Text("10").fontSize(24).fontColor("#32CD32").fontWeight(FontWeight.Bold)
-          Text("本月完成").fontSize(12).fontColor("#333333").margin({ top: 10, bottom: 5 })
-          Image($r("app.media.job_finish")).width(18).height(18).fillColor(Color.Black)
+          Text(`${this.vm.taskFinishedCount}`).fontSize(24).fontColor("#32CD32").fontWeight(FontWeight.Bold)
+          Row() {
+            Image($r("app.media.job_finish")).width(18).height(18).fillColor(Color.Black)
+            Text("本月完成").fontSize(14).fontColor($r("app.color.text")).fontWeight(FontWeight.Bold).margin({ left: 5 })
+          }.margin({ top: 8 })
         }
         .margin(5)
         .layoutWeight(1)
-        .aspectRatio(1)
+        .height(80)
         .backgroundColor("#FFF5EB")
         .borderRadius(12)
         .justifyContent(FlexAlign.Center)
@@ -152,75 +151,97 @@ export struct TabHome {
     List() {
       ListItem() {
         Row() {
-          Text("我的当前任务").fontSize(14).fontColor("#333333").fontWeight(FontWeight.Medium)
+          Text("当前任务").fontSize(14).fontColor("#333333").fontWeight(FontWeight.Medium)
           Row().layoutWeight(1)
           Text("查看全部").fontSize(14).fontColor("#1E90FF").fontWeight(FontWeight.Medium)
         }.width("100%").height(46).onClick(() => {
-          this.vm.updateTabIndex(1)
+          this.vm.updateTabIndex(2)
         })
-      }
+      }.padding({ left: 16, right: 16 })
 
-      ForEach([1, 2], (item: number, index: number) => {
-        ListItem() {
+      // 空数据提示
+      ListItem() {
+        CardContainer() {
           Column() {
-            Row() {
-              Text("冷却水系统能量隔离作业").fontSize(15).fontColor("#333333").fontWeight(FontWeight.Medium)
-              Row().layoutWeight(1)
-              Text("待办")
-                .fontSize(12)
-                .fontColor("#333333")
-                .backgroundColor("#FFD700")
-                .borderRadius(20)
-                .height(24)
-                .padding({ left: 10, right: 10 })
-                .textAlign(TextAlign.Center)
-            }
+            Text("您当前暂无任务").fontSize(14).fontColor($r("app.color.text"))
+          }.width("100%").height(102).justifyContent(FlexAlign.Center)
+        }
+      }.padding({ left: 16, right: 16 })
+      .visibility(this.vm.homeTasks.length == 0 ? Visibility.Visible : Visibility.None)
 
-            Flex({ wrap: FlexWrap.Wrap, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
-              Image($r("app.media.location")).width(12).height(12).fillColor("#1E90FF").margin({ right: 5 })
-              Text("车间B区")
-                .fontSize(13)
-                .fontColor("#666666")
-                .margin({ right: 12 })
-                .height(24)
-                .textAlign(TextAlign.Center)
-              Image($r("app.media.user")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
-              Text("负责人:王主管哈哈哈哈")
-                .fontSize(13)
-                .fontColor("#666666")
-                .margin({ right: 12 })
-                .height(24)
-                .textAlign(TextAlign.Center)
-              Image($r("app.media.jobs")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
-              Text("WO-2025-005")
-                .fontSize(13)
-                .fontColor("#666666")
-                .margin({ right: 12 })
-                .height(24)
-                .textAlign(TextAlign.Center)
-            }.margin({ top: 10 })
+      ForEach(this.vm.homeTasks, (task: Task, idx: number) => {
+        ListItem() {
+          CardContainer({ paddings: 16 }) {
+            Column() {
+              Row() {
+                Text(task.name).fontSize(15).fontColor("#333333").fontWeight(FontWeight.Medium)
+                Row().layoutWeight(1)
+                // Text("待办")
+                //   .fontSize(12)
+                //   .fontColor("#333333")
+                //   .backgroundColor("#FFD700")
+                //   .borderRadius(20)
+                //   .height(24)
+                //   .padding({ left: 10, right: 10 })
+                //   .textAlign(TextAlign.Center)
+              }
 
-            Text("作业内容:上锁挂牌").fontSize(13).fontColor("#666666").height(24).textAlign(TextAlign.Center)
+              Flex({ wrap: FlexWrap.Wrap, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
+                // Image($r("app.media.location")).width(12).height(12).fillColor("#1E90FF").margin({ right: 5 })
+                // Text("车间B区")
+                //   .fontSize(13)
+                //   .fontColor("#666666")
+                //   .margin({ right: 12 })
+                //   .height(24)
+                //   .textAlign(TextAlign.Center)
+                // 编号
+                Image($r("app.media.jobs")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
+                Text(`${task.orderNo}`)
+                  .fontSize(13)
+                  .fontColor("#666666")
+                  .margin({ right: 12 })
+                  .height(24)
+                  .textAlign(TextAlign.Center)
+                // 负责人
+                Image($r("app.media.user")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
+                Text(`负责人:${task.initiatorName}`)
+                  .fontSize(13)
+                  .fontColor("#666666")
+                  .margin({ right: 12 })
+                  .height(24)
+                  .textAlign(TextAlign.Center)
+              }.margin({ top: 10 })
 
-            Row() {
-              Text("今天 14:00").layoutWeight(1).margin({ right: 10 }).fontColor("#999999").fontSize(12)
-              Button("查看详情")
-                .height(35)
-                .padding({ left: 15, right: 15 })
-                .backgroundColor("#4682B4")
-                .borderRadius(4)
-                .fontSize(13)
-                .fontWeight(FontWeight.Medium)
-            }.width("100%").layoutWeight(1)
-          }.width("100%").height("100%").justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
+              Row() {
+                Text(`当前任务:`)
+                  .fontSize(13)
+                  .fontColor("#666666")
+                  .height(24)
+                Text(`${task.currentNodeName ?? '--'}`)
+                  .backgroundColor("#1E90FF")
+                  .borderRadius(4)
+                  .padding({
+                    left: 5,
+                    top: 3,
+                    right: 5,
+                    bottom: 3
+                  })
+                  .fontSize(12)
+                  .fontColor(Color.White)
+                Text("今天 14:00")
+                  .margin({ left: 10 })
+                  .fontColor("#999999")
+                  .fontSize(12)
+                  .layoutWeight(1)
+                  .textAlign(TextAlign.End)
+              }.width("100%").margin({ bottom: -8 })
+            }.width("100%").justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
+          }
         }
         .width("100%")
-        .height(175)
-        .backgroundColor("#F8F9FA")
-        .borderRadius(12)
-        .border({ width: 1, color: "#EEEEEE" })
-        .margin({ bottom: index == 1 ? 0 : 15 })
-        .padding(16)
+        .clip(false)
+        .padding({ left: 16, right: 16 })
+        .margin({ bottom: idx >= (this.vm.homeTasks.length - 1) ? 0 : 15 })
       })
       ListItem() {
         Row() {
@@ -228,38 +249,38 @@ export struct TabHome {
           Row().layoutWeight(1)
           Text("全部消息").fontSize(14).fontColor("#1E90FF").fontWeight(FontWeight.Medium)
         }.width("100%").height(46).onClick(() => {
-          this.vm.updateTabIndex(2)
+          this.getUIContext().getRouter().pushUrl({ url: "pages/PageMessage" }).catch()
         })
-      }
+      }.padding({ left: 16, right: 16 })
 
-      ForEach([1, 2], (item: number) => {
-        ListItem() {
+      // 空数据提示
+      ListItem() {
+        CardContainer() {
           Column() {
-            Text("系统通知:您有新的作业任务待处理,请及时查看并执行操作,请及时查看并执行操作,请及时查看并执行操作,请及时查看并执行操作")
-              .fontSize(14)
-              .fontColor("#333333")
-              .textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(2)
-            Text("5分钟前")
-              .layoutWeight(1)
-              .width("100%")
-              .textAlign(TextAlign.End)
-              .fontSize(12)
-              .fontColor("#999999")
+            Text("您当前暂无消息").fontSize(14).fontColor($r("app.color.text"))
+          }.width("100%").height(102).justifyContent(FlexAlign.Center)
+        }
+      }.padding({ left: 16, right: 16 })
+      .visibility(this.vm.homeMessages.length == 0 ? Visibility.Visible : Visibility.None)
+
+      ForEach(this.vm.homeMessages, (msg: Message) => {
+        ListItem() {
+          CardContainer({ paddings: 16 }) {
+            Column() {
+              Text(`${msg.title ?? "提醒"}`).fontSize(15).fontColor("#333333").fontWeight(FontWeight.Medium).margin({ bottom: 10 })
+              Text(`${msg.templateContent}`).fontSize(13).fontColor("#666666").lineHeight(18)
+              Row() {
+                Text("作业管理").fontSize(12).fontColor("#999999").layoutWeight(1)
+                Text("09:45").fontSize(12).fontColor("#999999")
+              }.margin({ top: 6, bottom: -5 })
+            }.width("100%").alignItems(HorizontalAlign.Start)
           }
-          .width("100%")
-          .height("100%")
-          .justifyContent(FlexAlign.Start)
-          .alignItems(HorizontalAlign.Start)
-          .padding(16)
         }
         .width("100%")
-        .height(102)
-        .backgroundColor("#F8F9FA")
-        .borderRadius(12)
-        .border({ width: 1, color: "#EEEEEE" })
         .margin({ bottom: 15 })
+        .padding({ left: 16, right: 16 })
       })
     }
-    .width("100%").layoutWeight(1).padding({ left: 16, right: 16 }).scrollBar(BarState.Off)
+    .width("100%").layoutWeight(1).scrollBar(BarState.Off)
   }
 }

+ 208 - 73
entry/src/main/ets/pages/PageHomeComponents/TabJobs.ets

@@ -1,35 +1,38 @@
-import { VMTabJobs } from '../../vm/VMTabJobs'
+import { Job } from '../../api/rsp/Job'
+import { CardContainer } from '../../components/CardContainer'
+import { VMHome } from '../../vm/VMHome'
 
 @Component
 export struct TabJobs {
-  @State vm: VMTabJobs = new VMTabJobs()
+  // 关联首页状态
+  @Link vm: VMHome
 
   build() {
     Column() {
+      // 顶部工具栏
       this.TopBar()
-      Refresh({ refreshing: $$this.vm.isRefreshing }) {
+      // 任务分组栏
+      this.TaskType()
+      Refresh({ refreshing: $$this.vm.jobsPage.isRefreshing }) {
         List() {
-          ForEach(["今天", 2, 3, "昨天", 5, 6, 7, 8], (item: object, idx: number) => {
-            if (idx == 0 || idx == 3) {
-              ListItem() {
-                this.ListItemTitle(item.toString())
-              }
-            } else {
-              ListItem() {
-                this.ListItemContent()
-              }
-              .width("100%")
-              .height(175)
-              .backgroundColor("#F8F9FA")
-              .borderRadius(12)
-              .border({ width: 1, color: "#EEEEEE" })
-              .margin({ bottom: idx + 1 == 3 ? 0 : 15 })
-              .padding(16)
+          ForEach(this.vm.jobs, (item: Job, idx: number) => {
+            ListItem() {
+              this.ListItemContent(item)
             }
+            .width("100%")
+            .clip(false)
+            .padding({ left: 16, right: 16 })
+            .margin({ top: 8, bottom: 8 })
           })
-        }.width("100%").height("100%").padding({ left: 16, right: 16 }).scrollBar(BarState.Off)
+        }.width("100%").height("100%").scrollBar(BarState.Off)
       }.width("100%").layoutWeight(1).onRefreshing(() => {
-        this.vm.onRefresh()
+        this.vm.getJobsData({
+          pageNo: 1,
+          pageSize: 10,
+          type: this.vm.jobsPage.type,
+          isRefreshing: true,
+          isGetData: true
+        })
       })
     }
     .width("100%")
@@ -61,72 +64,204 @@ export struct TabJobs {
       .padding({
         left: 16,
         top: 15,
+        right: 16
+      })
+
+      Row() {
+        TextInput({ placeholder: "搜索作业名称或作业编号..." })
+          .placeholderColor(Color.White)
+          .fontSize(16)
+          .lineHeight(22)
+          .fontColor(Color.White)
+          .backgroundColor(Color.Transparent)
+          .onChange((value) => {
+            // this.vm.updateCode(value)
+          })
+      }
+      .height(40)
+      .linearGradient({ angle: 90, colors: [['#FFA126', 0.0], ['#FFB126', 1.0]] })
+      .borderRadius("50%")
+      .margin({
+        left: 16,
+        top: 8,
         right: 16,
-        bottom: 15
+        bottom: 8
       })
+      .justifyContent(FlexAlign.Center)
     }
     .width("100%")
-    .backgroundColor("#FFA500")
+    .linearGradient({ angle: 90, colors: [['#FF8C00', 0.0], ['#FFA500', 1.0]] })
     .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
   }
 
+  @Builder
+  TaskType() {
+    Row() {
+      Text("进行中")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.jobsPage.type == "running" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.jobsPage.type == "running" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getJobsData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "running",
+            isGetData: true,
+          })
+        })
+      Text("待发布")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.jobsPage.type == "unreleased" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.jobsPage.type == "unreleased" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getJobsData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "unreleased",
+            isGetData: true,
+          })
+        })
+      Text("已完成")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.jobsPage.type == "completed" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.jobsPage.type == "completed" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getJobsData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "completed",
+            isGetData: true,
+          })
+        })
+      Text("全部")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.jobsPage.type == "" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.jobsPage.type == "" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getJobsData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "",
+            isGetData: true,
+          })
+        })
+    }.margin({ top: 5, bottom: 5 })
+    .padding({ left: 16, top: 6, right: 16 })
+    .width("100%").justifyContent(FlexAlign.Start)
+  }
+
   @Builder
   ListItemTitle(title: string) {
     Text(title).fontColor("#333333").fontSize(16).height(45)
   }
 
   @Builder
-  ListItemContent() {
-    Column() {
-      Row() {
-        Text("冷却水系统能量隔离作业").fontSize(15).fontColor("#333333").fontWeight(FontWeight.Medium)
-        Row().layoutWeight(1)
-        Text("待办")
-          .fontSize(12)
-          .fontColor("#333333")
-          .backgroundColor("#FFD700")
-          .borderRadius(20)
-          .height(24)
-          .padding({ left: 10, right: 10 })
-          .textAlign(TextAlign.Center)
-      }
-
-      Flex({ wrap: FlexWrap.Wrap, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
-        Image($r("app.media.location")).width(12).height(12).fillColor("#1E90FF").margin({ right: 5 })
-        Text("车间B区")
-          .fontSize(13)
-          .fontColor("#666666")
-          .margin({ right: 12 })
-          .height(24)
-          .textAlign(TextAlign.Center)
-        Image($r("app.media.user")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
-        Text("负责人:王主管哈哈哈哈")
-          .fontSize(13)
-          .fontColor("#666666")
-          .margin({ right: 12 })
-          .height(24)
-          .textAlign(TextAlign.Center)
-        Image($r("app.media.jobs")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
-        Text("WO-2025-005")
-          .fontSize(13)
-          .fontColor("#666666")
-          .margin({ right: 12 })
-          .height(24)
-          .textAlign(TextAlign.Center)
-      }.margin({ top: 10 })
+  ListItemContent(job: Job) {
+    CardContainer({ paddings: 16 }) {
+      Column() {
+        Row() {
+          Text(job.name).fontSize(15).fontColor("#333333").fontWeight(FontWeight.Medium)
+          Row().layoutWeight(1)
+          // Text("待办")
+          //   .fontSize(12)
+          //   .fontColor("#333333")
+          //   .backgroundColor("#FFD700")
+          //   .borderRadius(20)
+          //   .height(24)
+          //   .padding({ left: 10, right: 10 })
+          //   .textAlign(TextAlign.Center)
+        }
 
-      Text("作业内容:上锁挂牌").fontSize(13).fontColor("#666666").height(24).textAlign(TextAlign.Center)
+        Flex({ wrap: FlexWrap.Wrap, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
+          // Image($r("app.media.location")).width(12).height(12).fillColor("#1E90FF").margin({ right: 5 })
+          // Text("车间B区")
+          //   .fontSize(13)
+          //   .fontColor("#666666")
+          //   .margin({ right: 12 })
+          //   .height(24)
+          //   .textAlign(TextAlign.Center)
+          // 编号
+          Image($r("app.media.jobs")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
+          Text(`${job.orderNo}`)
+            .fontSize(13)
+            .fontColor("#666666")
+            .margin({ right: 12 })
+            .height(24)
+            .textAlign(TextAlign.Center)
+          // 负责人
+          Image($r("app.media.user")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
+          Text(`负责人:${job.initiatorName}`)
+            .fontSize(13)
+            .fontColor("#666666")
+            .margin({ right: 12 })
+            .height(24)
+            .textAlign(TextAlign.Center)
+        }.margin({ top: 10 })
 
-      Row() {
-        Text("今天 14:00").layoutWeight(1).margin({ right: 10 }).fontColor("#999999").fontSize(12)
-        Button("查看详情")
-          .height(35)
-          .padding({ left: 15, right: 15 })
-          .backgroundColor("#4682B4")
-          .borderRadius(4)
-          .fontSize(13)
-          .fontWeight(FontWeight.Medium)
-      }.width("100%").layoutWeight(1)
-    }.width("100%").height("100%").justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
+        Row() {
+          Text(`当前任务:`)
+            .fontSize(13)
+            .fontColor("#666666")
+            .height(24)
+          Text(`${job.currentNodeName ?? '--'}`)
+            .backgroundColor("#1E90FF")
+            .borderRadius(4)
+            .padding({
+              left: 5,
+              top: 3,
+              right: 5,
+              bottom: 3
+            })
+            .fontSize(12)
+            .fontColor(Color.White)
+          Text("今天 14:00")
+            .margin({ left: 10 })
+            .fontColor("#999999")
+            .fontSize(12)
+            .layoutWeight(1)
+            .textAlign(TextAlign.End)
+        }.width("100%").margin({ bottom: -8 })
+      }.width("100%").justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
+    }
   }
 }

+ 23 - 1
entry/src/main/ets/pages/PageHomeComponents/TabSettings.ets

@@ -1,4 +1,6 @@
 import { CardContainer } from '../../components/CardContainer'
+import { Loading } from '../../components/loading/Loading'
+import { EventBus } from '../../utils/EventBus'
 import { VMHome } from '../../vm/VMHome'
 
 @Component
@@ -98,7 +100,27 @@ export struct TabSettings {
     .borderRadius(6)
     .justifyContent(FlexAlign.Center)
     .onClick(() => {
-      this.getUIContext().showAlertDialog({ title: "提示", message: "确定要退出登录吗?" })
+      this.getUIContext()
+        .showAlertDialog({
+          title: "提示",
+          message: "确定要退出登录吗?",
+          autoCancel: false,
+          primaryButton: {
+            value: "取消",
+            action: () => {
+            }
+          },
+          secondaryButton: {
+            value: "确定",
+            action: () => {
+              Loading.showLoading()
+              setTimeout(() => {
+                EventBus.emit("EVENT_LOGOUT")
+                Loading.hideLoading()
+              }, 1000)
+            }
+          }
+        })
     })
   }
 }

+ 246 - 0
entry/src/main/ets/pages/PageHomeComponents/TabTask.ets

@@ -0,0 +1,246 @@
+import { Task } from '../../api/rsp/Task'
+import { CardContainer } from '../../components/CardContainer'
+import { VMHome } from '../../vm/VMHome'
+
+@Component
+export struct TabTasks {
+  // 关联首页状态
+  @Link vm: VMHome
+
+  build() {
+    Column() {
+      // 顶部工具栏
+      this.TopBar()
+      // 任务分组栏
+      this.TaskType()
+      Refresh({ refreshing: $$this.vm.tasksPage.isRefreshing }) {
+        List() {
+          ForEach(this.vm.tasks, (item: Task) => {
+            ListItem() {
+              this.ListItemContent(item)
+            }
+            .width("100%")
+            .clip(false)
+            .padding({ left: 16, right: 16 })
+            .margin({ top: 8, bottom: 8 })
+          })
+        }.width("100%").height("100%").scrollBar(BarState.Off)
+      }.width("100%").layoutWeight(1).onRefreshing(() => {
+        this.vm.getTasksData({
+          pageNo: 1,
+          pageSize: 10,
+          type: this.vm.tasksPage.type,
+          isRefreshing: true,
+          isGetData: true
+        })
+      })
+    }
+    .width("100%")
+    .height("100%")
+    .clip(false)
+    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
+  }
+
+  /**
+   * 顶部状态栏
+   */
+  @Builder
+  TopBar() {
+    Column() {
+      Row() {
+        Text("我的任务")
+          .fontSize(18)
+          .fontColor(Color.White)
+          .fontWeight(FontWeight.Medium)
+          .height(36)
+          .layoutWeight(1)
+
+        // Stack() {
+        //   Image($r("app.media.add")).width(20).height(20).fillColor(Color.White)
+        // }.width(36).height(24).onClick(() => {
+        // })
+      }
+      .width("100%")
+      .padding({
+        left: 16,
+        top: 15,
+        right: 16
+      })
+
+      Row() {
+        TextInput({ placeholder: "搜索任务名称或任务编号..." })
+          .placeholderColor(Color.White)
+          .fontSize(16)
+          .lineHeight(22)
+          .fontColor(Color.White)
+          .backgroundColor(Color.Transparent)
+          .onChange((value) => {
+            // this.vm.updateCode(value)
+          })
+      }
+      .height(40)
+      .linearGradient({ angle: 90, colors: [['#FFA126', 0.0], ['#FFB126', 1.0]] })
+      .borderRadius("50%")
+      .margin({
+        left: 16,
+        top: 8,
+        right: 16,
+        bottom: 8
+      })
+      .justifyContent(FlexAlign.Center)
+    }
+    .width("100%")
+    .linearGradient({ angle: 90, colors: [['#FF8C00', 0.0], ['#FFA500', 1.0]] })
+    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
+  }
+
+  @Builder
+  TaskType() {
+    Row() {
+      Text("进行中")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.tasksPage.type == "running" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.tasksPage.type == "running" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getTasksData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "running",
+            isGetData: true,
+          })
+        })
+      Text("已完成")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.tasksPage.type == "approved" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.tasksPage.type == "approved" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getTasksData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "approved",
+            isGetData: true,
+          })
+        })
+      Text("全部")
+        .fontSize(14)
+        .lineHeight(20)
+        .fontColor(this.vm.tasksPage.type == "" ? "#FFFFFF" : "#666666")
+        .backgroundColor(this.vm.tasksPage.type == "" ? $r("app.color.main") : "#F0F0F0")
+        .borderRadius("50%")
+        .margin({ right: 10 })
+        .padding({
+          left: 12,
+          right: 12,
+          top: 5,
+          bottom: 5
+        })
+        .onClick(() => {
+          this.vm.getTasksData({
+            pageNo: 1,
+            pageSize: 10,
+            isRefreshing: true,
+            type: "",
+            isGetData: true,
+          })
+        })
+    }.margin({ top: 5, bottom: 5 })
+    .padding({ left: 16, top: 6, right: 16 })
+    .width("100%").justifyContent(FlexAlign.Start)
+  }
+
+  @Builder
+  ListItemTitle(title: string) {
+    Text(title).fontColor("#333333").fontSize(16).height(45)
+  }
+
+  @Builder
+  ListItemContent(task: Task) {
+    CardContainer({ paddings: 16 }) {
+      Column() {
+        Row() {
+          Text(task.name).fontSize(15).fontColor("#333333").fontWeight(FontWeight.Medium)
+          Row().layoutWeight(1)
+          // Text("待办")
+          //   .fontSize(12)
+          //   .fontColor("#333333")
+          //   .backgroundColor("#FFD700")
+          //   .borderRadius(20)
+          //   .height(24)
+          //   .padding({ left: 10, right: 10 })
+          //   .textAlign(TextAlign.Center)
+        }
+
+        Flex({ wrap: FlexWrap.Wrap, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
+          // Image($r("app.media.location")).width(12).height(12).fillColor("#1E90FF").margin({ right: 5 })
+          // Text("车间B区")
+          //   .fontSize(13)
+          //   .fontColor("#666666")
+          //   .margin({ right: 12 })
+          //   .height(24)
+          //   .textAlign(TextAlign.Center)
+          // 编号
+          Image($r("app.media.jobs")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
+          Text(`${task.orderNo}`)
+            .fontSize(13)
+            .fontColor("#666666")
+            .margin({ right: 12 })
+            .height(24)
+            .textAlign(TextAlign.Center)
+          // 负责人
+          Image($r("app.media.user")).width(12).height(12).fillColor("#666666").margin({ right: 5 })
+          Text(`负责人:${task.initiatorName}`)
+            .fontSize(13)
+            .fontColor("#666666")
+            .margin({ right: 12 })
+            .height(24)
+            .textAlign(TextAlign.Center)
+
+        }.margin({ top: 10 })
+
+        Row() {
+          Text(`当前任务:`)
+            .fontSize(13)
+            .fontColor("#666666")
+            .height(24)
+          Text(`${task.currentNodeName ?? '--'}`)
+            .backgroundColor("#1E90FF")
+            .borderRadius(4)
+            .padding({
+              left: 5,
+              top: 3,
+              right: 5,
+              bottom: 3
+            })
+            .fontSize(12)
+            .fontColor(Color.White)
+          Text("今天 14:00")
+            .margin({ left: 10 })
+            .fontColor("#999999")
+            .fontSize(12)
+            .layoutWeight(1)
+            .textAlign(TextAlign.End)
+        }.width("100%").margin({ bottom: -8 })
+      }.width("100%").justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
+    }
+  }
+}

+ 1 - 1
entry/src/main/ets/pages/PageLogin.ets

@@ -96,6 +96,7 @@ struct PageLogin {
             .margin({ top: 30 })
             .border({ radius: 4 })
             .onClick(() => {
+              hideKeyboard()
               this.vm.login(() => {
                 setTimeout(() => {
                   this.getUIContext().getRouter().replaceUrl({ url: 'pages/PageHome' }).catch()
@@ -162,7 +163,6 @@ struct PageLogin {
         .width("100%").height("100%")
       }.width("100%").height("100%")
     }.onClick(() => {
-      console.log("隐藏键盘")
       hideKeyboard()
     })
   }

+ 4 - 3
entry/src/main/ets/pages/PageHomeComponents/TabMessage.ets → entry/src/main/ets/pages/PageMessage.ets

@@ -1,8 +1,9 @@
-import { VMTabMessage } from '../../vm/VMTabMessage'
+import { VMMessage } from '../vm/VMMessage';
 
+@Entry
 @Component
-export struct TabMessage {
-  @State vm: VMTabMessage = new VMTabMessage()
+struct PageMessage {
+  @State vm: VMMessage = new VMMessage()
 
   build() {
     Column() {

+ 2 - 2
entry/src/main/ets/utils/HttpClient.ets

@@ -3,7 +3,7 @@ import { promptAction } from '@kit.ArkUI'
 import { Rsp } from '../api/rsp/Rsp'
 import { Storage } from './Storage'
 import { EventBus } from './EventBus'
-import { ReqApi } from '../api/req/ReqApi'
+import { ApiRequest } from '../api/req/ApiRequest'
 import { Login } from '../api/rsp/Login'
 
 // 请求网络的基址
@@ -79,7 +79,7 @@ async function requestHttp<T>(url: string = '',
         return apiRsp as Rsp<T>
       } else if (apiRsp.code == 401) {
         // 未登录,需要刷新token
-        const rtRsp = await ReqApi.refreshToken(Storage.getRefreshToken()).catch(() => {
+        const rtRsp = await ApiRequest.refreshToken(Storage.getRefreshToken()).catch(() => {
           const err = new Rsp<Login>()
           err.code = 401
           err.msg = "Login expired"

+ 168 - 5
entry/src/main/ets/vm/VMHome.ets

@@ -1,5 +1,9 @@
-import { ReqApi } from '../api/req/ReqApi'
+import { ApiRequest } from '../api/req/ApiRequest'
+import { Job } from '../api/rsp/Job'
+import { Message } from '../api/rsp/Message'
+import { Task } from '../api/rsp/Task'
 import { User } from '../api/rsp/User'
+import { Loading } from '../components/loading/Loading'
 
 @Observed
 export class VMHome {
@@ -9,25 +13,77 @@ export class VMHome {
   user: User = new User()
   // 是否刷新中
   isTabHomeRefreshing: boolean = false
+  // 进行中的任务数
+  taskProgressCount: number = 0
+  // 已完成任务数
+  taskFinishedCount: number = 0
+  // 进行中的作业数
+  jobProgressCount: number = 0
+  // 未读消息数
+  messageUnreadCount: number = 0
+  // 当前进行中的作业列表
+  homeTasks: Task[] = []
+  // 获取最近三条通知
+  homeMessages: Message[] = []
+  // 作业页面Page加载器
+  jobsPage: HomePageLoad = new HomePageLoad()
+  // 作业列表
+  jobs: Job[] = []
+  // 任务页面Page加载器
+  tasksPage: HomePageLoad = new HomePageLoad()
+  // 任务列表
+  tasks: Task[] = []
 
   /**
    * 初始化首页数据
    */
   async init() {
-    this.refreshAllData()
+    this.jobsPage.type = "running"
+    this.tasksPage.type = "running"
+    this.refreshAllData(true).then(async () => {
+      this.getJobsData(this.jobsPage)
+      this.getTasksData(this.tasksPage)
+    })
   }
 
   /**
    * 刷新首页所有数据
    */
-  private async refreshAllData(): Promise<boolean> {
+  private async refreshAllData(showLoading: boolean = false): Promise<boolean> {
     try {
+      if (showLoading) {
+        Loading.showLoading()
+      }
       // 获取权限和用户信息
-      const upRsp = await ReqApi.getUserPermission()
+      const upRsp = await ApiRequest.getUserPermission()
+      // 获取进行中和本月已完成的数据
+      const statisticsRsp = await ApiRequest.getTaskStatistics()
+      // 获取未读消息数
+      const msgCountRsp = await ApiRequest.getMessagesUnread()
+      // 查询进行中的作业,主要为了获取当前进行中的作业数
+      const jobsRsp = await ApiRequest.getJobs({ pageNo: 1, pageSize: 1, status: "running" })
+      // 查询最近三条任务
+      const tasksRsp = await ApiRequest.getTasks({ pageNo: 1, pageSize: 3, approvalStatus: "running" })
+      // 获取最新三条通知
+      const msgRsp = await ApiRequest.getMessages({ pageNo: 1, pageSize: 3 })
+      // 查询进行中的任务
+      // 赋值操作放到最后,统一性
       this.user = upRsp.data?.user ?? new User()
+      this.taskProgressCount = statisticsRsp.data?.inProgressCount ?? 0
+      this.taskFinishedCount = statisticsRsp.data?.completedCount ?? 0
+      this.jobProgressCount = jobsRsp.data?.total ?? 0
+      this.messageUnreadCount = msgCountRsp.data ?? 0
+      this.homeTasks = tasksRsp.data?.list ?? []
+      this.homeMessages = msgRsp.data?.list ?? []
     } catch (e) {
+      setTimeout(() => {
+        Loading.hideLoading()
+      }, 200)
       return false
     }
+    setTimeout(() => {
+      Loading.hideLoading()
+    }, 200)
     return true
   }
 
@@ -36,10 +92,14 @@ export class VMHome {
     this.refreshAllData().then(() => {
       setTimeout(() => {
         this.isTabHomeRefreshing = false
-      }, 1000)
+      }, 200)
     })
   }
 
+  onTabTaskRefresh() {
+
+  }
+
   /**
    * 更新当前选中状态
    * @param index
@@ -47,4 +107,107 @@ export class VMHome {
   updateTabIndex(index: number) {
     this.tabIndex = index
   }
+
+  /**
+   * 获取作业列表
+   *
+   * @param page
+   */
+  getJobsData(page: HomePageLoad) {
+    // 如果当前正在获取数据,则不进行获取
+    if (this.jobsPage.isGetData) {
+      return
+    }
+    this.jobsPage = {
+      pageNo: this.jobsPage.pageNo,
+      pageSize: this.jobsPage.pageSize,
+      type: page.type,
+      isRefreshing: page.isRefreshing,
+      isGetData: true
+    }
+    ApiRequest.getJobs({ pageNo: page.pageNo, pageSize: page.pageSize, status: page.type })
+      .then((rsp) => {
+        setTimeout(() => {
+          if (page.pageNo <= 1) {
+            this.jobs = rsp.data?.list ?? []
+          } else {
+            this.jobs.push(...rsp.data?.list ?? [])
+          }
+          this.jobsPage = {
+            pageNo: page.pageNo,
+            pageSize: this.jobsPage.pageSize,
+            type: this.jobsPage.type,
+            isRefreshing: false,
+            isGetData: false
+          }
+        }, 500)
+      }).catch(() => {
+      setTimeout(() => {
+        this.jobsPage = {
+          pageNo: this.jobsPage.pageNo,
+          pageSize: this.jobsPage.pageSize,
+          type: this.jobsPage.type,
+          isRefreshing: false,
+          isGetData: false
+        }
+      }, 500)
+    })
+  }
+
+  /**
+   * 获取任务数据
+   *
+   * @param page 当前加载的页
+   */
+  getTasksData(page: HomePageLoad) {
+    // 如果当前正在获取数据,则不进行获取
+    if (this.tasksPage.isGetData) {
+      return
+    }
+    this.tasksPage = {
+      pageNo: this.tasksPage.pageNo,
+      pageSize: this.tasksPage.pageSize,
+      type: page.type,
+      isRefreshing: page.isRefreshing,
+      isGetData: true
+    }
+    ApiRequest.getTasks({ pageNo: page.pageNo, pageSize: page.pageSize, approvalStatus: page.type })
+      .then((rsp) => {
+        setTimeout(() => {
+          if (page.pageNo <= 1) {
+            this.tasks = rsp.data?.list ?? []
+          } else {
+            this.tasks.push(...rsp.data?.list ?? [])
+          }
+          this.tasksPage = {
+            pageNo: page.pageNo,
+            pageSize: this.tasksPage.pageSize,
+            type: this.tasksPage.type,
+            isRefreshing: false,
+            isGetData: false
+          }
+        }, 500)
+      }).catch(() => {
+      setTimeout(() => {
+        this.tasksPage = {
+          pageNo: this.tasksPage.pageNo,
+          pageSize: this.tasksPage.pageSize,
+          type: this.tasksPage.type,
+          isRefreshing: false,
+          isGetData: false
+        }
+      }, 500)
+    })
+  }
+}
+
+/**
+ * 首页Page加载器
+ */
+export class HomePageLoad {
+  public pageNo: number = 1
+  public pageSize: number = 10
+  public type: string = ""
+  public isRefreshing: boolean = false
+  public isGetData: boolean = false
 }

+ 2 - 2
entry/src/main/ets/vm/VMLogin.ets

@@ -1,7 +1,7 @@
 import { Loading } from '../components/loading/Loading'
 import { promptAction } from '@kit.ArkUI'
 import { hideKeyboard } from '../utils/SysUtils'
-import { ReqApi } from '../api/req/ReqApi'
+import { ApiRequest } from '../api/req/ApiRequest'
 import { Storage } from '../utils/Storage'
 
 @Observed
@@ -36,7 +36,7 @@ export class VMLogin {
     }
     hideKeyboard()
     Loading.showLoading({ text: '登录中...' })
-    ReqApi.login(this.account.trim(), this.code).then((rsp) => {
+    ApiRequest.login(this.account.trim(), this.code).then((rsp) => {
       this.isLogin = true
       Storage.setLogin(true)
       Storage.setToken(rsp.data?.accessToken ?? "")

+ 1 - 1
entry/src/main/ets/vm/VMTabJobs.ets → entry/src/main/ets/vm/VMMessage.ets

@@ -1,5 +1,5 @@
 @Observed
-export class VMTabJobs {
+export class VMMessage {
   isRefreshing: boolean = false
 
   onRefresh() {

+ 0 - 11
entry/src/main/ets/vm/VMTabMessage.ets

@@ -1,11 +0,0 @@
-@Observed
-export class VMTabMessage {
-  isRefreshing: boolean = false
-
-  onRefresh() {
-    this.isRefreshing = true
-    setTimeout(() => {
-      this.isRefreshing = false
-    }, 3000)
-  }
-}

+ 1 - 1
entry/src/main/resources/base/element/float.json

@@ -5,4 +5,4 @@
       "value": "50fp"
     }
   ]
-}
+}

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

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1766632828544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="73158" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M224.924444 967.111111C153.813333 967.111111 128 929.578667 128 862.620444V242.659556c0-62.421333 18.033778-105.671111 91.448889-105.671112h56.988444s32.711111 10.168889 32.711111 15.246223c0 38.727111 26.936889 79.018667 60.757334 79.018666h277.12c32.199111 0 59.136-40.206222 59.136-78.933333 0-5.077333 36.494222-15.246222 36.494222-15.246222h55.779556c67.726222 0 100.977778 43.278222 100.977777 105.671111v619.875555c0 75.064889-35.456 104.490667-106.510222 104.490667H224.924444z m63.104-420.366222a40.647111 40.647111 0 0 0 0.213334 56.675555l118.385778 118.528 1.607111 2.062223a38.812444 38.812444 0 0 0 55.808 0l251.889777-253.952a39.537778 39.537778 0 0 0-55.594666-56.234667L436.024889 639.544889l-91.776-93.44a40.604444 40.604444 0 0 0-27.875556-11.121778 40.064 40.064 0 0 0-28.344889 11.690667v0.071111z m125.454223-382.321778c-22.101333 0-39.921778-30.392889-40.035556-55.808C373.333333 83.2 391.196444 56.888889 413.482667 56.888889h190.791111c22.215111 0 40.035556 26.296889 40.035555 51.712 0 25.415111-17.820444 55.808-38.855111 55.808l-191.971555 0.014222z" fill="#323233" p-id="73159"></path></svg>

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

@@ -2,6 +2,7 @@
   "src": [
     "pages/PageSplash",
     "pages/PageLogin",
-    "pages/PageHome"
+    "pages/PageHome",
+    "pages/PageMessage"
   ]
-}
+}