Bladeren bron

新增职称评审流程

余思翰 2 weken geleden
bovenliggende
commit
ace234f629

+ 44
- 0
oa-ui/src/api/oa/titles/titles.js Bestand weergeven

@@ -0,0 +1,44 @@
1
+import request from '@/utils/request'
2
+
3
+// 查询职称评审列表
4
+export function listEval(query) {
5
+  return request({
6
+    url: '/oa/titleEval/list',
7
+    method: 'get',
8
+    params: query
9
+  })
10
+}
11
+
12
+// 查询职称评审详细
13
+export function getEval(titleEvalId) {
14
+  return request({
15
+    url: '/oa/titleEval/' + titleEvalId,
16
+    method: 'get'
17
+  })
18
+}
19
+
20
+// 新增职称评审
21
+export function addEval(data) {
22
+  return request({
23
+    url: '/oa/titleEval',
24
+    method: 'post',
25
+    data: data
26
+  })
27
+}
28
+
29
+// 修改职称评审
30
+export function updateEval(data) {
31
+  return request({
32
+    url: '/oa/titleEval',
33
+    method: 'put',
34
+    data: data
35
+  })
36
+}
37
+
38
+// 删除职称评审
39
+export function delEval(titleEvalId) {
40
+  return request({
41
+    url: '/oa/titleEval/' + titleEvalId,
42
+    method: 'delete'
43
+  })
44
+}

+ 7
- 1
oa-ui/src/utils/deleteResource.js Bestand weergeven

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2024-06-13 17:07:59
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-06-09 09:32:10
5
+ * @LastEditTime: 2025-08-19 09:30:31
6 6
  */
7 7
 import request from '@/utils/request'
8 8
 
@@ -150,6 +150,12 @@ const apiEndpoints = [
150 150
       '/oa/check/:id',
151 151
     ]
152 152
   },
153
+  {
154
+    procDefName: '职称评审',
155
+    apiUrl: [
156
+      '/oa/titleEval/:id',
157
+    ]
158
+  },
153 159
 ]
154 160
 
155 161
 // 编写一个方法来处理删除请求,并同时发送所有API请求  

+ 6
- 2
oa-ui/src/views/flowable/form/components/conditionDisplay.vue Bestand weergeven

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2024-04-23 17:08:16
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-27 16:07:26
5
+ * @LastEditTime: 2025-08-18 14:10:52
6 6
 -->
7 7
 <template>
8 8
   <div>
@@ -61,6 +61,8 @@
61 61
       v-else-if="taskForm.procDefName == '参培审核'"></study-form>
62 62
     <budget-adjust :key="'budgetAdjust' + taskForm.taskId" :taskForm="taskForm" :taskName="''" :isFlow="true"
63 63
       v-else-if="taskForm.procDefName == '项目核算'"></budget-adjust>
64
+    <titles-form :key="'titles' + taskForm.taskId" :taskForm="taskForm" :taskName="''" :isFlow="true"
65
+      v-else-if="taskForm.procDefName == '职称评审'"></titles-form>
64 66
   </div>
65 67
 </template>
66 68
 
@@ -95,6 +97,7 @@ import outsourceForm from '@/views/flowable/form/outsource/outsourceForm.vue';
95 97
 import performanceForm from '@/views/flowable/form/performance/performanceForm.vue';
96 98
 import StudyForm from "@/views/flowable/form//oa/studyForm.vue";
97 99
 import BudgetAdjust from '@/views/flowable/form/budget/adjust/budgetAdjust.vue';
100
+import TitlesForm from '@/views/flowable/form/oa/titlesForm.vue';
98 101
 export default {
99 102
   props: {
100 103
     passingParam: {
@@ -135,7 +138,8 @@ export default {
135 138
     outsourceForm,
136 139
     performanceForm,
137 140
     StudyForm,
138
-    BudgetAdjust
141
+    BudgetAdjust,
142
+    TitlesForm
139 143
   },
140 144
   data() {
141 145
     return {

+ 4
- 0
oa-ui/src/views/flowable/form/components/detailDisplay.vue Bestand weergeven

@@ -56,6 +56,8 @@
56 56
       @goBack="goBack"></study-form>
57 57
     <adjust-index :taskName="taskName" :taskForm="taskForm" v-else-if="taskForm.procDefName == '项目核算'"
58 58
       @goBack="goBack"></adjust-index>
59
+    <titles-form :taskName="taskName" :taskForm="taskForm" v-else-if="taskForm.procDefName == '职称评审'"
60
+      @goBack="goBack"></titles-form>
59 61
   </div>
60 62
 </template>
61 63
 
@@ -90,6 +92,7 @@ import outsourceForm from '@/views/flowable/form/outsource/outsourceForm.vue';
90 92
 import PerformanceForm from '@/views/flowable/form/performance/performanceForm.vue';
91 93
 import StudyForm from "@/views/flowable/form/oa/studyForm.vue";
92 94
 import AdjustIndex from '@/views/flowable/form/budget/adjust/adjustIndex.vue';
95
+import TitlesForm from '@/views/flowable/form/oa/titlesForm.vue';
93 96
 export default {
94 97
   components: {
95 98
     ScTable,
@@ -122,6 +125,7 @@ export default {
122 125
     PerformanceForm,
123 126
     StudyForm,
124 127
     AdjustIndex,
128
+    TitlesForm
125 129
   },
126 130
   props: {
127 131
     taskForm: {

+ 0
- 1
oa-ui/src/views/flowable/form/oa/studyForm.vue Bestand weergeven

@@ -194,7 +194,6 @@ export default {
194 194
   methods: {
195 195
     initForm() {
196 196
       getTrainApproval(this.taskForm.formId).then(res => {
197
-        console.log(res.data)
198 197
         if (res.data) {
199 198
           this.formTotal = 1;
200 199
           this.form = res.data;

+ 596
- 0
oa-ui/src/views/flowable/form/oa/titlesForm.vue Bestand weergeven

@@ -0,0 +1,596 @@
1
+<!--
2
+ * @Author: ysh
3
+ * @Date: 2025-08-18 10:59:25
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-08-19 16:33:56
6
+-->
7
+<template>
8
+  <div>
9
+    <el-row :gutter="20">
10
+      <el-col :span="isFlow ? 18 : 24" :xs="24">
11
+        <h2 style="text-align: center;">职称申请表</h2>
12
+
13
+        <!-- 流程步骤指示器 -->
14
+        <div class="process-steps" v-if="isFlow && taskName">
15
+          <el-steps :active="getCurrentStepIndex()" finish-status="success" align-center>
16
+            <el-step title="评审申请" description="填写基本信息并上传材料"></el-step>
17
+            <el-step title="初步审核" description="审核申请材料并填写意见"></el-step>
18
+            <el-step title="盖章上传" description="上传盖章后的评审表"></el-step>
19
+            <el-step title="确认信息" description="最终确认并完成流程"></el-step>
20
+          </el-steps>
21
+        </div>
22
+
23
+        <div class="mt20 mb20" v-if="showAlter">
24
+          <el-alert title="任务被退回,请修改后重新提交" type="error" :closable="false">
25
+            <return-comment :taskForm="taskForm" @isReturn="isReturn"></return-comment>
26
+          </el-alert>
27
+        </div>
28
+
29
+        <!-- 当前步骤提示 -->
30
+        <div class="current-step-info" v-if="isFlow && taskName">
31
+          <el-card shadow="never" :body-style="{ padding: '15px' }">
32
+            <div class="step-header">
33
+              <i class="el-icon-info"></i>
34
+              <span class="step-title">当前步骤:{{ taskName }}</span>
35
+            </div>
36
+            <div class="step-description">{{ getStepDescription() }}</div>
37
+          </el-card>
38
+        </div>
39
+
40
+        <el-form :model="form" :rules="formRules" ref="form" label-width="135px" :disabled="taskName == ''"
41
+          class="mt20">
42
+          <!-- 基本信息区域 -->
43
+          <div class="form-section" v-if="showBasicInfo()">
44
+            <div class="section-title">
45
+              <i class="el-icon-user"></i>
46
+              <span>基本信息</span>
47
+            </div>
48
+
49
+            <!-- 申请人 -->
50
+            <el-form-item label="申请人" prop="userId">
51
+              <span class="auditor">{{ getUserName(form.userId) }}</span>
52
+            </el-form-item>
53
+
54
+            <!-- 申请时间 -->
55
+            <el-form-item label="申请时间" prop="userId">
56
+              {{ form.applyTime }}
57
+            </el-form-item>
58
+
59
+            <!-- 评审年度 -->
60
+            <el-form-item label="评审年度" prop="annual">
61
+              {{ form.annual }}
62
+            </el-form-item>
63
+
64
+            <!-- 评审单位 -->
65
+            <el-form-item label="评审单位" prop="institude">
66
+              <el-select v-model="form.institude" placeholder="请选择评审单位" style="width: 100%"
67
+                :disabled="taskName == '' || taskName != '评审申请'">
68
+                <el-option label="中国电建" value="中国电建" />
69
+                <el-option label="成都人社" value="成都人社" />
70
+                <el-option label="四川省测绘局" value="四川省测绘局" />
71
+                <el-option label="四川省建设厅" value="四川省建设厅" />
72
+                <el-option label="其他" value="其他" />
73
+              </el-select>
74
+            </el-form-item>
75
+
76
+            <!-- 职称类型 -->
77
+            <el-form-item label="职称类型" prop="type">
78
+              <el-select v-model="form.type" placeholder="请选择职称类型" style="width: 100%"
79
+                :disabled="taskName == '' || taskName != '评审申请'">
80
+                <el-option label="工程技术类" value="工程技术类" />
81
+                <el-option label="工程经济类" value="工程经济类" />
82
+                <el-option label="其他" value="其他" />
83
+              </el-select>
84
+            </el-form-item>
85
+
86
+            <!-- 职称级别 -->
87
+            <el-form-item label="职称级别" prop="level">
88
+              <el-select v-model="form.level" placeholder="请选择职称级别" style="width: 100%"
89
+                :disabled="taskName == '' || taskName != '评审申请'">
90
+                <el-option label="员级" value="员级" />
91
+                <el-option label="助理级" value="助理级" />
92
+                <el-option label="中级" value="中级" />
93
+                <el-option label="副高级" value="副高级" />
94
+                <el-option label="正高级" value="正高级" />
95
+              </el-select>
96
+            </el-form-item>
97
+
98
+            <!-- 职称专业名称 -->
99
+            <el-form-item label="职称专业名称" prop="titleProfession">
100
+              <el-input v-model="form.titleProfession" placeholder="请输入职称专业名称" maxlength="50" show-word-limit
101
+                :disabled="taskName == '' || taskName != '评审申请'" />
102
+            </el-form-item>
103
+          </div>
104
+
105
+          <!-- 申请材料区域 -->
106
+          <div class="form-section" v-if="showApplicationMaterials()">
107
+            <div class="section-title">
108
+              <i class="el-icon-document"></i>
109
+              <span>申请材料</span>
110
+            </div>
111
+
112
+            <!-- 盖章前评审表 -->
113
+            <el-form-item label="评审表(盖章前)" prop="sheet">
114
+              <FileUpload v-if="taskName == '评审申请' && !form.sheet" :disabled="taskName == '' || taskName != '评审申请'"
115
+                ref="sheetFile" :limit="1" :filePathName="'职称评审/盖章前评审表'" :fileType="['pdf']" @input="getSheetPath">
116
+              </FileUpload>
117
+              <div v-if="form.sheet">
118
+                <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + form.sheet}`)">
119
+                  {{ getFileName(form.sheet) }}
120
+                </el-link>
121
+                <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + form.sheet}`"
122
+                  :underline="false" target="_blank">
123
+                  <span class="el-icon-download">下载文件</span>
124
+                </el-link>
125
+                <span class="el-icon-delete del-file" @click="deleteDoc('sheet')"
126
+                  v-if="taskName == '评审申请' && taskName != ''">删除文件</span>
127
+              </div>
128
+            </el-form-item>
129
+
130
+            <!-- 其他材料 -->
131
+            <el-form-item label="其他材料" prop="material">
132
+              <FileUpload v-if="taskName == '评审申请' && !form.material" :disabled="taskName == '' || taskName != '评审申请'"
133
+                ref="materialFile" :limit="1" :filePathName="'职称评审/其他材料'" :fileType="['rar', 'zip']"
134
+                @input="getMaterialPath">
135
+              </FileUpload>
136
+              <div v-if="form.material">
137
+                <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + form.material}`)">
138
+                  {{ getFileName(form.material) }}
139
+                </el-link>
140
+                <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + form.material}`"
141
+                  :underline="false" target="_blank">
142
+                  <span class="el-icon-download">下载文件</span>
143
+                </el-link>
144
+                <span class="el-icon-delete del-file" @click="deleteDoc('material')"
145
+                  v-if="taskName == '评审申请' && taskName != ''">删除文件</span>
146
+              </div>
147
+            </el-form-item>
148
+          </div>
149
+
150
+          <!-- 审核意见区域 -->
151
+          <div class="form-section" v-if="showReviewOpinion()">
152
+            <div class="section-title">
153
+              <i class="el-icon-edit-outline"></i>
154
+              <span>审核意见</span>
155
+            </div>
156
+
157
+            <!-- 职称评审意见 -->
158
+            <el-form-item label="职称评审意见" prop="titleComment" v-if="taskName != '评审申请'">
159
+              <el-input v-model="form.titleComment" type="textarea" :rows="3" placeholder="请输入职称评审意见" maxlength="200"
160
+                show-word-limit :disabled="taskName == '' || taskName != '初步审核'" />
161
+              <div class="sign mt10" v-if="form.titleUserId">
162
+                <div class="mr20">签名:<span class="auditor">{{ getUserName(form.titleUserId) }}</span>
163
+                </div>
164
+                <div class="ml20"><span>审核时间:{{ form.titleTime }}</span></div>
165
+              </div>
166
+            </el-form-item>
167
+          </div>
168
+
169
+          <!-- 盖章材料区域 -->
170
+          <div class="form-section" v-if="showStampMaterials()">
171
+            <div class="section-title">
172
+              <!-- <i class="el-icon-edit"></i> -->
173
+              <svg-icon icon-class="skill" />
174
+              <span>盖章材料</span>
175
+            </div>
176
+
177
+            <!-- 盖章后评审表 -->
178
+            <el-form-item label="评审表(盖章后)" prop="sheetStamp">
179
+              <FileUpload v-if="taskName == '盖章上传' && !form.sheetStamp" :disabled="taskName == '' || taskName != '盖章上传'"
180
+                ref="sheetStampFile" :limit="1" :filePathName="'职称评审/盖章后评审表'" :fileType="['pdf']"
181
+                @input="getSheetStampPath">
182
+              </FileUpload>
183
+              <div v-if="form.sheetStamp">
184
+                <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + form.sheetStamp}`)">
185
+                  {{ getFileName(form.sheetStamp) }}
186
+                </el-link>
187
+                <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + form.sheetStamp}`"
188
+                  :underline="false" target="_blank">
189
+                  <span class="el-icon-download">下载文件</span>
190
+                </el-link>
191
+                <span class="el-icon-delete del-file" @click="deleteDoc('sheetStamp')"
192
+                  v-if="taskName == '盖章上传' && taskName != ''">删除文件</span>
193
+              </div>
194
+            </el-form-item>
195
+          </div>
196
+        </el-form>
197
+
198
+        <!-- 操作按钮 -->
199
+        <div style="text-align: center;" v-if="taskName" class="mt30">
200
+          <el-button type="warning" @click="saveDraft">保存</el-button>
201
+          <el-button type="danger" @click="returnOpen = true" v-if="taskName != '评审申请' && taskName != '盖章上传'">退
202
+            回</el-button>
203
+          <el-button type="primary" @click="submitForm">{{ taskName == '盖章上传' || taskName == '评审申请' ? '提交申请' :
204
+            '确认审核' }}</el-button>
205
+        </div>
206
+      </el-col>
207
+      <el-col :span="6" :xs="24" v-if="isFlow">
208
+        <el-card>
209
+          <h2 style="text-align: center;">流程进度</h2>
210
+          <div>
211
+            <flow :flowData="flowData" />
212
+          </div>
213
+        </el-card>
214
+      </el-col>
215
+    </el-row>
216
+
217
+    <el-dialog title="退回" :visible.sync="returnOpen" width="40%" append-to-body>
218
+      <return-btn :taskForm="taskForm" :comment="commentByRole()" @goBack="$emit('goBack')" @saves=""
219
+        @cancel="returnOpen = false"></return-btn>
220
+    </el-dialog>
221
+  </div>
222
+</template>
223
+
224
+<script>
225
+import flow from '@/views/flowable/task/todo/detail/flow'
226
+import { flowXmlAndNode } from "@/api/flowable/definition";
227
+import { listEval, getEval, delEval, addEval, updateEval } from "@/api/oa/titles/titles";
228
+import { complete, getNextFlowNode } from "@/api/flowable/todo";
229
+import { allocatedUserList } from "@/api/system/role";
230
+import ReturnComment from "@/views/flowable/form/components/flowBtn/returnComment.vue";
231
+import ReturnBtn from "@/views/flowable/form/components/flowBtn/returnBtn.vue";
232
+export default {
233
+  components: {
234
+    flow,
235
+    ReturnComment,
236
+    ReturnBtn,
237
+  },
238
+  props: {
239
+    taskName: {
240
+      type: String,
241
+      required: true
242
+    },
243
+    taskForm: {
244
+      type: Object,
245
+      required: true
246
+    },
247
+    isFlow: {
248
+      type: Boolean,
249
+      default: true
250
+    }
251
+  },
252
+  created() {
253
+    if (this.isFlow)
254
+      flowXmlAndNode({ procInsId: this.taskForm.procInsId, deployId: this.taskForm.deployId }).then(res => {
255
+        this.flowData = res.data;
256
+      })
257
+    // 初始化表单数据
258
+    this.initFormData()
259
+  },
260
+  data() {
261
+    return {
262
+      baseUrl: process.env.VUE_APP_BASE_API,
263
+      flowData: {},
264
+      isEdit: false,
265
+      form: {
266
+        userId: '',
267
+        annual: '',
268
+        institude: '',
269
+        type: '',
270
+        level: '',
271
+        titleProfession: '',
272
+        sheet: '',
273
+        material: ''
274
+      },
275
+      rules: {},
276
+      returnOpen: false,
277
+      showAlter: true
278
+    }
279
+  },
280
+  computed: {
281
+    // 动态生成验证规则
282
+    formRules() {
283
+      if (this.taskName == '') {
284
+        return {}; // 当taskName为空时,不进行验证
285
+      }
286
+
287
+      return {
288
+        institude: [
289
+          { required: true, message: '请选择评审单位', trigger: 'change' }
290
+        ],
291
+        type: [
292
+          { required: true, message: '请选择职称类型', trigger: 'change' }
293
+        ],
294
+        level: [
295
+          { required: true, message: '请选择职称级别', trigger: 'change' }
296
+        ],
297
+        titleProfession: [
298
+          { required: true, message: '请输入职称专业名称', trigger: 'blur' },
299
+          { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
300
+        ],
301
+        sheet: [
302
+          { required: true, message: '请上传盖章前评审表', trigger: 'change' }
303
+        ],
304
+        material: [
305
+          { required: true, message: '请上传其他材料', trigger: 'change' }
306
+        ],
307
+        titleComment: [
308
+          { required: this.taskName == '初步审核', message: '请输入职称评审意见', trigger: 'blur' },
309
+          { min: 2, max: 200, message: '长度在 2 到 200 个字符', trigger: 'blur' }
310
+        ],
311
+        sheetStamp: [
312
+          { required: this.taskName == '盖章上传', message: '请上传盖章后评审表', trigger: 'change' },
313
+        ]
314
+      };
315
+    }
316
+  },
317
+  methods: {
318
+    // 获取当前步骤索引
319
+    getCurrentStepIndex() {
320
+      const stepMap = {
321
+        '评审申请': 0,
322
+        '初步审核': 1,
323
+        '盖章上传': 2,
324
+        '确认信息': 3
325
+      };
326
+      return stepMap[this.taskName] || 0;
327
+    },
328
+
329
+    // 获取步骤描述
330
+    getStepDescription() {
331
+      const descriptions = {
332
+        '评审申请': '请填写基本信息并上传相关材料文件',
333
+        '初步审核': '请审核申请材料并填写评审意见',
334
+        '盖章上传': '请上传盖章后的评审表文件',
335
+        '确认信息': '请确认所有信息无误后完成流程'
336
+      };
337
+      return descriptions[this.taskName] || '';
338
+    },
339
+
340
+    // 显示基本信息区域
341
+    showBasicInfo() {
342
+      return true; // 所有步骤都显示基本信息
343
+    },
344
+
345
+    // 显示申请材料区域
346
+    showApplicationMaterials() {
347
+      return this.taskName == '' || ['评审申请', '初步审核', '盖章上传', '确认信息'].includes(this.taskName);
348
+    },
349
+
350
+    // 显示审核意见区域
351
+    showReviewOpinion() {
352
+      return this.taskName == '' || ['初步审核', '盖章上传', '确认信息'].includes(this.taskName);
353
+    },
354
+
355
+    // 显示盖章材料区域
356
+    showStampMaterials() {
357
+      return this.taskName == '' || ['盖章上传', '确认信息'].includes(this.taskName);
358
+    },
359
+
360
+    // 初始化表单数据
361
+    initFormData() {
362
+      getEval(this.taskForm.formId).then(res => {
363
+        if (res.data) {
364
+          this.form = res.data;
365
+          this.isEdit = true;
366
+        } else {
367
+          this.form = {
368
+            userId: this.$store.state.user.id,
369
+            annual: new Date().getFullYear().toString(),
370
+            applyTime: this.parseTime(new Date(), '{y}-{m}-{d}'),
371
+            institude: '',
372
+            type: '',
373
+            level: '',
374
+          }
375
+        }
376
+      })
377
+    },
378
+    // 保存
379
+    async saveDraft() {
380
+      if (this.taskName == '') {
381
+        this.$message.info('当前为只读模式,无法保存')
382
+        return;
383
+      }
384
+
385
+      if (this.taskName == '初步审核') {
386
+        this.form.titleUserId = this.$store.state.user.id;
387
+        this.form.titleTime = this.parseTime(new Date(), '{y}-{m}-{d}');
388
+      } else if (this.taskName == '盖章上传') {
389
+        this.form.materialUploadTime = this.parseTime(new Date(), '{y}-{m}-{d}');
390
+      } else if (this.taskName == '确认信息') {
391
+        this.form.confirmer = this.$store.state.user.id;
392
+        this.form.confirmStatus = '1';
393
+        this.form.confirmTime = this.parseTime(new Date(), '{y}-{m}-{d}');
394
+      }
395
+      if (this.isEdit) {
396
+        await updateEval(this.form);
397
+      } else {
398
+        this.form.titleEvalId = this.taskForm.formId;
399
+        await addEval(this.form);
400
+        this.isEdit = true;
401
+      }
402
+      this.$message.success('保存成功')
403
+    },
404
+    // 提交表单
405
+    submitForm() {
406
+      if (this.taskName == '') {
407
+        this.$message.info('当前为只读模式,无法提交')
408
+        return;
409
+      }
410
+
411
+      this.$refs.form.validate((valid) => {
412
+        if (valid) {
413
+          let msg = '确认提交职称申请表?';
414
+          if (this.taskName == '确认信息') {
415
+            msg = '最后一个节点,提交将无法修改,是否确认提交?';
416
+          }
417
+          this.$confirm(msg, '提示', {
418
+            confirmButtonText: '确定',
419
+            cancelButtonText: '取消',
420
+            type: 'warning'
421
+          }).then(() => {
422
+            this.submitFlow()
423
+          }).catch(() => {
424
+            this.$message.info('已取消提交')
425
+          })
426
+        } else {
427
+          this.$message.error('请完善表单信息')
428
+          return false
429
+        }
430
+      })
431
+    },
432
+    async submitFlow() {
433
+      await this.saveDraft();
434
+      if (this.taskName == '评审申请') {
435
+        let allocatedRes = await allocatedUserList({ roleId: 19 });
436
+        let titleUserId = allocatedRes.rows[0].userId;
437
+        this.$set(this.taskForm.variables, "approval", titleUserId);
438
+      } else if (this.taskName == '初步审核') {
439
+        this.$set(this.taskForm.variables, "approval", this.form.userId);
440
+      } else if (this.taskName == '盖章上传') {
441
+        this.$set(this.taskForm.variables, "approval", this.form.titleUserId);
442
+      }
443
+      getNextFlowNode({ taskId: this.taskForm.taskId }).then(() => {
444
+        complete(this.taskForm).then(response => {
445
+          this.$modal.msgSuccess(response.msg);
446
+          this.$emit('goBack');
447
+        })
448
+      })
449
+    },
450
+    getSheetPath(path) {
451
+      let arr = path.split('/upload')
452
+      this.form.sheet = arr[1]
453
+      if (path == "") {
454
+        this.form.sheet = ""
455
+      }
456
+    },
457
+    getMaterialPath(path) {
458
+      let arr = path.split('/upload')
459
+      this.form.material = arr[1]
460
+      if (path == "") {
461
+        this.form.material = ""
462
+      }
463
+    },
464
+    getSheetStampPath(path) {
465
+      let arr = path.split('/upload')
466
+      this.form.sheetStamp = arr[1]
467
+      if (path == "") {
468
+        this.form.sheetStamp = ""
469
+      }
470
+    },
471
+    getFileName(name) {
472
+      if (name) {
473
+        let arr = name.split('/')
474
+        return arr[arr.length - 1];
475
+      }
476
+    },
477
+    deleteDoc(key) {
478
+      this.$set(this.form, key, undefined)
479
+    },
480
+    isReturn(val) {
481
+      this.showAlter = val;
482
+    },
483
+    commentByRole() {
484
+      if (this.taskName == "初步审核") {
485
+        return this.form.titleComment;
486
+      }
487
+    },
488
+  }
489
+}
490
+</script>
491
+
492
+<style lang="scss" scoped>
493
+@import "@/assets/styles/element-reset.scss";
494
+
495
+.process-steps {
496
+  margin: 20px 0;
497
+  padding: 20px;
498
+  background: #f8f9fa;
499
+  border-radius: 8px;
500
+}
501
+
502
+.current-step-info {
503
+  margin: 20px 0;
504
+
505
+  .step-header {
506
+    display: flex;
507
+    align-items: center;
508
+    margin-bottom: 8px;
509
+
510
+    i {
511
+      color: #409eff;
512
+      margin-right: 8px;
513
+      font-size: 16px;
514
+    }
515
+
516
+    .step-title {
517
+      font-weight: bold;
518
+      color: #303133;
519
+      font-size: 16px;
520
+    }
521
+  }
522
+
523
+  .step-description {
524
+    color: #606266;
525
+    font-size: 14px;
526
+    line-height: 1.5;
527
+  }
528
+}
529
+
530
+.form-section {
531
+  margin-bottom: 30px;
532
+  padding: 20px;
533
+  border: 1px solid #e4e7ed;
534
+  border-radius: 8px;
535
+  background: #fff;
536
+
537
+  .section-title {
538
+    display: flex;
539
+    align-items: center;
540
+    margin-bottom: 20px;
541
+    padding-bottom: 10px;
542
+    border-bottom: 2px solid #409eff;
543
+
544
+    i {
545
+      color: #409eff;
546
+      margin-right: 8px;
547
+      font-size: 18px;
548
+    }
549
+
550
+    svg {
551
+      color: #409eff;
552
+      margin-right: 8px;
553
+      font-size: 18px;
554
+    }
555
+
556
+    span {
557
+      font-size: 16px;
558
+      font-weight: bold;
559
+      color: #303133;
560
+    }
561
+  }
562
+}
563
+
564
+.sign {
565
+  display: flex;
566
+  justify-content: flex-end;
567
+  align-items: center;
568
+  padding-right: 80px;
569
+  line-height: 30px;
570
+  /* 如果需要垂直居中 */
571
+}
572
+
573
+.mt20 {
574
+  margin-top: 20px;
575
+}
576
+
577
+.mt30 {
578
+  margin-top: 30px;
579
+}
580
+
581
+.mb20 {
582
+  margin-bottom: 20px;
583
+}
584
+
585
+.ml20 {
586
+  margin-left: 20px;
587
+}
588
+
589
+.mr20 {
590
+  margin-right: 20px;
591
+}
592
+
593
+.mt10 {
594
+  margin-top: 10px;
595
+}
596
+</style>

+ 21
- 0
oa-ui/src/views/oa/titles/info.vue Bestand weergeven

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

+ 355
- 0
oa-ui/src/views/oa/titles/record.vue Bestand weergeven

@@ -0,0 +1,355 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
4
+      <el-form-item label="职称类型" prop="type">
5
+        <el-select v-model="queryParams.type" clearable placeholder="请选择职称类型" @change="handleQuery">
6
+          <el-option label="工程技术类" value="工程技术类"></el-option>
7
+          <el-option label="工程经济类" value="工程经济类"></el-option>
8
+          <el-option label="其他" value="其他"></el-option>
9
+        </el-select>
10
+      </el-form-item>
11
+      <el-form-item label="职称级别" prop="level">
12
+        <el-select v-model="queryParams.level" clearable placeholder="请选择职称级别" @change="handleQuery">
13
+          <el-option label="正高级" value="正高级"></el-option>
14
+          <el-option label="副高级" value="副高级"></el-option>
15
+          <el-option label="高级" value="高级"></el-option>
16
+          <el-option label="中级" value="中级"></el-option>
17
+          <el-option label="初级" value="初级"></el-option>
18
+          <el-option label="员级" value="员级"></el-option>
19
+        </el-select>
20
+      </el-form-item>
21
+      <el-form-item label="申请人" prop="userId">
22
+        <el-select v-model="queryParams.userId" filterable clearable @change="handleQuery">
23
+          <el-option v-for="item in $store.state.user.userList" :key="item.userId" :label="item.nickName"
24
+            :value="item.userId">
25
+          </el-option>
26
+        </el-select>
27
+      </el-form-item>
28
+      <el-form-item>
29
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
30
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
31
+      </el-form-item>
32
+    </el-form>
33
+
34
+    <el-row :gutter="10" class="mb8">
35
+      <el-col :span="1.5">
36
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
37
+          v-hasPermi="['oa:eval:add']">新增</el-button>
38
+      </el-col>
39
+      <el-col :span="1.5">
40
+        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
41
+          v-hasPermi="['oa:eval:edit']">修改</el-button>
42
+      </el-col>
43
+      <el-col :span="1.5">
44
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
45
+          v-hasPermi="['oa:eval:remove']">删除</el-button>
46
+      </el-col>
47
+      <el-col :span="1.5">
48
+        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
49
+          v-hasPermi="['oa:eval:export']">导出</el-button>
50
+      </el-col>
51
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
52
+    </el-row>
53
+
54
+    <el-table v-loading="loading" :data="evalList" @selection-change="handleSelectionChange">
55
+      <el-table-column type="selection" width="55" align="center" />
56
+      <el-table-column label="申请人" align="center" prop="userId">
57
+        <template slot-scope="scope">
58
+          {{ getUserName(scope.row.userId) }}
59
+        </template>
60
+      </el-table-column>
61
+      <el-table-column label="申请时间" align="center" prop="applyTime" width="150">
62
+        <template slot-scope="scope">
63
+          <span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
64
+        </template>
65
+      </el-table-column>
66
+      <el-table-column label="评审年度" align="center" prop="annual" />
67
+      <el-table-column label="评审单位" align="center" prop="institude" />
68
+      <el-table-column label="职称类型" align="center" prop="type" />
69
+      <el-table-column label="职称级别" align="center" prop="level" />
70
+      <el-table-column label="职称专业名称" align="center" prop="titleProfession" />
71
+      <el-table-column label="审核意见" align="center" prop="titleComment" />
72
+      <el-table-column label="审核时间" align="center" prop="titleTime" width="180">
73
+        <template slot-scope="scope">
74
+          <span>{{ parseTime(scope.row.titleTime, '{y}-{m}-{d}') }}</span>
75
+        </template>
76
+      </el-table-column>
77
+      <el-table-column label="职称管理员" align="center" prop="titleUserId">
78
+        <template slot-scope="scope">
79
+          {{ getUserName(scope.row.titleUserId) }}
80
+        </template>
81
+      </el-table-column>
82
+      <el-table-column label="确认时间" align="center" prop="confirmTime" width="150">
83
+        <template slot-scope="scope">
84
+          <span>{{ parseTime(scope.row.confirmTime, '{y}-{m}-{d}') }}</span>
85
+        </template>
86
+      </el-table-column>
87
+      <el-table-column label="确认状态" align="center" prop="confirmStatus" />
88
+      <el-table-column label="是否通过" align="center" prop="isApproved" />
89
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
90
+        <template slot-scope="scope">
91
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
92
+            v-hasPermi="['oa:eval:edit']">修改</el-button>
93
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
94
+            v-hasPermi="['oa:eval:remove']">删除</el-button>
95
+        </template>
96
+      </el-table-column>
97
+    </el-table>
98
+
99
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
100
+      @pagination="getList" />
101
+
102
+    <!-- 添加或修改职称评审对话框 -->
103
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
104
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
105
+        <el-form-item label="申请人" prop="userId">
106
+          <el-input v-model="form.userId" placeholder="请输入申请人" />
107
+        </el-form-item>
108
+        <el-form-item label="评审年度" prop="annual">
109
+          <el-input v-model="form.annual" placeholder="请输入评审年度" />
110
+        </el-form-item>
111
+        <el-form-item label="评审单位" prop="institude">
112
+          <el-input v-model="form.institude" placeholder="请输入评审单位" />
113
+        </el-form-item>
114
+        <el-form-item label="职称级别" prop="level">
115
+          <el-input v-model="form.level" placeholder="请输入职称级别" />
116
+        </el-form-item>
117
+        <el-form-item label="职称专业名称" prop="titleProfession">
118
+          <el-input v-model="form.titleProfession" placeholder="请输入职称专业名称" />
119
+        </el-form-item>
120
+        <el-form-item label="评审表" prop="sheet">
121
+          <el-input v-model="form.sheet" placeholder="请输入评审表" />
122
+        </el-form-item>
123
+        <el-form-item label="评审表" prop="sheetStamp">
124
+          <el-input v-model="form.sheetStamp" placeholder="请输入评审表" />
125
+        </el-form-item>
126
+        <el-form-item label="其他材料" prop="material">
127
+          <el-input v-model="form.material" placeholder="请输入其他材料" />
128
+        </el-form-item>
129
+        <el-form-item label="是否通过" prop="isApproved">
130
+          <el-input v-model="form.isApproved" placeholder="请输入是否通过" />
131
+        </el-form-item>
132
+        <el-form-item label="公示红头文件" prop="publicityFile">
133
+          <file-upload v-model="form.publicityFile" />
134
+        </el-form-item>
135
+        <el-form-item label="证书扫描件" prop="scanFile">
136
+          <file-upload v-model="form.scanFile" />
137
+        </el-form-item>
138
+        <el-form-item label="证书取得时间" prop="obtainTime">
139
+          <el-date-picker clearable v-model="form.obtainTime" type="date" value-format="yyyy-MM-dd"
140
+            placeholder="请选择证书取得时间">
141
+          </el-date-picker>
142
+        </el-form-item>
143
+        <el-form-item label="申请时间" prop="applyTime">
144
+          <el-date-picker clearable v-model="form.applyTime" type="date" value-format="yyyy-MM-dd"
145
+            placeholder="请选择申请时间">
146
+          </el-date-picker>
147
+        </el-form-item>
148
+        <el-form-item label="职称管理员" prop="titleUserId">
149
+          <el-input v-model="form.titleUserId" placeholder="请输入职称管理员" />
150
+        </el-form-item>
151
+        <el-form-item label="职称管理员审核时间" prop="titleTime">
152
+          <el-date-picker clearable v-model="form.titleTime" type="date" value-format="yyyy-MM-dd"
153
+            placeholder="请选择职称管理员审核时间">
154
+          </el-date-picker>
155
+        </el-form-item>
156
+        <el-form-item label="职称管理员审核意见" prop="titleComment">
157
+          <el-input v-model="form.titleComment" placeholder="请输入职称管理员审核意见" />
158
+        </el-form-item>
159
+        <el-form-item label="盖章材料上传时间" prop="materialUploadTime">
160
+          <el-date-picker clearable v-model="form.materialUploadTime" type="date" value-format="yyyy-MM-dd"
161
+            placeholder="请选择盖章材料上传时间">
162
+          </el-date-picker>
163
+        </el-form-item>
164
+        <el-form-item label="确认人" prop="confirmer">
165
+          <el-input v-model="form.confirmer" placeholder="请输入确认人" />
166
+        </el-form-item>
167
+        <el-form-item label="确认时间" prop="confirmTime">
168
+          <el-date-picker clearable v-model="form.confirmTime" type="date" value-format="yyyy-MM-dd"
169
+            placeholder="请选择确认时间">
170
+          </el-date-picker>
171
+        </el-form-item>
172
+      </el-form>
173
+      <div slot="footer" class="dialog-footer">
174
+        <el-button type="primary" @click="submitForm">确 定</el-button>
175
+        <el-button @click="cancel">取 消</el-button>
176
+      </div>
177
+    </el-dialog>
178
+  </div>
179
+</template>
180
+
181
+<script>
182
+import { listEval, getEval, delEval, addEval, updateEval } from "@/api/oa/titles/titles";
183
+
184
+export default {
185
+  name: "Eval",
186
+  data() {
187
+    return {
188
+      // 遮罩层
189
+      loading: true,
190
+      // 选中数组
191
+      ids: [],
192
+      // 非单个禁用
193
+      single: true,
194
+      // 非多个禁用
195
+      multiple: true,
196
+      // 显示搜索条件
197
+      showSearch: true,
198
+      // 总条数
199
+      total: 0,
200
+      // 职称评审表格数据
201
+      evalList: [],
202
+      // 弹出层标题
203
+      title: "",
204
+      // 是否显示弹出层
205
+      open: false,
206
+      // 查询参数
207
+      queryParams: {
208
+        pageNum: 1,
209
+        pageSize: 10,
210
+        userId: null,
211
+        annual: null,
212
+        institude: null,
213
+        type: null,
214
+        level: null,
215
+        titleProfession: null,
216
+        sheet: null,
217
+        sheetStamp: null,
218
+        material: null,
219
+        isApproved: null,
220
+        publicityFile: null,
221
+        scanFile: null,
222
+        obtainTime: null,
223
+        applyTime: null,
224
+        titleUserId: null,
225
+        titleTime: null,
226
+        titleComment: null,
227
+        materialUploadTime: null,
228
+        confirmer: null,
229
+        confirmTime: null,
230
+        confirmStatus: null
231
+      },
232
+      // 表单参数
233
+      form: {},
234
+      // 表单校验
235
+      rules: {
236
+      }
237
+    };
238
+  },
239
+  created() {
240
+    this.getList();
241
+  },
242
+  methods: {
243
+    /** 查询职称评审列表 */
244
+    getList() {
245
+      this.loading = true;
246
+      listEval(this.queryParams).then(response => {
247
+        this.evalList = response.rows;
248
+        this.total = response.total;
249
+        this.loading = false;
250
+      });
251
+    },
252
+    // 取消按钮
253
+    cancel() {
254
+      this.open = false;
255
+      this.reset();
256
+    },
257
+    // 表单重置
258
+    reset() {
259
+      this.form = {
260
+        titleEvalId: null,
261
+        userId: null,
262
+        annual: null,
263
+        institude: null,
264
+        type: null,
265
+        level: null,
266
+        titleProfession: null,
267
+        sheet: null,
268
+        sheetStamp: null,
269
+        material: null,
270
+        isApproved: null,
271
+        publicityFile: null,
272
+        scanFile: null,
273
+        obtainTime: null,
274
+        applyTime: null,
275
+        titleUserId: null,
276
+        titleTime: null,
277
+        titleComment: null,
278
+        materialUploadTime: null,
279
+        confirmer: null,
280
+        confirmTime: null,
281
+        confirmStatus: null
282
+      };
283
+      this.resetForm("form");
284
+    },
285
+    /** 搜索按钮操作 */
286
+    handleQuery() {
287
+      this.queryParams.pageNum = 1;
288
+      this.getList();
289
+    },
290
+    /** 重置按钮操作 */
291
+    resetQuery() {
292
+      this.resetForm("queryForm");
293
+      this.handleQuery();
294
+    },
295
+    // 多选框选中数据
296
+    handleSelectionChange(selection) {
297
+      this.ids = selection.map(item => item.titleEvalId)
298
+      this.single = selection.length !== 1
299
+      this.multiple = !selection.length
300
+    },
301
+    /** 新增按钮操作 */
302
+    handleAdd() {
303
+      this.reset();
304
+      this.open = true;
305
+      this.title = "添加职称评审";
306
+    },
307
+    /** 修改按钮操作 */
308
+    handleUpdate(row) {
309
+      this.reset();
310
+      const titleEvalId = row.titleEvalId || this.ids
311
+      getEval(titleEvalId).then(response => {
312
+        this.form = response.data;
313
+        this.open = true;
314
+        this.title = "修改职称评审";
315
+      });
316
+    },
317
+    /** 提交按钮 */
318
+    submitForm() {
319
+      this.$refs["form"].validate(valid => {
320
+        if (valid) {
321
+          if (this.form.titleEvalId != null) {
322
+            updateEval(this.form).then(response => {
323
+              this.$modal.msgSuccess("修改成功");
324
+              this.open = false;
325
+              this.getList();
326
+            });
327
+          } else {
328
+            addEval(this.form).then(response => {
329
+              this.$modal.msgSuccess("新增成功");
330
+              this.open = false;
331
+              this.getList();
332
+            });
333
+          }
334
+        }
335
+      });
336
+    },
337
+    /** 删除按钮操作 */
338
+    handleDelete(row) {
339
+      const titleEvalIds = row.titleEvalId || this.ids;
340
+      this.$modal.confirm('是否确认删除职称评审编号为"' + titleEvalIds + '"的数据项?').then(function () {
341
+        return delEval(titleEvalIds);
342
+      }).then(() => {
343
+        this.getList();
344
+        this.$modal.msgSuccess("删除成功");
345
+      }).catch(() => { });
346
+    },
347
+    /** 导出按钮操作 */
348
+    handleExport() {
349
+      this.download('oa/eval/export', {
350
+        ...this.queryParams
351
+      }, `eval_${new Date().getTime()}.xlsx`)
352
+    }
353
+  }
354
+};
355
+</script>

Laden…
Annuleren
Opslaan