소스 검색

更新移动端

余思翰 3 달 전
부모
커밋
118c295aa7
30개의 변경된 파일1757개의 추가작업 그리고 648개의 파일을 삭제
  1. 10
    0
      oa-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/oa/CmcBorrowDetailController.java
  2. 8
    0
      oa-back/ruoyi-system/src/main/java/com/ruoyi/oa/mapper/CmcBorrowDetailMapper.java
  3. 8
    0
      oa-back/ruoyi-system/src/main/java/com/ruoyi/oa/service/ICmcBorrowDetailService.java
  4. 13
    0
      oa-back/ruoyi-system/src/main/java/com/ruoyi/oa/service/impl/CmcBorrowDetailServiceImpl.java
  5. 7
    0
      oa-back/ruoyi-system/src/main/resources/mapper/oa/CmcBorrowDetailMapper.xml
  6. 8
    0
      oa-ui-app/api/oa/borrow/borrowDetail.js
  7. 139
    0
      oa-ui-app/api/system/post.js
  8. 7
    1
      oa-ui-app/config.js
  9. 30
    3
      oa-ui-app/pages.json
  10. 0
    2
      oa-ui-app/pages/components/ProjectPicker.vue
  11. 21
    0
      oa-ui-app/pages/emptyBox.vue
  12. 149
    0
      oa-ui-app/pages/form/borrow/borrow.vue
  13. 297
    0
      oa-ui-app/pages/form/borrow/borrowDetail.vue
  14. 461
    0
      oa-ui-app/pages/form/declare/declare.vue
  15. 65
    45
      oa-ui-app/pages/message/apply/apply.vue
  16. 0
    398
      oa-ui-app/pages/message/apply/components/declare/declare.vue
  17. 83
    46
      oa-ui-app/pages/message/apply/detail.vue
  18. 21
    0
      oa-ui-app/pages/message/completed/index.vue
  19. 83
    50
      oa-ui-app/pages/message/index.vue
  20. 15
    0
      oa-ui-app/pages/message/myProcess/index.vue
  21. 199
    89
      oa-ui-app/pages/work/index.vue
  22. BIN
      oa-ui-app/static/images/message/completed.png
  23. BIN
      oa-ui-app/static/images/message/flowable.png
  24. BIN
      oa-ui-app/static/images/user.png
  25. 45
    1
      oa-ui-app/static/scss/global.scss
  26. 1
    1
      oa-ui-app/store/getters.js
  27. 13
    6
      oa-ui-app/store/modules/user.js
  28. 2
    1
      oa-ui-app/utils/constant.js
  29. 61
    0
      oa-ui-app/utils/snowFlake.js
  30. 11
    5
      oa-ui-app/utils/storage.js

+ 10
- 0
oa-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/oa/CmcBorrowDetailController.java 파일 보기

@@ -96,4 +96,14 @@ public class CmcBorrowDetailController extends BaseController
96 96
     {
97 97
         return success(cmcBorrowDetailService.deleteCmcBorrowDetailByBorrowIds(borrowIds));
98 98
     }
99
+
100
+    /**
101
+     * 删除cmc借款明细通过borrowDetailId
102
+     */
103
+    @Log(title = "cmc借款明细", businessType = BusinessType.DELETE)
104
+    @DeleteMapping("/id/{borrowDetailId}")
105
+    public AjaxResult removeByBorrowDetailId(@PathVariable String[] borrowDetailId)
106
+    {
107
+        return success(cmcBorrowDetailService.deleteCmcBorrowDetailByBorrowDetailId(borrowDetailId));
108
+    }
99 109
 }

+ 8
- 0
oa-back/ruoyi-system/src/main/java/com/ruoyi/oa/mapper/CmcBorrowDetailMapper.java 파일 보기

@@ -58,4 +58,12 @@ public interface CmcBorrowDetailMapper
58 58
      * @return 结果
59 59
      */
60 60
     public int deleteCmcBorrowDetailByBorrowIds(String[] borrowIds);
61
+
62
+    /**
63
+     * 批量删除cmc借款明细
64
+     *
65
+     * @param borrowIds 需要删除的数据主键集合
66
+     * @return 结果
67
+     */
68
+    public int deleteCmcBorrowDetailByBorrowDetailId(String[] borrowDetailId);
61 69
 }

+ 8
- 0
oa-back/ruoyi-system/src/main/java/com/ruoyi/oa/service/ICmcBorrowDetailService.java 파일 보기

@@ -58,4 +58,12 @@ public interface ICmcBorrowDetailService
58 58
      * @return 结果
59 59
      */
60 60
     public int deleteCmcBorrowDetailByBorrowId(String borrowId);
61
+
62
+    /**
63
+     * 批量删除cmc借款明细
64
+     *
65
+     * @param borrowIds 需要删除的cmc借款明细主键集合
66
+     * @return 结果
67
+     */
68
+    public int deleteCmcBorrowDetailByBorrowDetailId(String[] borrowDetailId);
61 69
 }

+ 13
- 0
oa-back/ruoyi-system/src/main/java/com/ruoyi/oa/service/impl/CmcBorrowDetailServiceImpl.java 파일 보기

@@ -90,4 +90,17 @@ public class CmcBorrowDetailServiceImpl implements ICmcBorrowDetailService
90 90
     {
91 91
         return cmcBorrowDetailMapper.deleteCmcBorrowDetailByBorrowId(borrowId);
92 92
     }
93
+
94
+    /**
95
+     * 批量删除cmc借款明细
96
+     *
97
+     * @param borrowIds 需要删除的cmc借款明细主键
98
+     * @return 结果
99
+     */
100
+    @Override
101
+    public int deleteCmcBorrowDetailByBorrowDetailId(String[] borrowDetailId)
102
+    {
103
+        return cmcBorrowDetailMapper.deleteCmcBorrowDetailByBorrowDetailId(borrowDetailId);
104
+    }
105
+
93 106
 }

+ 7
- 0
oa-back/ruoyi-system/src/main/resources/mapper/oa/CmcBorrowDetailMapper.xml 파일 보기

@@ -85,4 +85,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
85 85
             #{borrowId}
86 86
         </foreach>
87 87
     </delete>
88
+
89
+    <delete id="deleteCmcBorrowDetailByBorrowDetailId" parameterType="String">
90
+        delete from cmc_borrow_detail where borrow_detail_id in
91
+        <foreach item="borrowDetailId" collection="array" open="(" separator="," close=")">
92
+            #{borrowDetailId}
93
+        </foreach>
94
+    </delete>
88 95
 </mapper>

+ 8
- 0
oa-ui-app/api/oa/borrow/borrowDetail.js 파일 보기

@@ -42,3 +42,11 @@ export function delBorrowDetail(borrowId) {
42 42
     method: 'delete'
43 43
   })
44 44
 }
45
+
46
+// 删除cmc借款明细根据每一项Id
47
+export function delBorrowDetailByDetailId(borrowDetailId) {
48
+  return request({
49
+    url: '/oa/borrowDetail/id' + borrowDetailId,
50
+    method: 'delete'
51
+  })
52
+}

+ 139
- 0
oa-ui-app/api/system/post.js 파일 보기

@@ -0,0 +1,139 @@
1
+/*
2
+ * @Author: wrh
3
+ * @Date: 2024-03-07 17:33:37
4
+ * @LastEditors: wrh
5
+ * @LastEditTime: 2024-05-22 16:17:43
6
+ */
7
+import request from '@/utils/request'
8
+
9
+// 查询岗位列表
10
+export function listPost(query) {
11
+  return request({
12
+    url: '/system/post/list',
13
+    method: 'get',
14
+    params: query
15
+  })
16
+}
17
+
18
+// 根据岗位查用户
19
+export function getUserByPost(query) {
20
+  return request({
21
+    url: '/system/post/postName',
22
+    method: 'get',
23
+    params: query
24
+  })
25
+}
26
+
27
+// 查询岗位详细
28
+export function getPost(postId) {
29
+  return request({
30
+    url: '/system/post/' + postId,
31
+    method: 'get'
32
+  })
33
+}
34
+
35
+// 新增岗位
36
+export function addPost(data) {
37
+  return request({
38
+    url: '/system/post',
39
+    method: 'post',
40
+    data: data
41
+  })
42
+}
43
+
44
+// 修改岗位
45
+export function updatePost(data) {
46
+  return request({
47
+    url: '/system/post',
48
+    method: 'put',
49
+    data: data
50
+  })
51
+}
52
+
53
+// 删除岗位
54
+export function delPost(postId) {
55
+  return request({
56
+    url: '/system/post/' + postId,
57
+    method: 'delete'
58
+  })
59
+}
60
+
61
+// 通过deptId获取是否部门负责人
62
+export function getIsDeptLeader() {
63
+  return request({
64
+    url: '/system/post/isDeptLeader',
65
+    method: 'get'
66
+  })
67
+}
68
+
69
+// 查询当前用户的部门负责人
70
+export function getUsersDeptLeader(query) {
71
+  return request({
72
+    url: '/system/post/deptLeader',
73
+    method: 'get',
74
+    params: query
75
+  })
76
+}
77
+
78
+// 查询经营部门的部门负责人
79
+export function getDeptLeaders(query) {
80
+  return request({
81
+    url: '/system/post/deptLeaders',
82
+    method: 'get',
83
+    params: query
84
+  })
85
+}
86
+
87
+// 查询当前部门的部门负责人
88
+export function getUsersDeptLeaderByDept(query) {
89
+  return request({
90
+    url: '/system/post/deptLeaderByDept',
91
+    method: 'get',
92
+    params: query
93
+  })
94
+}
95
+
96
+// 查询经营部门的部门负责人
97
+export function getDeptLeadersByDeptId(query) {
98
+  return request({
99
+    url: '/system/post/deptLeadersByDept',
100
+    method: 'get',
101
+    params: query
102
+  })
103
+}
104
+
105
+// 查询当前用户的部门负责人
106
+export function getUsersViceDeptLeader(query) {
107
+  return request({
108
+    url: '/system/post/deptViceLeader',
109
+    method: 'get',
110
+    params: query
111
+  })
112
+}
113
+
114
+// 查询当前部门的部门负责人
115
+export function getUsersViceDeptLeaderByDept(query) {
116
+  return request({
117
+    url: '/system/post/deptViceLeaderByDept',
118
+    method: 'get',
119
+    params: query
120
+  })
121
+}
122
+
123
+// 查询当前用户的分管领导
124
+export function getUsersManageLeader(query) {
125
+  return request({
126
+    url: '/system/post/manageLeader',
127
+    method: 'get',
128
+    params: query
129
+  })
130
+}
131
+
132
+// 查询当前部门的分管领导
133
+export function getUsersManageLeaderByDept(query) {
134
+  return request({
135
+    url: '/system/post/manageLeaderByDept',
136
+    method: 'get',
137
+    params: query
138
+  })
139
+}

+ 7
- 1
oa-ui-app/config.js 파일 보기

@@ -1,7 +1,13 @@
1
+/*
2
+ * @Author: ysh
3
+ * @Date: 2025-01-16 11:17:07
4
+ * @LastEditors: 
5
+ * @LastEditTime: 2025-02-27 10:25:33
6
+ */
1 7
 // 应用全局配置
2 8
 module.exports = {
3 9
   // baseUrl: 'https://vue.ruoyi.vip/prod-api',
4
-  baseUrl: 'http://192.168.28.119:8080',
10
+  baseUrl: 'http://192.168.28.107:8080',
5 11
   // 应用信息
6 12
   appInfo: {
7 13
     // 应用名称

+ 30
- 3
oa-ui-app/pages.json 파일 보기

@@ -1,3 +1,9 @@
1
+/*
2
+ * @Author: ysh
3
+ * @Date: 2025-01-15 14:42:34
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-20 10:20:46
6
+ */
1 7
 {
2 8
 	"pages": [{
3 9
 			"path": "pages/login",
@@ -80,6 +86,20 @@
80 86
 				"enablePullDownRefresh": true
81 87
 			}
82 88
 		},
89
+		{
90
+			"path": "pages/message/completed/index",
91
+			"style": {
92
+				"navigationBarTitleText": "已办任务",
93
+				"enablePullDownRefresh": true
94
+			}
95
+		},
96
+		{
97
+			"path": "pages/message/myProcess/index",
98
+			"style": {
99
+				"navigationBarTitleText": "我的流程",
100
+				"enablePullDownRefresh": true
101
+			}
102
+		},
83 103
 		{
84 104
 			"path" : "pages/message/apply/detail",
85 105
 			"style" : 
@@ -88,10 +108,17 @@
88 108
 			}
89 109
 		},
90 110
 		{
91
-			"path" : "pages/message/apply/components/declare/declare",
111
+			"path" : "pages/form/declare/declare",
112
+			"style" : 
113
+			{
114
+				"navigationBarTitleText" : "工作填报"
115
+			}
116
+		},
117
+		{
118
+			"path" : "pages/form/borrow/borrow",
92 119
 			"style" : 
93 120
 			{
94
-				"navigationBarTitleText" : ""
121
+				"navigationBarTitleText" : "借款审批"
95 122
 			}
96 123
 		}
97 124
 	],
@@ -126,7 +153,7 @@
126 153
 	},
127 154
 	"globalStyle": {
128 155
 		"navigationBarTextStyle": "black",
129
-		"navigationBarTitleText": "RuoYi",
156
+		"navigationBarTitleText": "CMC",
130 157
 		"navigationBarBackgroundColor": "#FFFFFF"
131 158
 	}
132 159
 }

+ 0
- 2
oa-ui-app/pages/components/ProjectPicker.vue 파일 보기

@@ -135,8 +135,6 @@
135 135
 							pageSize: this.pageSize
136 136
 						});
137 137
 					}
138
-
139
-					console.log(res)
140 138
 					this.projectList = this.currentPage === 1 ?
141 139
 						res.rows : [...this.projectList, ...res.rows];
142 140
 

+ 21
- 0
oa-ui-app/pages/emptyBox.vue 파일 보기

@@ -0,0 +1,21 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-02-19 16:58:25
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-20 09:46:49
6
+-->
7
+<template>
8
+  <view>
9
+    <u-empty mode="list" icon="list" text="抱歉,移动端暂未更新此页面,请前往网页端查看"></u-empty>
10
+  </view>
11
+</template>
12
+
13
+<script>
14
+  export default {
15
+    
16
+  }
17
+</script>
18
+
19
+<style lang="scss" scoped>
20
+
21
+</style>

+ 149
- 0
oa-ui-app/pages/form/borrow/borrow.vue 파일 보기

@@ -0,0 +1,149 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-02-20 10:20:22
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-27 10:49:10
6
+-->
7
+<template>
8
+  <view class="form-container">
9
+    <!-- 表单标题 -->
10
+    <view class="form-title">
11
+      <text class="title-text">借款审批</text>
12
+      <view class="title-line"></view>
13
+    </view>
14
+    <!-- 表单内容 -->
15
+    <uni-forms ref="form" :modelValue="form" :rules="rules" label-position="top" label-width="150" class="custom-form">
16
+      <!-- 当前节点 -->
17
+      <uni-forms-item label="当前节点" class="form-item">
18
+        <uni-tag :inverted="true" type="primary" :text="taskName"></uni-tag>
19
+      </uni-forms-item>
20
+
21
+      <!-- 流程发起人 -->
22
+      <uni-forms-item label="填报人" class="form-item">
23
+        <uni-tag :inverted="true" type="primary" :text="startUserName"></uni-tag>
24
+      </uni-forms-item>
25
+
26
+      <!-- 填报日期 -->
27
+      <uni-forms-item label="填报日期" class="form-item">
28
+        <text>{{ form.applyDate }}</text>
29
+      </uni-forms-item>
30
+
31
+      <!-- 借款类型 -->
32
+      <uni-forms-item label="借款类型" required class="form-item" name="borrowUsage">
33
+        <uni-data-checkbox v-model="form.borrowUsage" :localdata="borrowUsageOptions"></uni-data-checkbox>
34
+      </uni-forms-item>
35
+
36
+      <!-- 借款类型 -->
37
+      <uni-forms-item label="借款事由" required class="form-item" name="applyReason" v-if="form.borrowUsage != 0">
38
+        <uv-textarea v-model="form.applyReason" placeholder="请输入借款事由"></uv-textarea>
39
+      </uni-forms-item>
40
+
41
+      <!-- 选择项目 -->
42
+      <uni-forms-item label="选择项目" required class="form-item" v-if="form.borrowUsage == 0" name="projectId">
43
+        <u-button type="primary" @click="openProject = true" v-if="taskName == '借款申请'">选择项目</u-button>
44
+        <ProjectPicker :visible.sync="openProject" :selected.sync="selectedProject" @confirm="handleConfirm" />
45
+        <ProjectInfo :project="projectObj"></ProjectInfo>
46
+      </uni-forms-item>
47
+
48
+      <!-- 借款明细 -->
49
+      <uni-forms-item label="借款明细" required class="form-item">
50
+        <BorrowDetail :borrowId="form.borrowId"></BorrowDetail>
51
+      </uni-forms-item>
52
+
53
+    </uni-forms>
54
+
55
+
56
+  </view>
57
+</template>
58
+
59
+<script>
60
+import ProjectPicker from '@/pages/components/ProjectPicker.vue';
61
+import ProjectInfo from '@/pages/components/ProjectInfo.vue';
62
+import { parseTime } from "@/utils/common.js"
63
+import { listBorrow, getBorrow, delBorrow, addBorrow, updateBorrow } from "@/api/oa/borrow/borrow";
64
+import { listProject, getProject } from "@/api/oa/project/project";
65
+import BorrowDetail from './borrowDetail.vue';
66
+export default {
67
+  components: {
68
+    ProjectPicker,
69
+    ProjectInfo,
70
+    BorrowDetail
71
+  },
72
+  props: {
73
+    taskForm: Object,
74
+    taskName: String, // 当前节点
75
+    startUserName: String, // 流程发起人
76
+  },
77
+  created() {
78
+    this.initForm();
79
+    uni.setNavigationBarTitle({
80
+      title: '借款审批'
81
+    });
82
+  },
83
+  data() {
84
+    return {
85
+      form: {
86
+        submitTime: '',
87
+        borrowUsage: '0',
88
+      },
89
+      rules: {},
90
+      borrowUsageOptions: [{
91
+        text: '项目借款',
92
+        value: '0',
93
+        disable: false
94
+      }, {
95
+        text: '非项目借款',
96
+        value: '1',
97
+        disable: false
98
+      }, {
99
+        text: '工会借款',
100
+        value: '2',
101
+        disable: false
102
+      }, {
103
+        text: '党委借款',
104
+        value: '3',
105
+        disable: false
106
+      }, {
107
+        text: '团委借款',
108
+        value: '4',
109
+        disable: false
110
+      }
111
+      ],
112
+      openProject: false,
113
+      selectedProject: null, //选中的项目
114
+      projectObj: {}, //项目信息的项目
115
+      fromTotal: 0,
116
+    }
117
+  },
118
+  methods: {
119
+    initForm() {
120
+      getBorrow(this.taskForm.formId).then(res => {
121
+        if (res.data) {
122
+          this.fromTotal = 1;
123
+          this.form = res.data;
124
+          console.log(this.form);
125
+          if (this.form.projectId) {
126
+            getProject(this.form.projectId).then(res => {
127
+              if (res.data) {
128
+                this.selectedProject = res.data;
129
+                this.projectObj = res.data;
130
+              }
131
+            })
132
+          }
133
+        } else {
134
+          this.fromTotal = 0;
135
+          this.form.applier = this.$store.getters.userId;
136
+          this.form.applyDate = parseTime(new Date(), "{y}-{m}-{d}");
137
+        }
138
+      })
139
+    },
140
+    handleConfirm(project) {
141
+      console.log('选中的项目:', project);
142
+      this.selectedProject = project;
143
+      this.projectObj = project;
144
+    },
145
+  },
146
+}
147
+</script>
148
+
149
+<style lang="scss" scoped></style>

+ 297
- 0
oa-ui-app/pages/form/borrow/borrowDetail.vue 파일 보기

@@ -0,0 +1,297 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-02-27 10:43:04
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-28 16:27:00
6
+-->
7
+<template>
8
+  <view class="container">
9
+    <u-button type="primary" @click="showAddPopup = true">+ 新增借款项</u-button>
10
+    <!-- 列表标题 -->
11
+    <view class="list-header">
12
+      <text class="header-item">开支项目</text>
13
+      <text class="header-item amount">申请金额</text>
14
+    </view>
15
+
16
+    <!-- 数据列表 -->
17
+    <view class="list-box" v-for="(item, index) in detailList" :key="item.borrowDetailId">
18
+      <view class="indexs">
19
+        <text>{{ index + 1 }}</text>
20
+      </view>
21
+      <view class="list-item">
22
+        <view class="item-left">
23
+          <text class="item-title">{{ item.borrowItem }}</text>
24
+          <text class="item-sub">
25
+            ¥{{ item.price }} × {{ item.quantity }}{{ item.unit }}
26
+          </text>
27
+        </view>
28
+        <view class="item-right">
29
+          <text class="total-amount">¥{{ item.applyAmount }}</text>
30
+        </view>
31
+      </view>
32
+      <!-- <view class="fg-amount">
33
+        <text>分管领导审核金额</text>
34
+        <uni-easyinput v-model="item.managerAmount" placeholder="请输入审核金额" />
35
+      </view> -->
36
+      <view class="box-button">
37
+        <u-button size="normal" icon="edit-pen">修改</u-button>
38
+        <u-button size="normal" icon="trash" @click="deleteItem(item)">删除</u-button>
39
+      </view>
40
+    </view>
41
+
42
+    <!-- 借款弹窗 -->
43
+    <view v-if="showAddPopup" class="add-popup">
44
+
45
+      <view class="popup-content">
46
+        <text class="popup-title">新增借款项</text>
47
+
48
+        <uni-forms ref="form" :modelValue="newItem" :rules="rules" label-position="top" label-width="150"
49
+          class="custom-form">
50
+          <uni-forms-item label="开支项目" name="borrowItem" required class="form-item">
51
+            <uni-easyinput v-model="newItem.borrowItem" placeholder="请输入开支项目" />
52
+          </uni-forms-item>
53
+          <uni-forms-item label="单位" name="unit" required class="form-item">
54
+            <uni-easyinput v-model="newItem.unit" placeholder="请输入单位" />
55
+          </uni-forms-item>
56
+          <uni-forms-item label="单价" name="price" required class="form-item">
57
+            <uni-easyinput type="number" v-model="newItem.price" placeholder="请输入单价" />
58
+          </uni-forms-item>
59
+          <uni-forms-item label="数量" name="quantity" required class="form-item">
60
+            <uni-easyinput type="number" v-model="newItem.quantity" placeholder="请输入数量" />
61
+          </uni-forms-item>
62
+          <uni-forms-item label="合计">
63
+            <text>{{ getTotal() }}</text>
64
+          </uni-forms-item>
65
+        </uni-forms>
66
+        <view class="popup-buttons">
67
+          <u-button @click="cancelAdd">取消</u-button>
68
+          <u-button type="primary" class="confirm" @click="confirmAdd">确认添加</u-button>
69
+        </view>
70
+      </view>
71
+    </view>
72
+  </view>
73
+</template>
74
+
75
+<script>
76
+import { listBorrowDetail, addBorrowDetail, updateBorrowDetail, delBorrowDetail, delBorrowDetailByDetailId } from "@/api/oa/borrow/borrowDetail";
77
+import uButton from '../../../uni_modules/uview-ui/components/u-button/u-button.vue';
78
+export default {
79
+  components: { uButton },
80
+  props: {
81
+    borrowId: String
82
+  },
83
+  data() {
84
+    return {
85
+      detailList: [],
86
+      showAddPopup: false,
87
+      newItem: {
88
+        borrowItem: '',
89
+        unit: '',
90
+        price: '',
91
+        quantity: '',
92
+        applyAmount: 0
93
+      },
94
+      rules: {},
95
+      errorMessage: '',
96
+    }
97
+  },
98
+  created() {
99
+  },
100
+  watch: {
101
+    borrowId() {
102
+      this.initList();
103
+    }
104
+  },
105
+  methods: {
106
+    initList() {
107
+      listBorrowDetail({ pageSize: 999, borrowId: this.borrowId }).then(res => {
108
+        if (res.rows.length != 0) {
109
+          this.detailList = res.rows
110
+          console.log(res.rows);
111
+        }
112
+      });
113
+    },
114
+    // 确认添加
115
+    confirmAdd() {
116
+      this.$refs.form.validate().then(res => {
117
+        console.log('表单数据信息:', res);
118
+        res.borrowId = this.borrowId;
119
+        res.applyAmount = this.getTotal();
120
+        addBorrowDetail(res);
121
+        // this.detailList.unshift({
122
+        //   borrowId: this.borrowId,
123
+        //   borrowItem: this.newItem.borrowItem,
124
+        //   unit: this.newItem.unit,
125
+        //   price: Number(this.newItem.price),
126
+        //   quantity: Number(this.newItem.quantity),
127
+        //   applyAmount: Number(this.newItem.price) * Number(this.newItem.quantity)
128
+        // })
129
+        // console.log(this.detailList);
130
+        this.clearForm()
131
+        this.showAddPopup = false
132
+        this.initList();
133
+      })
134
+
135
+    },
136
+
137
+    // 清空表单
138
+    clearForm() {
139
+      this.newItem = {
140
+        borrowItem: '',
141
+        unit: '',
142
+        price: '',
143
+        quantity: '',
144
+        applyAmount: 0
145
+      }
146
+    },
147
+
148
+    // 取消添加
149
+    cancelAdd() {
150
+      this.clearForm()
151
+      this.showAddPopup = false
152
+    },
153
+    getTotal() {
154
+      return (Number(this.newItem.price) * Number(this.newItem.quantity)).toFixed(2)
155
+    },
156
+    deleteItem(item) {
157
+      this.$modal.confirm('是否删除开支项目为'+item.borrowItem+'的项?').then(() => {
158
+        delBorrowDetailByDetailId(item.borrowDetailId).then(res => {
159
+          this.$message.success(res.msg)
160
+        })
161
+      })
162
+
163
+    }
164
+  },
165
+}
166
+</script>
167
+
168
+<style lang="scss" scoped>
169
+.container {
170
+  padding: 20rpx 30rpx;
171
+  background-color: #f8f8f8;
172
+}
173
+
174
+/* 列表标题样式 */
175
+.list-header {
176
+  display: flex;
177
+  justify-content: space-between;
178
+  padding: 20rpx 0;
179
+  font-weight: bold;
180
+  border-bottom: 1rpx solid #eee;
181
+}
182
+
183
+.list-box {
184
+  margin-bottom: 20rpx;
185
+  padding: 30rpx 10rpx;
186
+  border-bottom: 1rpx solid #eee;
187
+  background-color: #fff;
188
+  border-radius: 12rpx;
189
+  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
190
+
191
+  .indexs {
192
+    font-size: 25rpx;
193
+    height: 30rpx;
194
+    position: relative;
195
+
196
+    text {
197
+      display: block;
198
+      position: absolute;
199
+      right: 10rpx;
200
+      width: 32rpx;
201
+      height: 32rpx;
202
+      text-align: center;
203
+    }
204
+  }
205
+
206
+  .box-button {
207
+    display: flex;
208
+    padding: 10rpx;
209
+
210
+  }
211
+}
212
+
213
+/* 列表项样式 */
214
+.list-item {
215
+  display: flex;
216
+  justify-content: space-between;
217
+  align-items: center;
218
+}
219
+
220
+.item-left {
221
+  flex: 1;
222
+}
223
+
224
+.item-title {
225
+  display: block;
226
+  font-size: 32rpx;
227
+  font-weight: bold;
228
+  color: #333;
229
+  margin-bottom: 15rpx;
230
+}
231
+
232
+.item-sub {
233
+  font-size: 26rpx;
234
+  color: #999;
235
+}
236
+
237
+.total-amount {
238
+  font-size: 30rpx;
239
+  color: #f1a532;
240
+  font-weight: bold;
241
+  padding-right: 30rpx;
242
+}
243
+
244
+.delete {
245
+  font-size: 30rpx;
246
+  color: #ff6a6c;
247
+  font-weight: bold;
248
+}
249
+
250
+.edit {
251
+  font-size: 30rpx;
252
+  color: #3c9cff;
253
+  font-weight: bold;
254
+  padding-right: 20rpx;
255
+}
256
+
257
+/* 金额列对齐 */
258
+.amount {
259
+  min-width: 100rpx;
260
+  padding-right: 20rpx;
261
+}
262
+
263
+
264
+.item-right {
265
+  min-width: 200rpx;
266
+  text-align: right;
267
+}
268
+
269
+
270
+
271
+.add-popup {
272
+  position: fixed;
273
+  top: 0;
274
+  left: 0;
275
+  right: 0;
276
+  bottom: 0;
277
+  background-color: rgba(0, 0, 0, 0.5);
278
+  display: flex;
279
+  justify-content: center;
280
+  align-items: center;
281
+  z-index: 999;
282
+}
283
+
284
+.popup-content {
285
+  background-color: white;
286
+  width: 600rpx;
287
+  padding: 40rpx;
288
+  border-radius: 20rpx;
289
+}
290
+
291
+.popup-title {
292
+  font-size: 36rpx;
293
+  font-weight: bold;
294
+  display: block;
295
+  margin-bottom: 40rpx;
296
+}
297
+</style>

+ 461
- 0
oa-ui-app/pages/form/declare/declare.vue 파일 보기

@@ -0,0 +1,461 @@
1
+<template>
2
+	<view class="form-container">
3
+		<!-- 表单标题 -->
4
+		<view class="form-title">
5
+			<text class="title-text">工作填报</text>
6
+			<view class="title-line"></view>
7
+		</view>
8
+		<!-- 表单内容 -->
9
+		<uni-forms ref="form" :modelValue="formData" :rules="rules" label-position="top" label-width="150"
10
+			class="custom-form">
11
+			<!-- 当前节点 -->
12
+			<uni-forms-item label="当前节点" class="form-item">
13
+				<uni-tag :inverted="true" type="primary" :text="taskName"></uni-tag>
14
+			</uni-forms-item>
15
+
16
+			<!-- 流程发起人 -->
17
+			<uni-forms-item label="填报人" class="form-item">
18
+				<uni-tag :inverted="true" type="primary" :text="startUserName"></uni-tag>
19
+			</uni-forms-item>
20
+
21
+			<!-- 填报日期 -->
22
+			<uni-forms-item label="填报日期" class="form-item">
23
+				<text>{{ formData.submitTime }}</text>
24
+			</uni-forms-item>
25
+			<!-- 是否零星项目 -->
26
+			<uni-forms-item label="是否零星项目" class="form-item" name="isScattered">
27
+				<uni-data-checkbox v-model="isScattered" :localdata="isScatteredOptions"></uni-data-checkbox>
28
+			</uni-forms-item>
29
+
30
+			<!-- 选择项目 -->
31
+			<uni-forms-item label="选择项目" required class="form-item" v-if="!isScattered" name="projectId">
32
+				<!-- <ProjectPicker v-model="formData.projectId" placeholder="请选择项目" :labelKey="'projectName'"
33
+					:valueKey="'projectId'" @change="handleProjectChange"
34
+					:customStyle="{ borderColor: '#e5e5e5', borderRadius: '8px' }" v-if="taskName == '工作填报'" /> -->
35
+				<!-- <ProjectInfo :project="projectObj" v-else></ProjectInfo> -->
36
+				<u-button type="primary" @click="openProject = true" v-if="taskName == '工作填报'">选择项目</u-button>
37
+				<ProjectPicker :visible.sync="openProject" :selected.sync="selectedProject" @confirm="handleConfirm" />
38
+				<ProjectInfo :project="projectObj"></ProjectInfo>
39
+			</uni-forms-item>
40
+
41
+			<!-- 工作类别 -->
42
+			<uni-forms-item label="工作类别" required class="form-item" name="workType">
43
+				<uni-data-select :disabled="taskName != '工作填报'" :clear="taskName == '工作填报'" v-model="formData.workType"
44
+					:localdata="workTypeColumns" @change="bindWorkTypeChange"></uni-data-select>
45
+			</uni-forms-item>
46
+
47
+			<!-- 工作细项 -->
48
+			<uni-forms-item label="工作细项" required class="form-item" name="workItem">
49
+				<picker @change="bindWorkItemChange" :value="formData.workItem" :range="workItemList"
50
+					:disabled="taskName != '工作填报'">
51
+					<view class="uni-input">
52
+						<uni-easyinput type="text" :disabled="taskName != '工作填报'" v-model="formData.workItem"
53
+							@click="showType = true" placeholder="请选择" :styles="inputStyle" />
54
+					</view>
55
+				</picker>
56
+			</uni-forms-item>
57
+
58
+			<!-- 具体内容 -->
59
+			<uni-forms-item label="具体内容" required class="form-item" name="workContent">
60
+				<uni-easyinput :disabled="taskName != '工作填报'" type="textarea" v-model="formData.workContent"
61
+					placeholder="请输入具体工作内容" :styles="textareaStyle" />
62
+			</uni-forms-item>
63
+
64
+			<!-- 工天 -->
65
+			<uni-forms-item label="工天" required class="form-item" name="workLoad">
66
+				<uni-easyinput :disabled="taskName != '工作填报'" type="number" v-model="formData.workLoad" placeholder="请输入所需工天"
67
+					:styles="inputStyle">
68
+					<text slot="right" class="unit">天</text>
69
+				</uni-easyinput>
70
+			</uni-forms-item>
71
+
72
+			<uni-forms-item label="系数" required class="form-item" name="coefficient" v-if="taskName != '工作填报'">
73
+				<uni-easyinput type="number" v-model="formData.coefficient" placeholder="请输入系数" :styles="inputStyle"
74
+					@blur="countMoney" @clear="countMoney" :disabled="taskName == '填报人确认'">
75
+				</uni-easyinput>
76
+			</uni-forms-item>
77
+
78
+			<uni-forms-item label="工天单价" class="form-item" v-if="taskName != '工作填报'">
79
+				<u-tag :text="formData.price + '/人天'" type="success" plain></u-tag>
80
+			</uni-forms-item>
81
+
82
+			<uni-forms-item label="预估绩效" class="form-item" v-if="taskName != '工作填报'">
83
+				<u-tag :text="'¥' + money" type="primary" plain></u-tag>
84
+			</uni-forms-item>
85
+			<!-- 提交按钮 -->
86
+			<button class="save-btn" @click="save">保存</button>
87
+			<button class="submit-btn margin-top-xs" type="primary" @click="submitForm">提交</button>
88
+		</uni-forms>
89
+
90
+		<uv-modal ref="popModal" title="提示" content='是否提交表单?' :showCancelButton="true" @confirm="confirmSubmit"></uv-modal>
91
+	</view>
92
+</template>
93
+
94
+<script>
95
+import ProjectPicker from '@/pages/components/ProjectPicker.vue';
96
+import ProjectInfo from '@/pages/components/ProjectInfo.vue';
97
+import { listPrice, getWorkTypeList, getWorkItemList } from '@/api/oa/price/price'
98
+import { listProject, submitProject, modifyProject, delProject } from "@/api/oa/project/project";
99
+import { listDeclare, getDeclare, addDeclare, updateDeclare } from '@/api/oa/declare/declare';
100
+import { parseTime } from "@/utils/common.js"
101
+import { complete, getNextFlowNode } from "@/api/flowable/todo";
102
+import { getUsersDeptLeader, getUsersDeptLeaderByDept, getUsersManageLeaderByDept } from "@/api/system/post.js";
103
+export default {
104
+	components: {
105
+		ProjectPicker,
106
+		ProjectInfo
107
+	},
108
+	props: {
109
+		taskForm: Object,
110
+		taskName: String, // 当前节点
111
+		startUserName: String, // 流程发起人
112
+	},
113
+	created() {
114
+		this.getProjectList();
115
+		this.initForm();
116
+		if (this.taskName != '工作填报') {
117
+			this.isScatteredOptions.map(item => item.disable = true)
118
+		}
119
+		uni.setNavigationBarTitle({
120
+			title: '工作填报'
121
+		});
122
+	},
123
+	data() {
124
+		return {
125
+			openProject: false,
126
+			selectedProject: null,
127
+			isScattered: 0,
128
+			formData: {
129
+				userId: null,
130
+				projectId: '',
131
+				workType: '',
132
+				workItem: '',
133
+				workContent: '',
134
+				workLoad: '',
135
+				price: 216,
136
+				submitTime: '',
137
+				coefficient: undefined,
138
+			},
139
+			money: '',
140
+			rules: {
141
+				projectId: {
142
+					rules: [{
143
+						required: true,
144
+						errorMessage: '请选择项目',
145
+					},]
146
+				},
147
+				workType: {
148
+					rules: [{
149
+						required: true,
150
+						errorMessage: '请选择工作类别',
151
+					},]
152
+				},
153
+				workItem: {
154
+					rules: [{
155
+						required: true,
156
+						errorMessage: '请选择工作细项',
157
+					},]
158
+				},
159
+				workContent: {
160
+					rules: [{
161
+						required: true,
162
+						errorMessage: '请输入具体内容',
163
+					},]
164
+				},
165
+				workLoad: {
166
+					rules: [{
167
+						required: true,
168
+						errorMessage: '请输入工作量',
169
+					},]
170
+				},
171
+				coefficient: {
172
+					rules: [{
173
+						required: true,
174
+						errorMessage: '请输入系数',
175
+					},]
176
+				}
177
+			},
178
+			projectObj: {},
179
+			isScatteredOptions: [{
180
+				text: '否',
181
+				value: 0,
182
+				disable: false
183
+			}, {
184
+				text: '是',
185
+				value: 1,
186
+				disable: false
187
+			}],
188
+			projects: [],
189
+			projectIndex: -1,
190
+			inputStyle: {
191
+				borderColor: '#e5e5e5',
192
+				borderRadius: '8px'
193
+			},
194
+			textareaStyle: {
195
+				borderColor: '#e5e5e5',
196
+				borderRadius: '8px',
197
+				height: '100px'
198
+			},
199
+			showType: false,
200
+			workTypeColumns: [{
201
+				text: '外业',
202
+				value: '外业',
203
+			},
204
+			{
205
+				text: '内业',
206
+				value: '内业'
207
+			}
208
+			],
209
+			workItemList: [],
210
+			hasForm: false,
211
+			show: false,
212
+		};
213
+	},
214
+	methods: {
215
+		handleConfirm(project) {
216
+			console.log('选中的项目:', project);
217
+			this.selectedProject = project;
218
+			this.projectObj = project;
219
+		},
220
+		initForm() {
221
+			if (this.taskName == '工作填报') {
222
+				this.formData.submitTime = parseTime(new Date(), "{y}-{m}-{d}");
223
+				this.formData.userId = this.$store.getters.userId;
224
+			}
225
+			getDeclare(this.taskForm.formId).then(res => {
226
+				if (res.data) {
227
+					this.hasForm = true;
228
+					this.formData = res.data;
229
+					if (res.data.projectId) {
230
+						this.isScattered = 0;
231
+					} else {
232
+						this.isScattered = 1;
233
+					}
234
+					res.data.project.projectLeader = res.data.projectLeader
235
+					this.projectObj = res.data.project;
236
+					this.selectedProject = res.data.project;
237
+					this.bindWorkTypeChange(this.formData.workType);
238
+					this.countMoney();
239
+				} else {
240
+					this.hasForm = false;
241
+				}
242
+			})
243
+		},
244
+		bindProjectChange(e) {
245
+			this.projectIndex = e.detail.value;
246
+			this.formData.project = this.projects[this.projectIndex];
247
+		},
248
+		bindWorkTypeChange(e) {
249
+			listPrice({
250
+				workType: e,
251
+				pageNum: 1,
252
+				pageSize: 9999
253
+			}).then(res => {
254
+				if (res.code == 200) {
255
+					let data = res.rows;
256
+					let list = [];
257
+					for (let d of data) {
258
+						list.push(d.workItem)
259
+					}
260
+					if (e == '内业') {
261
+						list.push('其他')
262
+					}
263
+					this.workItemList = [...new Set(list)];
264
+				}
265
+			})
266
+		},
267
+		bindWorkItemChange(e) {
268
+			this.formData.workItem = this.workItemList[e.detail.value];
269
+		},
270
+		handleRadioChange(e) {
271
+			this.formData.isScattered = e.detail.value;
272
+		},
273
+		handleProjectChange(row) {
274
+
275
+		},
276
+		getProjectList() {
277
+			listProject({
278
+				pageNum: 1,
279
+				pageSize: 10
280
+			}).then(res => {
281
+				this.projects = res.rows
282
+			})
283
+		},
284
+		countMoney() {
285
+			console.log(this.formData);
286
+			let result = Number(this.formData.price) * Number(this.formData.workLoad) * Number(this.formData.coefficient)
287
+			console.log(result);
288
+			this.money = result.toFixed(2)
289
+		},
290
+		async save() {
291
+			if (!this.isScattered) {
292
+				this.formData.projectId = this.projectObj.projectId;
293
+			} else {
294
+				this.formData.projectId = ''
295
+			}
296
+			if (this.hasForm) {
297
+				let updateRes = await updateDeclare(this.formData);
298
+			} else {
299
+				this.formData.formId = this.taskForm.formId;
300
+				let addRes = await addDeclare(this.formData);
301
+				if (addRes.code == 200) {
302
+					this.hasForm = true;
303
+				} else {
304
+					this.hasForm = false;
305
+				}
306
+			}
307
+			uni.showToast({
308
+				title: '保存成功',
309
+				icon: 'success'
310
+			});
311
+		},
312
+		submitForm() {
313
+			this.$refs.form.validate().then(res => {
314
+				console.log('表单数据信息:', res);
315
+				console.log(this.taskForm);
316
+				this.taskForm.variables.skip = false;
317
+				if (!this.projectObj.projectLeader) {
318
+					if (this.isScattered == 0) {
319
+						this.$message.error('该项目未指定项目负责人,无法提交。')
320
+						return
321
+					}
322
+				}
323
+				this.$refs.popModal.open();
324
+			}).catch(err => {
325
+				console.log('表单错误信息:', err);
326
+			})
327
+		},
328
+		confirmSubmit() {
329
+			if (this.taskName == '工作填报') {
330
+				this.declareSubmit();
331
+			} else if (this.taskName == '项目负责人审核' || this.taskName == '部门负责人审核') {
332
+				this.approveForm();
333
+			} else {
334
+				this.confirmForm();
335
+			}
336
+		},
337
+		async declareSubmit() {
338
+			if (this.isScattered == 0) {
339
+				let approval = this.projectObj.projectLeader;
340
+				this.taskForm.variables.approval = approval
341
+			} else {
342
+				let resData = await getUsersDeptLeader({ userId: this.form.userId });
343
+				if (resData.data) {
344
+					this.taskForm.variables.approval = resData.data.userId
345
+					this.taskForm.variables.skip = true;
346
+				}
347
+			}
348
+			if (this.hasForm) {
349
+				updateDeclare(this.formData);
350
+			} else {
351
+				this.formData.formId = this.taskForm.formId;
352
+				addDeclare(this.formData);
353
+			}
354
+			this.handleComplete(this.taskForm);
355
+		},
356
+		async approveForm() {
357
+			if (this.taskName == '项目负责人审核') {
358
+				this.formData.checkStatus = '1';
359
+				updateDeclare(this.formData);
360
+				let resData = await getUsersDeptLeader({ userId: this.formData.userId });
361
+				if (resData.data) {
362
+					this.taskForm.variables.approval = resData.data.userId;
363
+					this.handleComplete(this.taskForm);
364
+				}
365
+			} else if (this.taskName == '部门负责人审核') {
366
+				this.formData.checkStatus = '1';
367
+				this.formData.auditStatus = '1';
368
+				updateDeclare(this.formData);
369
+				this.taskForm.variables.approval = this.formData.userId;
370
+				this.handleComplete(this.taskForm);
371
+			}
372
+		},
373
+		confirmForm() {
374
+			this.$modal.confirm('最后一个节点,提交将结束流程,是否提交?').then(() => {
375
+				this.formData.confirmStatus = '1';
376
+				updateDeclare(this.formData);
377
+				this.handleComplete(this.taskForm);
378
+			})
379
+		},
380
+		handleComplete(taskForm) {
381
+			const params = { taskId: this.taskForm.taskId };
382
+			getNextFlowNode(params).then(() => {
383
+				complete(taskForm).then(response => {
384
+					uni.showToast({
385
+						title: response.msg,
386
+						icon: 'success'
387
+					});
388
+					setTimeout(() => {
389
+						this.$emit('goBack')
390
+					}, 500);
391
+				})
392
+			})
393
+
394
+		},
395
+	}
396
+};
397
+</script>
398
+
399
+<style lang="scss" scoped>
400
+.form-container {
401
+	padding: 20px;
402
+	background-color: #f8f8f8;
403
+}
404
+
405
+.form-title {
406
+	margin-bottom: 15px;
407
+	text-align: center;
408
+
409
+	.title-text {
410
+		font-size: 20px;
411
+		font-weight: bold;
412
+		color: #333;
413
+	}
414
+
415
+	.title-line {
416
+		width: 50px;
417
+		height: 2px;
418
+		background-color: #007AFF;
419
+		margin: 8px auto;
420
+	}
421
+}
422
+
423
+.custom-form {
424
+	background-color: #fff;
425
+	padding: 15px;
426
+	border-radius: 12px;
427
+	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
428
+}
429
+
430
+.form-item {
431
+	margin-bottom: 20px;
432
+
433
+	/deep/ .uni-forms-item__label {
434
+		font-weight: 500;
435
+		color: #666;
436
+		padding-bottom: 8px;
437
+	}
438
+}
439
+
440
+.picker {
441
+	width: 100%;
442
+	padding: 10px;
443
+	border: 1px solid #e5e5e5;
444
+	border-radius: 8px;
445
+	display: flex;
446
+	align-items: center;
447
+	justify-content: space-between;
448
+	color: #333;
449
+}
450
+
451
+.radio-label {
452
+	margin-right: 25px;
453
+	display: inline-flex;
454
+	align-items: center;
455
+}
456
+
457
+.unit {
458
+	color: #999;
459
+	padding: 0 10px;
460
+}
461
+</style>

+ 65
- 45
oa-ui-app/pages/message/apply/apply.vue 파일 보기

@@ -1,20 +1,26 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-01-21 10:01:39
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-19 15:55:13
6
+-->
1 7
 <template>
2 8
 	<view>
3
-		<view class="tag-view text-center" style="padding: 10rpx;">
9
+		<view class="tag-view text-center margin-top-xs margin-bottom-xs" style="padding: 10rpx;">
4 10
 			<uni-tag :text="'您还有' + total + '个任务待审'" />
5 11
 		</view>
6 12
 		<u-list v-if="todoList.length > 0">
7 13
 			<u-list-item v-for="(item, index) in todoList" :key="index">
8 14
 				<view @click="goToDetail(item)">
9
-					<uni-card>
15
+					<view class="box">
10 16
 						<view style="text-align: right;">
11
-							<span style="font-size: 26rpx;color: #999999;">{{item.createTime}}</span>
17
+							<span style="font-size: 26rpx;color: #999999;">{{ item.createTime }}</span>
12 18
 						</view>
13
-						<uni-title type="h3" :title="item.title ? item.title:'暂无标题'"></uni-title>
14
-						<view>流程名称:{{item.procDefName}}</view>
15
-						<view>当前节点:{{item.taskName}}</view>
16
-						<view>流程发起人:{{item.startUserName}}</view>
17
-					</uni-card>
19
+						<uni-title type="h3" :title="item.title ? item.title : '暂无标题'"></uni-title>
20
+						<view>流程名称:{{ item.procDefName }}</view>
21
+						<view>当前节点:{{ item.taskName }}</view>
22
+						<view>流程发起人:{{ item.startUserName }}</view>
23
+					</view>
18 24
 				</view>
19 25
 			</u-list-item>
20 26
 		</u-list>
@@ -23,48 +29,62 @@
23 29
 </template>
24 30
 
25 31
 <script>
26
-	import {
27
-		todoList
28
-	} from "@/api/flowable/todo";
29
-	export default {
30
-		data() {
31
-			return {
32
-				todoList: [],
33
-				total: 0,
34
-			};
32
+import {
33
+	todoList
34
+} from "@/api/flowable/todo";
35
+export default {
36
+	data() {
37
+		return {
38
+			todoList: [],
39
+			total: 0,
40
+		};
41
+	},
42
+	created() {
43
+		this.getTodoList();
44
+	},
45
+	onLoad: function (options) {
46
+		uni.startPullDownRefresh();
47
+	},
48
+	onPullDownRefresh() {
49
+		this.getTodoList();
50
+	},
51
+	methods: {
52
+		getTodoList() {
53
+			todoList({
54
+				pageNum: 1,
55
+				pageSize: 999,
56
+				name: null
57
+			}).then(response => {
58
+				this.total = response.data.total;
59
+				this.todoList = response.data.records;
60
+				uni.stopPullDownRefresh();
61
+			});
35 62
 		},
36
-		created() {
37
-			this.getTodoList();
38
-		},
39
-		onLoad: function(options) {
40
-			uni.startPullDownRefresh();
41
-		},
42
-		onPullDownRefresh() {
43
-			this.getTodoList();
44
-		},
45
-		methods: {
46
-			getTodoList() {
47
-				todoList({
48
-					pageNum: 1,
49
-					pageSize: 999,
50
-					name: null
51
-				}).then(response => {
52
-					this.total = response.data.total;
53
-					this.todoList = response.data.records;
54
-					uni.stopPullDownRefresh();
55
-				});
56
-			},
57
-			goToDetail(item) {
58
-				// 跳转到详情页,并传递项目ID
59
-				console.log(item)
60
-				uni.navigateTo({
61
-					url: `/pages/message/apply/detail?procDefName=${item.procDefName}&taskName=${item.taskName}&startUserName=${item.startUserName}&taskId=${item.taskId}`
62
-				});
63
+		goToDetail(item) {
64
+			// 跳转到详情页,并传递项目ID
65
+			const query = {
66
+				procInsId: item.procInsId,
67
+				executionId: item.executionId,
68
+				deployId: item.deployId,
69
+				taskId: item.taskId,
70
+				taskName: item.taskName,
71
+				startUserName: item.startUserName,
72
+				procDefName: item.procDefName
63 73
 			}
74
+			const encodedParams = encodeURIComponent(JSON.stringify(query));
75
+			uni.navigateTo({
76
+				url: `/pages/message/apply/detail?params=${encodedParams}`
77
+			})
64 78
 		}
65 79
 	}
80
+}
66 81
 </script>
67 82
 
68 83
 <style lang="scss">
69
-
84
+.box {
85
+	background-color: #fff;
86
+	border-radius: 4px;
87
+	padding: 10px 20px;
88
+	margin: 0 10px 10px;
89
+}
70 90
 </style>

+ 0
- 398
oa-ui-app/pages/message/apply/components/declare/declare.vue 파일 보기

@@ -1,398 +0,0 @@
1
-<template>
2
-	<view class="form-container">
3
-		<!-- 表单标题 -->
4
-		<view class="form-title">
5
-			<text class="title-text">工作填报</text>
6
-			<view class="title-line"></view>
7
-		</view>
8
-		<!-- 表单内容 -->
9
-		<uni-forms ref="form" :modelValue="formData" :rules="rules" label-position="top" label-width="150"
10
-			class="custom-form">
11
-			<!-- 当前节点 -->
12
-			<uni-forms-item label="当前节点" class="form-item">
13
-				<uni-tag :inverted="true" type="primary" :text="taskName"></uni-tag>
14
-			</uni-forms-item>
15
-
16
-			<!-- 流程发起人 -->
17
-			<uni-forms-item label="填报人" class="form-item">
18
-				<uni-tag :inverted="true" type="primary" :text="startUserName"></uni-tag>
19
-			</uni-forms-item>
20
-
21
-			<!-- 填报日期 -->
22
-			<uni-forms-item label="填报日期" class="form-item">
23
-				<text>{{formData.submitTime}}</text>
24
-			</uni-forms-item>
25
-			<!-- 是否零星项目 -->
26
-			<uni-forms-item label="是否零星项目" required class="form-item" name="isScattered">
27
-				<uni-data-checkbox v-model="isScattered" :localdata="isScatteredOptions"></uni-data-checkbox>
28
-			</uni-forms-item>
29
-
30
-			<!-- 选择项目 -->
31
-			<uni-forms-item label="选择项目" required class="form-item" v-if="!isScattered" name="projectId">
32
-				<!-- <ProjectPicker v-model="formData.projectId" placeholder="请选择项目" :labelKey="'projectName'"
33
-					:valueKey="'projectId'" @change="handleProjectChange"
34
-					:customStyle="{ borderColor: '#e5e5e5', borderRadius: '8px' }" v-if="taskName == '工作填报'" /> -->
35
-				<!-- <ProjectInfo :project="projectObj" v-else></ProjectInfo> -->
36
-				<u-button type="primary" @click="openProject = true" v-if="taskName == '工作填报'">选择项目</u-button>
37
-				<ProjectPicker :visible.sync="openProject" :selected.sync="selectedProject" @confirm="handleConfirm" />
38
-				<ProjectInfo :project="projectObj"></ProjectInfo>
39
-			</uni-forms-item>
40
-
41
-			<!-- 工作类别 -->
42
-			<uni-forms-item label="工作类别" required class="form-item" name="workType">
43
-				<uni-data-select :disabled="taskName != '工作填报'" :clear="taskName == '工作填报'" v-model="formData.workType"
44
-					:localdata="workTypeColumns" @change="bindWorkTypeChange"></uni-data-select>
45
-			</uni-forms-item>
46
-
47
-			<!-- 工作细项 -->
48
-			<uni-forms-item label="工作细项" required class="form-item" name="workItem">
49
-				<picker @change="bindWorkItemChange" :value="formData.workItem" :range="workItemList"
50
-					:disabled="taskName != '工作填报'">
51
-					<view class="uni-input">
52
-						<uni-easyinput type="text" :disabled="taskName != '工作填报'" v-model="formData.workItem"
53
-							@click="showType = true" placeholder="请选择" :styles="inputStyle" />
54
-					</view>
55
-				</picker>
56
-			</uni-forms-item>
57
-
58
-			<!-- 具体内容 -->
59
-			<uni-forms-item label="具体内容" required class="form-item" name="workContent">
60
-				<uni-easyinput :disabled="taskName != '工作填报'" type="textarea" v-model="formData.workContent"
61
-					placeholder="请输入具体工作内容" :styles="textareaStyle" />
62
-			</uni-forms-item>
63
-
64
-			<!-- 工天 -->
65
-			<uni-forms-item label="工天" required class="form-item" name="workLoad">
66
-				<uni-easyinput :disabled="taskName != '工作填报'" type="number" v-model="formData.workLoad" placeholder="请输入所需工天"
67
-					:styles="inputStyle">
68
-					<text slot="right" class="unit">天</text>
69
-				</uni-easyinput>
70
-			</uni-forms-item>
71
-
72
-			<uni-forms-item label="系数" required class="form-item" name="coefficient" v-if="taskName != '工作填报'">
73
-				<uni-easyinput type="number" v-model="formData.coefficient" placeholder="请输入系数" :styles="inputStyle"
74
-					@input="countMoney">
75
-				</uni-easyinput>
76
-			</uni-forms-item>
77
-
78
-			<uni-forms-item label="工天单价" class="form-item" v-if="taskName != '工作填报'">
79
-				<u-tag :text="formData.price+'/人天'" type="success" plain></u-tag>
80
-			</uni-forms-item>
81
-
82
-			<uni-forms-item label="预估绩效" class="form-item" v-if="taskName != '工作填报'">
83
-				<u-tag :text="'¥'+money" type="primary" plain></u-tag>
84
-			</uni-forms-item>
85
-			<!-- 提交按钮 -->
86
-			<button class="save-btn" @click="save">保存</button>
87
-			<button class="submit-btn margin-top-xs" type="primary" @click="submitForm">提交</button>
88
-		</uni-forms>
89
-	</view>
90
-</template>
91
-
92
-<script>
93
-	import ProjectPicker from '@/pages/components/ProjectPicker.vue';
94
-	import ProjectInfo from '@/pages/components/ProjectInfo.vue';
95
-	import {
96
-		listPrice,
97
-		getWorkTypeList,
98
-		getWorkItemList
99
-	} from '@/api/oa/price/price'
100
-	import {
101
-		listProject,
102
-		submitProject,
103
-		modifyProject,
104
-		delProject
105
-	} from "@/api/oa/project/project";
106
-	import {
107
-		listDeclare,
108
-		getDeclare,
109
-		addDeclare,
110
-		updateDeclare
111
-	} from '@/api/oa/declare/declare';
112
-	import {
113
-		parseTime
114
-	} from "@/utils/common.js"
115
-	export default {
116
-		components: {
117
-			ProjectPicker,
118
-			ProjectInfo
119
-		},
120
-		props: {
121
-			taskForm: Object,
122
-			taskName: String, // 当前节点
123
-			startUserName: String, // 流程发起人
124
-		},
125
-		created() {
126
-			this.getProjectList();
127
-			this.initForm();
128
-			if (this.taskName != '工作填报') {
129
-				this.isScatteredOptions.map(item => item.disable = true)
130
-			}
131
-		},
132
-		data() {
133
-			return {
134
-				openProject: false,
135
-				selectedProject: null,
136
-				isScattered: 0,
137
-				formData: {
138
-					userId: null,
139
-					projectId: '',
140
-					workType: '',
141
-					workItem: '',
142
-					workContent: '',
143
-					workLoad: '',
144
-					price: 216,
145
-					submitTime: ''
146
-				},
147
-				money: '',
148
-				rules: {
149
-					isScattered: {
150
-						rules: [{
151
-							required: true,
152
-							errorMessage: '必填项',
153
-						}, ]
154
-					},
155
-					projectId: {
156
-						rules: [{
157
-							required: true,
158
-							errorMessage: '请选择项目',
159
-						}, ]
160
-					},
161
-					workType: {
162
-						rules: [{
163
-							required: true,
164
-							errorMessage: '请选择工作类别',
165
-						}, ]
166
-					},
167
-					workItem: {
168
-						rules: [{
169
-							required: true,
170
-							errorMessage: '请选择工作细项',
171
-						}, ]
172
-					},
173
-					workContent: {
174
-						rules: [{
175
-							required: true,
176
-							errorMessage: '请输入具体内容',
177
-						}, ]
178
-					},
179
-					workLoad: {
180
-						rules: [{
181
-							required: true,
182
-							errorMessage: '请输入工作量',
183
-						}, ]
184
-					},
185
-				},
186
-				projectObj: {},
187
-				isScatteredOptions: [{
188
-					text: '否',
189
-					value: 0,
190
-					disable: false
191
-				}, {
192
-					text: '是',
193
-					value: 1,
194
-					disable: false
195
-				}],
196
-				projects: [],
197
-				projectIndex: -1,
198
-				inputStyle: {
199
-					borderColor: '#e5e5e5',
200
-					borderRadius: '8px'
201
-				},
202
-				textareaStyle: {
203
-					borderColor: '#e5e5e5',
204
-					borderRadius: '8px',
205
-					height: '100px'
206
-				},
207
-				showType: false,
208
-				workTypeColumns: [{
209
-						text: '外业',
210
-						value: '外业',
211
-					},
212
-					{
213
-						text: '内业',
214
-						value: '内业'
215
-					}
216
-				],
217
-				workItemList: [],
218
-				hasForm: false,
219
-			};
220
-		},
221
-		methods: {
222
-			handleConfirm(project) {
223
-				console.log('选中的项目:', project);
224
-				this.selectedProject = project;
225
-				this.projectObj = project;
226
-			},
227
-			initForm() {
228
-				getDeclare(this.taskForm.formId).then(res => {
229
-					if (res.data) {
230
-						this.hasForm = true;
231
-						this.formData = res.data;
232
-						console.log(res.data)
233
-						if (res.data.projectId) {
234
-							this.isScattered = 0;
235
-						} else {
236
-							this.isScattered = 1;
237
-						}
238
-						res.data.project.projectLeader = res.data.projectLeader
239
-						this.projectObj = res.data.project;
240
-						this.selectedProject = res.data.project;
241
-						this.bindWorkTypeChange(this.formData.workType);
242
-						this.countMoney();
243
-					} else {
244
-						this.hasForm = false;
245
-					}
246
-					if (this.taskName == '工作填报') {
247
-						this.formData.submitTime = parseTime(new Date(), "{y}-{m}-{d}");
248
-						this.formData.userId = this.$store.getters.userId;
249
-						console.log(this.$store.getters)
250
-					}
251
-				})
252
-			},
253
-			bindProjectChange(e) {
254
-				this.projectIndex = e.detail.value;
255
-				this.formData.project = this.projects[this.projectIndex];
256
-			},
257
-			bindWorkTypeChange(e) {
258
-				listPrice({
259
-					workType: e,
260
-					pageNum: 1,
261
-					pageSize: 9999
262
-				}).then(res => {
263
-					if (res.code == 200) {
264
-						let data = res.rows;
265
-						let list = [];
266
-						for (let d of data) {
267
-							list.push(d.workItem)
268
-						}
269
-						if (e == '内业') {
270
-							list.push('其他')
271
-						}
272
-						this.workItemList = [...new Set(list)];
273
-					}
274
-				})
275
-			},
276
-			bindWorkItemChange(e) {
277
-				this.formData.workItem = this.workItemList[e.detail.value];
278
-				console.log(this.formData.workItem);
279
-			},
280
-			handleRadioChange(e) {
281
-				this.formData.isScattered = e.detail.value;
282
-			},
283
-			handleProjectChange(row) {
284
-				console.log(row)
285
-			},
286
-			getProjectList() {
287
-				listProject({
288
-					pageNum: 1,
289
-					pageSize: 10
290
-				}).then(res => {
291
-					this.projects = res.rows
292
-				})
293
-			},
294
-			countMoney() {
295
-				let result = parseFloat(this.formData.price * this.formData.workLoad * this.formData.coefficient)
296
-				console.log(result)
297
-				this.money = result.toFixed(2)
298
-			},
299
-			async save() {
300
-				if (!this.isScattered) {
301
-					this.formData.projectId = this.projectObj.projectId;
302
-				} else {
303
-					this.formData.projectId = ''
304
-				}
305
-				if (this.hasForm) {
306
-					let updateRes = await updateDeclare(this.formData);
307
-				} else {
308
-					this.formData.formId = this.taskForm.formId;
309
-					let addRes = await addDeclare(this.formData);
310
-					if (addRes.code == 200) {
311
-						this.hasForm = true;
312
-					} else {
313
-						this.hasForm = false;
314
-					}
315
-				}
316
-				uni.showToast({
317
-					title: '保存成功',
318
-					icon: 'success'
319
-				});
320
-			},
321
-			submitForm() {
322
-				this.$refs.form.validate().then(res => {
323
-					console.log('表单数据信息:', res);
324
-					uni.showToast({
325
-						title: '提交成功',
326
-						icon: 'success'
327
-					});
328
-				}).catch(err => {
329
-					console.log('表单错误信息:', err);
330
-				})
331
-			}
332
-		}
333
-	};
334
-</script>
335
-
336
-<style lang="scss" scoped>
337
-	.form-container {
338
-		padding: 20px;
339
-		background-color: #f8f8f8;
340
-	}
341
-
342
-	.form-title {
343
-		margin-bottom: 15px;
344
-		text-align: center;
345
-
346
-		.title-text {
347
-			font-size: 20px;
348
-			font-weight: bold;
349
-			color: #333;
350
-		}
351
-
352
-		.title-line {
353
-			width: 50px;
354
-			height: 2px;
355
-			background-color: #007AFF;
356
-			margin: 8px auto;
357
-		}
358
-	}
359
-
360
-	.custom-form {
361
-		background-color: #fff;
362
-		padding: 15px;
363
-		border-radius: 12px;
364
-		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
365
-	}
366
-
367
-	.form-item {
368
-		margin-bottom: 20px;
369
-
370
-		/deep/ .uni-forms-item__label {
371
-			font-weight: 500;
372
-			color: #666;
373
-			padding-bottom: 8px;
374
-		}
375
-	}
376
-
377
-	.picker {
378
-		width: 100%;
379
-		padding: 10px;
380
-		border: 1px solid #e5e5e5;
381
-		border-radius: 8px;
382
-		display: flex;
383
-		align-items: center;
384
-		justify-content: space-between;
385
-		color: #333;
386
-	}
387
-
388
-	.radio-label {
389
-		margin-right: 25px;
390
-		display: inline-flex;
391
-		align-items: center;
392
-	}
393
-
394
-	.unit {
395
-		color: #999;
396
-		padding: 0 10px;
397
-	}
398
-</style>

+ 83
- 46
oa-ui-app/pages/message/apply/detail.vue 파일 보기

@@ -1,59 +1,96 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-02-06 09:48:52
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-20 10:24:30
6
+-->
1 7
 <template>
2 8
 	<view>
3 9
 		<!-- 动态加载表单组件 -->
4
-		<component :is="currentForm" :taskForm="taskForm" :taskName="taskName" :startUserName="startUserName" />
10
+		<component :is="currentForm" :taskForm="taskForm" :taskName="taskName" :startUserName="startUserName"
11
+			@goBack="goBack" v-if="!isEmpty" />
12
+		<component :is="'EmptyBox'" v-if="isEmpty" />
5 13
 	</view>
6 14
 </template>
7 15
 
8 16
 <script>
9
-	import {
10
-		getProcessVariables
11
-	} from "@/api/flowable/definition";
12
-	import Declare from './components/declare/declare.vue';
13
-	export default {
14
-		components: {
15
-			Declare,
16
-		},
17
-		data() {
18
-			return {
19
-				procDefName: '', // 流程名称
20
-				taskName: '', // 当前节点
21
-				startUserName: '', // 流程发起人
22
-				formId: '',
23
-				taskForm: {},
24
-				currentForm: null // 当前加载的表单组件
25
-			};
26
-		},
27
-		onLoad(options) {
28
-			// 接收传递的参数
29
-			this.procDefName = options.procDefName;
30
-			this.taskName = options.taskName;
31
-			this.startUserName = options.startUserName;
17
+import {
18
+	getProcessVariables
19
+} from "@/api/flowable/definition";
20
+import Declare from '@/pages/form/declare/declare.vue';
21
+import Borrow from "@/pages/form/borrow/borrow.vue";
22
+import EmptyBox from "../../emptyBox.vue";
23
+export default {
24
+	components: {
25
+		Declare,
26
+		EmptyBox,
27
+		Borrow,
28
+	},
29
+	data() {
30
+		return {
31
+			procDefName: '', // 流程名称
32
+			taskName: '', // 当前节点
33
+			startUserName: '', // 流程发起人
34
+			formId: '',
35
+			taskForm: {
36
+				returnTaskShow: false, // 是否展示回退表单
37
+				delegateTaskShow: false, // 是否展示回退表单
38
+				defaultTaskShow: true, // 默认处理
39
+				comment: "", // 意见内容
40
+				procInsId: "", // 流程实例编号
41
+				instanceId: "", // 流程实例编号
42
+				deployId: "",  // 流程定义编号
43
+				taskId: "",// 流程任务编号
44
+				procDefId: "",  // 流程编号
45
+				targetKey: "",
46
+				variables: {
47
+					variables: {}
48
+				},
49
+			},
50
+			currentForm: null, // 当前加载的表单组件
51
+			isEmpty: false,
52
+		};
53
+	},
54
+	onLoad(options) {
55
+		const params = JSON.parse(decodeURIComponent(options.params));
56
+		// 接收传递的参数
57
+		this.procDefName = params.procDefName;
58
+		this.taskName = params.taskName;
59
+		this.startUserName = params.startUserName;
60
+		this.taskForm.taskId = params.taskId;
61
+		this.taskForm.deployId = params.deployId;
62
+		this.taskForm.procInsId = params.procInsId;
63
+		this.taskForm.executionId = params.executionId;
64
+		this.taskForm.instanceId = params.procInsId;
65
+		getProcessVariables(params.taskId).then(res => {
66
+			this.taskForm.formId = res.data.formId;
32 67
 			// 根据流程名称加载不同的表单组件
33
-			getProcessVariables(options.taskId).then(res => {
34
-				this.taskForm = res.data;
35
-				this.loadForm();
36
-			})
37
-
38
-		},
39
-		methods: {
40
-			loadForm() {
41
-				switch (this.procDefName) {
42
-					case '工作填报':
43
-						this.currentForm = 'Declare';
44
-						break;
45
-					case '流程B':
46
-						this.currentForm = 'ProcessBForm';
47
-						break;
48
-					default:
49
-						console.log('未知流程');
50
-						break;
51
-				}
68
+			this.loadForm();
69
+		})
70
+	},
71
+	methods: {
72
+		loadForm() {
73
+			this.isEmpty = false;
74
+			switch (this.procDefName) {
75
+				case '工作填报':
76
+					this.currentForm = 'Declare';
77
+					break;
78
+				case '借款审批':
79
+					this.currentForm = 'Borrow';
80
+					break;
81
+				default:
82
+					console.log('未知流程');
83
+					this.isEmpty = true;
84
+					break;
52 85
 			}
86
+		},
87
+		goBack() {
88
+			uni.navigateTo({
89
+				url: '/pages/message/apply/apply'
90
+			})
53 91
 		}
54 92
 	}
93
+}
55 94
 </script>
56 95
 
57
-<style lang="scss">
58
-
59
-</style>
96
+<style lang="scss"></style>

+ 21
- 0
oa-ui-app/pages/message/completed/index.vue 파일 보기

@@ -0,0 +1,21 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-02-19 15:30:13
4
+ * @LastEditors: 
5
+ * @LastEditTime: 2025-02-19 15:30:40
6
+-->
7
+<template>
8
+  <view>
9
+
10
+  </view>
11
+</template>
12
+
13
+<script>
14
+  export default {
15
+    
16
+  }
17
+</script>
18
+
19
+<style lang="scss" scoped>
20
+
21
+</style>

+ 83
- 50
oa-ui-app/pages/message/index.vue 파일 보기

@@ -1,3 +1,9 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-01-21 10:01:39
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-19 15:18:10
6
+-->
1 7
 <template>
2 8
 	<view class="u-page">
3 9
 		<scroll-view class="scroll-list" scroll-y="true">
@@ -15,9 +21,36 @@
15 21
 							</view>
16 22
 						</view>
17 23
 						<view class="info">
18
-							<span style="font-size: 26rpx;color: #999999;">{{acceptTime}}</span>
19
-							<u-badge class="info-badge" type="error" count="2" :max="99"
20
-								:value="detail"></u-badge>
24
+							<span style="font-size: 26rpx;color: #999999;">{{ acceptTime }}</span>
25
+							<u-badge class="info-badge" type="error" count="2" :max="99" :value="detail"></u-badge>
26
+						</view>
27
+					</view>
28
+				</view>
29
+				<view class="uni-list-cell">
30
+					<view class="uni-media-list" @click="$tab.navigateTo('/pages/message/completed/index')">
31
+						<view style="margin-right: 20rpx;">
32
+							<u-image :fade="false" src="@/static/images/message/completed.png" width="40px" height="40px"></u-image>
33
+						</view>
34
+						<view class="uni-media-list-body">
35
+							<view class="uni-media-list-text-top"><span>已办任务</span>
36
+							</view>
37
+							<view class="uni-media-list-text-bottom">
38
+								<uni-text><span>您的已办任务,在此进行撤回或查看已办任务等操作</span></uni-text>
39
+							</view>
40
+						</view>
41
+					</view>
42
+				</view>
43
+				<view class="uni-list-cell">
44
+					<view class="uni-media-list" @click="$tab.navigateTo('/pages/message/myProcess/index')">
45
+						<view style="margin-right: 20rpx;">
46
+							<u-image :fade="false" src="@/static/images/message/flowable.png" width="40px" height="40px"></u-image>
47
+						</view>
48
+						<view class="uni-media-list-body">
49
+							<view class="uni-media-list-text-top"><span>我的流程</span>
50
+							</view>
51
+							<view class="uni-media-list-text-bottom">
52
+								<uni-text><span>您发起的流程,在此可取消流程</span></uni-text>
53
+							</view>
21 54
 						</view>
22 55
 					</view>
23 56
 				</view>
@@ -27,57 +60,57 @@
27 60
 </template>
28 61
 
29 62
 <script>
30
-	import {
31
-		todoList
32
-	} from "@/api/flowable/todo";
33
-	export default {
34
-		data() {
35
-			return {
36
-				todoList: [],
37
-				detail: 0,
38
-				acceptTime: ''
39
-			};
40
-		},
41
-		created() {
42
-			this.getTodoList();
43
-		},
44
-		onLoad() {
63
+import {
64
+	todoList
65
+} from "@/api/flowable/todo";
66
+export default {
67
+	data() {
68
+		return {
69
+			todoList: [],
70
+			detail: 0,
71
+			acceptTime: ''
72
+		};
73
+	},
74
+	created() {
75
+		this.getTodoList();
76
+	},
77
+	onLoad() {
45 78
 
46
-		},
47
-		methods: {
48
-			
49
-			getTodoList() {
50
-				todoList({
51
-					pageNum: 1,
52
-					pageSize: 999,
53
-					name: null
54
-				}).then(response => {
55
-					console.log(response)
56
-					this.detail = response.data.total;
57
-					this.todoList = response.data.records;
58
-					this.acceptTime = response.data.records[0].createTime;
59
-				});
60
-			}
61
-		},
62
-	};
79
+	},
80
+	methods: {
81
+		getTodoList() {
82
+			todoList({
83
+				pageNum: 1,
84
+				pageSize: 999,
85
+				name: null
86
+			}).then(response => {
87
+				this.detail = response.data.total;
88
+				this.todoList = response.data.records;
89
+				this.acceptTime = response.data.records[0].createTime;
90
+			});
91
+		}
92
+	},
93
+};
63 94
 </script>
64 95
 <style lang="scss">
65
-	@import '../common/uni.css';
66
-	.info{
67
-		position: relative;
68
-		.info-badge{
69
-			position: absolute;
70
-			right: 0;
71
-			top:45rpx;
72
-		}
96
+@import '../common/uni.css';
97
+
98
+.info {
99
+	position: relative;
100
+
101
+	.info-badge {
102
+		position: absolute;
103
+		right: 0;
104
+		top: 45rpx;
73 105
 	}
106
+}
74 107
 </style>
75 108
 <style>
76
-	.icon {
77
-		width: 1em;
78
-		height: 1em;
79
-		vertical-align: -0.15em;
80
-		fill: currentColor;
81
-		overflow: hidden;
82
-	}
109
+.icon {
110
+	width: 1em;
111
+	height: 1em;
112
+	vertical-align: -0.15em;
113
+	fill: currentColor;
114
+	overflow: hidden;
115
+}
83 116
 </style>

+ 15
- 0
oa-ui-app/pages/message/myProcess/index.vue 파일 보기

@@ -0,0 +1,15 @@
1
+<template>
2
+  <view>
3
+
4
+  </view>
5
+</template>
6
+
7
+<script>
8
+  export default {
9
+    
10
+  }
11
+</script>
12
+
13
+<style lang="scss" scoped>
14
+
15
+</style>

+ 199
- 89
oa-ui-app/pages/work/index.vue 파일 보기

@@ -1,7 +1,7 @@
1 1
 <template>
2 2
   <view class="work-container">
3 3
     <!-- 轮播图 -->
4
-    <uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content">
4
+    <!-- <uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content">
5 5
       <swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
6 6
         <swiper-item v-for="(item, index) in data" :key="index">
7 7
           <view class="swiper-item" @click="clickBannerItem(item)">
@@ -9,12 +9,20 @@
9 9
           </view>
10 10
         </swiper-item>
11 11
       </swiper>
12
-    </uni-swiper-dot>
12
+    </uni-swiper-dot> -->
13 13
 
14 14
     <!-- 宫格组件 -->
15
-    <uni-section title="系统管理" type="line"></uni-section>
15
+    <uni-section title="常用操作" type="line"></uni-section>
16 16
     <view class="grid-body">
17
-      <uni-grid :column="4" :showBorder="false" @change="changeGrid">
17
+      <uni-grid :column="4" :showBorder="false" @change="openSendFlow">
18
+        <uni-grid-item>
19
+          <view class="grid-item-box">
20
+            <uni-icons type="paperplane-filled" size="30" color="#2979ff"></uni-icons>
21
+            <text class="text">发起流程</text>
22
+          </view>
23
+        </uni-grid-item>
24
+      </uni-grid>
25
+      <!-- <uni-grid :column="4" :showBorder="false" @change="changeGrid">
18 26
         <uni-grid-item>
19 27
           <view class="grid-item-box">
20 28
             <uni-icons type="person-filled" size="30"></uni-icons>
@@ -69,115 +77,217 @@
69 77
             <text class="text">日志管理</text>
70 78
           </view>
71 79
         </uni-grid-item>
72
-      </uni-grid>
80
+      </uni-grid> -->
73 81
     </view>
82
+
83
+    <uv-popup ref="popup" mode="bottom">
84
+      <view class="bottom-popup">
85
+        <view v-for="item in sendFlowList">
86
+          <u-button @click="sendFlow(item)">{{ item.name }}</u-button>
87
+        </view>
88
+      </view>
89
+    </uv-popup>
74 90
   </view>
75 91
 </template>
76 92
 
77 93
 <script>
78
-  export default {
79
-    data() {
80
-      return {
81
-        current: 0,
82
-        swiperDotIndex: 0,
83
-        data: [{
84
-            image: '/static/images/banner/banner01.jpg'
85
-          },
86
-          {
87
-            image: '/static/images/banner/banner02.jpg'
88
-          },
89
-          {
90
-            image: '/static/images/banner/banner03.jpg'
91
-          }
92
-        ]
93
-      }
94
-    },
95
-    methods: {
96
-      clickBannerItem(item) {
97
-        console.info(item)
94
+import { listDefinition } from "@/api/flowable/definition";
95
+import { Snowflake } from '@/utils/snowFlake.js';
96
+import { getNextFlowNodeByStart, todoList } from "@/api/flowable/todo";
97
+import { definitionStart, flowXmlAndNode } from "@/api/flowable/definition";
98
+export default {
99
+  data() {
100
+    return {
101
+      current: 0,
102
+      swiperDotIndex: 0,
103
+      data: [{
104
+        image: '/static/images/banner/banner01.jpg'
98 105
       },
99
-      changeSwiper(e) {
100
-        this.current = e.detail.current
106
+      {
107
+        image: '/static/images/banner/banner02.jpg'
101 108
       },
102
-      changeGrid(e) {
103
-        this.$modal.showToast('模块建设中~')
109
+      {
110
+        image: '/static/images/banner/banner03.jpg'
104 111
       }
112
+      ],
113
+      flowList: ['借款审批', '用车审批', '设备审批', '工作填报'],
114
+      sendFlowList: [],
115
+      // 查询参数
116
+      queryProcessParams: {
117
+        pageNum: 1,
118
+        pageSize: 9999,
119
+        name: null,
120
+        category: null,
121
+        key: null,
122
+        tenantId: null,
123
+        deployTime: null,
124
+        derivedFrom: null,
125
+        derivedFromRoot: null,
126
+        parentDeploymentId: null,
127
+        engineVersion: null
128
+      },
129
+      definitionList: [],
130
+      processTotal: 0,
131
+      processLoading: true
105 132
     }
133
+  },
134
+  created() {
135
+    this.getDefinitionList();
136
+  },
137
+  methods: {
138
+    clickBannerItem(item) {
139
+      console.info(item)
140
+    },
141
+    changeSwiper(e) {
142
+      this.current = e.detail.current
143
+    },
144
+    changeGrid(e) {
145
+      this.$modal.showToast('模块建设中~')
146
+    },
147
+    openSendFlow() {
148
+      this.$refs.popup.open();
149
+    },
150
+    sendFlow(row) {
151
+      let formId = new Snowflake(1n, 1n, 0n).nextId().toString();
152
+      getNextFlowNodeByStart({ deploymentId: row.deploymentId, variables: { formId: formId } }).then(res => {
153
+        let data = res.data;
154
+        const variables = {};
155
+        const formData = {};
156
+        formData.disabled = true;
157
+        formData.formBtns = false;
158
+        formData.formId = formId
159
+        if (row.id) {
160
+          variables.variables = formData;
161
+          definitionStart(row.id, JSON.stringify(variables)).then(res => {
162
+            this.$modal.msgSuccess(res.msg);
163
+            let procInstanceId = res.data;
164
+            todoList({
165
+              pageNum: 1,
166
+              pageSize: 99999999, processInsId: procInstanceId
167
+            }).then(toDoRes => {
168
+              let records = toDoRes.data.records;
169
+              if (records.length == 1) {
170
+                records = records[0]
171
+              }
172
+              const query = {
173
+                procInsId: records.procInsId,
174
+                executionId: records.executionId,
175
+                deployId: records.deployId,
176
+                taskId: records.taskId,
177
+                taskName: records.taskName,
178
+                startUserName: records.startUserName + '-' + records.startDeptName,
179
+                formId: formData.formId,
180
+                procDefName: records.procDefName
181
+              }
182
+              const encodedParams = encodeURIComponent(JSON.stringify(query));
183
+              uni.navigateTo({
184
+                url: `/pages/message/apply/detail?params=${encodedParams}`
185
+              })
186
+              this.$refs.popup.close();
187
+            })
188
+          })
189
+        }
190
+      })
191
+    },
192
+    getDefinitionList() {
193
+      listDefinition(this.queryProcessParams).then(response => {
194
+        this.definitionList = response.data.records;
195
+        this.processTotal = response.data.total;
196
+        this.processLoading = false;
197
+        let list = []
198
+        for (let i of this.definitionList) {
199
+          if (this.flowList.includes(i.name)) {
200
+            list.push(i)
201
+          }
202
+        }
203
+        this.sendFlowList = list;
204
+      });
205
+    },
106 206
   }
207
+}
107 208
 </script>
108 209
 
109 210
 <style lang="scss">
110
-  /* #ifndef APP-NVUE */
111
-  page {
112
-    display: flex;
113
-    flex-direction: column;
114
-    box-sizing: border-box;
115
-    background-color: #fff;
116
-    min-height: 100%;
117
-    height: auto;
118
-  }
211
+/* #ifndef APP-NVUE */
212
+page {
213
+  display: flex;
214
+  flex-direction: column;
215
+  box-sizing: border-box;
216
+  background-color: #fff;
217
+  min-height: 100%;
218
+  height: auto;
219
+}
119 220
 
120
-  view {
121
-    font-size: 14px;
122
-    line-height: inherit;
123
-  }
221
+view {
222
+  font-size: 14px;
223
+  line-height: inherit;
224
+}
124 225
 
125
-  /* #endif */
226
+/* #endif */
126 227
 
127
-  .text {
128
-    text-align: center;
129
-    font-size: 26rpx;
130
-    margin-top: 10rpx;
131
-  }
228
+.text {
229
+  text-align: center;
230
+  font-size: 26rpx;
231
+  margin-top: 10rpx;
232
+}
132 233
 
133
-  .grid-item-box {
134
-    flex: 1;
135
-    /* #ifndef APP-NVUE */
136
-    display: flex;
137
-    /* #endif */
138
-    flex-direction: column;
139
-    align-items: center;
140
-    justify-content: center;
141
-    padding: 15px 0;
142
-  }
234
+.grid-item-box {
235
+  flex: 1;
236
+  /* #ifndef APP-NVUE */
237
+  display: flex;
238
+  /* #endif */
239
+  flex-direction: column;
240
+  align-items: center;
241
+  justify-content: center;
242
+  padding: 15px 0;
243
+}
143 244
 
144
-  .uni-margin-wrap {
145
-    width: 690rpx;
146
-    width: 100%;
147
-    ;
148
-  }
245
+.uni-margin-wrap {
246
+  width: 690rpx;
247
+  width: 100%;
248
+  ;
249
+}
149 250
 
150
-  .swiper {
151
-    height: 300rpx;
152
-  }
251
+.swiper {
252
+  height: 300rpx;
253
+}
153 254
 
154
-  .swiper-box {
155
-    height: 150px;
156
-  }
255
+.swiper-box {
256
+  height: 150px;
257
+}
157 258
 
158
-  .swiper-item {
259
+.swiper-item {
260
+  /* #ifndef APP-NVUE */
261
+  display: flex;
262
+  /* #endif */
263
+  flex-direction: column;
264
+  justify-content: center;
265
+  align-items: center;
266
+  color: #fff;
267
+  height: 300rpx;
268
+  line-height: 300rpx;
269
+}
270
+
271
+@media screen and (min-width: 500px) {
272
+  .uni-swiper-dot-box {
273
+    width: 400px;
159 274
     /* #ifndef APP-NVUE */
160
-    display: flex;
275
+    margin: 0 auto;
161 276
     /* #endif */
162
-    flex-direction: column;
163
-    justify-content: center;
164
-    align-items: center;
165
-    color: #fff;
166
-    height: 300rpx;
167
-    line-height: 300rpx;
277
+    margin-top: 8px;
168 278
   }
169 279
 
170
-  @media screen and (min-width: 500px) {
171
-    .uni-swiper-dot-box {
172
-      width: 400px;
173
-      /* #ifndef APP-NVUE */
174
-      margin: 0 auto;
175
-      /* #endif */
176
-      margin-top: 8px;
177
-    }
178
-
179
-    .image {
180
-      width: 100%;
181
-    }
280
+  .image {
281
+    width: 100%;
182 282
   }
283
+}
284
+
285
+.bottom-popup {
286
+  max-height: 50vh;
287
+  margin-bottom: 65px;
288
+  padding: 10px;
289
+  text-align: center;
290
+
291
+  .popup-item {}
292
+}
183 293
 </style>

BIN
oa-ui-app/static/images/message/completed.png 파일 보기


BIN
oa-ui-app/static/images/message/flowable.png 파일 보기


BIN
oa-ui-app/static/images/user.png 파일 보기


+ 45
- 1
oa-ui-app/static/scss/global.scss 파일 보기

@@ -113,4 +113,48 @@
113 113
 		background-color: #f9ae3d;
114 114
 		color:#fff;
115 115
 		font-size: 16px;
116
-	}
116
+	}
117
+
118
+
119
+  
120
+.form-container {
121
+	padding: 20px;
122
+	background-color: #f8f8f8;
123
+}
124
+
125
+.form-title {
126
+	margin-bottom: 15px;
127
+	text-align: center;
128
+
129
+	.title-text {
130
+		font-size: 20px;
131
+		font-weight: bold;
132
+		color: #333;
133
+	}
134
+
135
+	.title-line {
136
+		width: 50px;
137
+		height: 2px;
138
+		background-color: #007AFF;
139
+		margin: 8px auto;
140
+	}
141
+}
142
+
143
+
144
+.custom-form {
145
+	background-color: #fff;
146
+	padding: 15px;
147
+	border-radius: 12px;
148
+	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
149
+}
150
+
151
+
152
+.form-item {
153
+	margin-bottom: 20px;
154
+
155
+	/deep/ .uni-forms-item__label {
156
+		font-weight: 500;
157
+		color: #666;
158
+		padding-bottom: 8px;
159
+	}
160
+}

+ 1
- 1
oa-ui-app/store/getters.js 파일 보기

@@ -4,6 +4,6 @@ const getters = {
4 4
 	name: state => state.user.name,
5 5
 	roles: state => state.user.roles,
6 6
 	permissions: state => state.user.permissions,
7
-	userId: state => state.user.id,
7
+	userId: state => state.user.userId,
8 8
 }
9 9
 export default getters

+ 13
- 6
oa-ui-app/store/modules/user.js 파일 보기

@@ -1,3 +1,9 @@
1
+/*
2
+ * @Author: ysh
3
+ * @Date: 2025-01-16 11:17:09
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-02-19 15:06:07
6
+ */
1 7
 import config from '@/config'
2 8
 import storage from '@/utils/storage'
3 9
 import constant from '@/utils/constant'
@@ -13,7 +19,7 @@ const user = {
13 19
     avatar: storage.get(constant.avatar),
14 20
     roles: storage.get(constant.roles),
15 21
     permissions: storage.get(constant.permissions),
16
-    id: storage.get(constant.id),
22
+    userId: storage.get(constant.userId),
17 23
   },
18 24
 
19 25
   mutations: {
@@ -36,9 +42,9 @@ const user = {
36 42
       state.permissions = permissions
37 43
       storage.set(constant.permissions, permissions)
38 44
     },
39
-    SET_ID: (state, id) => {
40
-      state.id = id
41
-      storage.set(constant.id, id)
45
+    SET_USERID: (state, userId) => {
46
+      state.userId = userId
47
+      storage.set(constant.userId, userId)
42 48
     },
43 49
   },
44 50
 
@@ -65,15 +71,16 @@ const user = {
65 71
       return new Promise((resolve, reject) => {
66 72
         getInfo().then(res => {
67 73
           const user = res.user
68
-          const avatar = (user == null || user.avatar == "" || user.avatar == null) ? require("@/static/images/profile.jpg") : baseUrl + user.avatar
74
+          const avatar = (user == null || user.avatar == "" || user.avatar == null) ? require("@/static/images/user.png") : baseUrl + user.avatar
69 75
           const username = (user == null || user.nickName == "" || user.nickName == null) ? "" : user.nickName
76
+          const userId = (user == null || user.userId == "" || user.userId == null) ? "" : user.userId
70 77
           if (res.roles && res.roles.length > 0) {
71 78
             commit('SET_ROLES', res.roles)
72 79
             commit('SET_PERMISSIONS', res.permissions)
73 80
           } else {
74 81
             commit('SET_ROLES', ['ROLE_DEFAULT'])
75 82
           }
76
-					commit('SET_ID', user.userId)
83
+					commit('SET_USERID', userId)
77 84
           commit('SET_NAME', username)
78 85
           commit('SET_AVATAR', avatar)
79 86
           resolve(res)

+ 2
- 1
oa-ui-app/utils/constant.js 파일 보기

@@ -2,7 +2,8 @@ const constant = {
2 2
    avatar: 'vuex_avatar',
3 3
    name: 'vuex_name',
4 4
    roles: 'vuex_roles',
5
-   permissions: 'vuex_permissions'
5
+   permissions: 'vuex_permissions',
6
+   userId:'vuex_userId'
6 7
  }
7 8
 
8 9
  export default constant

+ 61
- 0
oa-ui-app/utils/snowFlake.js 파일 보기

@@ -0,0 +1,61 @@
1
+export var Snowflake = /** @class */ (function() {
2
+  function Snowflake(_workerId, _dataCenterId, _sequence) {
3
+      this.twepoch = 1288834974657n;
4
+      //this.twepoch = 0n;
5
+      this.workerIdBits = 5n;
6
+      this.dataCenterIdBits = 5n;
7
+      this.maxWrokerId = -1n ^ (-1n << this.workerIdBits); // 值为:31
8
+      this.maxDataCenterId = -1n ^ (-1n << this.dataCenterIdBits); // 值为:31
9
+      this.sequenceBits = 12n;
10
+      this.workerIdShift = this.sequenceBits; // 值为:12
11
+      this.dataCenterIdShift = this.sequenceBits + this.workerIdBits; // 值为:17
12
+      this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits; // 值为:22
13
+      this.sequenceMask = -1n ^ (-1n << this.sequenceBits); // 值为:4095
14
+      this.lastTimestamp = -1n;
15
+      //设置默认值,从环境变量取
16
+      this.workerId = 1n;
17
+      this.dataCenterId = 1n;
18
+      this.sequence = 0n;
19
+      if (this.workerId > this.maxWrokerId || this.workerId < 0) {
20
+          throw new Error('_workerId must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']');
21
+      }
22
+      if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
23
+          throw new Error('_dataCenterId must max than 0 and small than maxDataCenterId-[' + this.maxDataCenterId + ']');
24
+      }
25
+
26
+      this.workerId = BigInt(_workerId);
27
+      this.dataCenterId = BigInt(_dataCenterId);
28
+      this.sequence = BigInt(_sequence);
29
+  }
30
+  Snowflake.prototype.tilNextMillis = function(lastTimestamp) {
31
+      var timestamp = this.timeGen();
32
+      while (timestamp <= lastTimestamp) {
33
+          timestamp = this.timeGen();
34
+      }
35
+      return BigInt(timestamp);
36
+  };
37
+  Snowflake.prototype.timeGen = function() {
38
+      return BigInt(Date.now());
39
+  };
40
+  Snowflake.prototype.nextId = function() {
41
+      var timestamp = this.timeGen();
42
+      if (timestamp < this.lastTimestamp) {
43
+          throw new Error('Clock moved backwards. Refusing to generate id for ' +
44
+              (this.lastTimestamp - timestamp));
45
+      }
46
+      if (this.lastTimestamp === timestamp) {
47
+          this.sequence = (this.sequence + 1n) & this.sequenceMask;
48
+          if (this.sequence === 0n) {
49
+              timestamp = this.tilNextMillis(this.lastTimestamp);
50
+          }
51
+      } else {
52
+          this.sequence = 0n;
53
+      }
54
+      this.lastTimestamp = timestamp;
55
+      return ((timestamp - this.twepoch) << this.timestampLeftShift) |
56
+          (this.dataCenterId << this.dataCenterIdShift) |
57
+          (this.workerId << this.workerIdShift) |
58
+          this.sequence;
59
+  };
60
+  return Snowflake;
61
+}());

+ 11
- 5
oa-ui-app/utils/storage.js 파일 보기

@@ -1,16 +1,22 @@
1
+/*
2
+ * @Author: ysh
3
+ * @Date: 2025-01-16 11:17:24
4
+ * @LastEditors: 
5
+ * @LastEditTime: 2025-02-17 14:39:22
6
+ */
1 7
 import constant from './constant'
2 8
 
3 9
 // 存储变量名
4 10
 let storageKey = 'storage_data'
5 11
 
6 12
 // 存储节点变量名
7
-let storageNodeKeys = [constant.avatar, constant.name, constant.roles, constant.permissions]
13
+let storageNodeKeys = [constant.avatar, constant.name, constant.roles, constant.permissions, constant.userId]
8 14
 
9 15
 // 存储的数据
10 16
 let storageData = uni.getStorageSync(storageKey) || {}
11 17
 
12 18
 const storage = {
13
-  set: function(key, value) {
19
+  set: function (key, value) {
14 20
     if (storageNodeKeys.indexOf(key) != -1) {
15 21
       let tmp = uni.getStorageSync(storageKey)
16 22
       tmp = tmp ? tmp : {}
@@ -18,14 +24,14 @@ const storage = {
18 24
       uni.setStorageSync(storageKey, tmp)
19 25
     }
20 26
   },
21
-  get: function(key) {
27
+  get: function (key) {
22 28
     return storageData[key] || ""
23 29
   },
24
-  remove: function(key) {
30
+  remove: function (key) {
25 31
     delete storageData[key]
26 32
     uni.setStorageSync(storageKey, storageData)
27 33
   },
28
-  clean: function() {
34
+  clean: function () {
29 35
     uni.removeStorageSync(storageKey)
30 36
   }
31 37
 }

Loading…
취소
저장