Browse Source

refactor: 重构两个台账模块的接口和页面逻辑

1. 调整免考核人员和合同到期台账的后端接口路径与参数
2. 重构页面查询条件、表单字段与字典映射
3. 新增增删改查完整业务逻辑与弹窗组件
4. 统一导出导入模板与文件名格式
huoyi 1 month ago
parent
commit
37e46e7d80

+ 35 - 15
src/api/ledgerManage/contractExpirationLedger.js

@@ -1,53 +1,73 @@
1 1
 import request from '@/utils/request'
2 2
 
3
-// 查询合同到期台账列表
3
+// 查询合同到期列表
4 4
 export function listContractExpirationLedger(query) {
5 5
   return request({
6
-    url: '/ledger/contract-expiration/list',
6
+    url: '/ledger/contract/list',
7 7
     method: 'get',
8 8
     params: query
9 9
   })
10 10
 }
11 11
 
12
-// 查询合同到期台账详情(合同明细)
12
+// 获取合同到期详细信息
13 13
 export function getContractExpirationLedger(id) {
14 14
   return request({
15
-    url: `/ledger/contract-expiration/${id}`,
15
+    url: `/ledger/contract/${id}`,
16 16
     method: 'get'
17 17
   })
18 18
 }
19 19
 
20
-// 新增合同到期台账
20
+// 新增合同到期
21 21
 export function addContractExpirationLedger(data) {
22 22
   return request({
23
-    url: '/ledger/contract-expiration',
23
+    url: '/ledger/contract',
24 24
     method: 'post',
25 25
     data: data
26 26
   })
27 27
 }
28 28
 
29
-// 修改合同到期台账
29
+// 修改合同到期
30 30
 export function updateContractExpirationLedger(data) {
31 31
   return request({
32
-    url: '/ledger/contract-expiration',
32
+    url: '/ledger/contract',
33 33
     method: 'put',
34 34
     data: data
35 35
   })
36 36
 }
37 37
 
38
-// 删除合同到期台账
38
+// 删除合同到期
39 39
 export function delContractExpirationLedger(ids) {
40 40
   return request({
41
-    url: `/ledger/contract-expiration/${ids}`,
41
+    url: `/ledger/contract/${ids}`,
42 42
     method: 'delete'
43 43
   })
44 44
 }
45 45
 
46
-// 导出合同到期台账列表
47
-export function exportContractExpirationLedger(query) {
46
+// 导出合同到期列表
47
+export function exportContractExpirationLedger(data) {
48 48
   return request({
49
-    url: '/ledger/contract-expiration/export',
50
-    method: 'get',
51
-    params: query
49
+    url: '/ledger/contract/export',
50
+    method: 'post',
51
+    data: data
52
+  })
53
+}
54
+
55
+// 导入数据列表
56
+export function importContractData(data) {
57
+  return request({
58
+    url: '/ledger/contract/importData',
59
+    method: 'post',
60
+    data: data,
61
+    headers: {
62
+      'Content-Type': 'multipart/form-data'
63
+    }
64
+  })
65
+}
66
+
67
+// 获取导入模板
68
+export function importContractTemplate() {
69
+  return request({
70
+    url: '/ledger/contract/importTemplate',
71
+    method: 'post'
52 72
   })
53 73
 }

+ 39 - 11
src/api/performance/exemptEvaluation.js

@@ -1,45 +1,73 @@
1 1
 import request from '@/utils/request'
2 2
 
3
-// 查询免考核人员列表
3
+// 查询不参加绩效考核人员名单列表
4 4
 export function listExemptEvaluation(query) {
5 5
   return request({
6
-    url: '/performance/exempt-evaluation/list',
6
+    url: '/ledger/excluded/list',
7 7
     method: 'get',
8 8
     params: query
9 9
   })
10 10
 }
11 11
 
12
-// 新增免考核人员
12
+// 导出不参加绩效考核人员名单列表
13
+export function exportExemptEvaluation(data) {
14
+  return request({
15
+    url: '/ledger/excluded/export',
16
+    method: 'post',
17
+    data: data
18
+  })
19
+}
20
+
21
+// 获取不参加绩效考核人员名单详细信息
22
+export function getExemptEvaluation(id) {
23
+  return request({
24
+    url: `/ledger/excluded/${id}`,
25
+    method: 'get'
26
+  })
27
+}
28
+
29
+// 新增不参加绩效考核人员名单
13 30
 export function addExemptEvaluation(data) {
14 31
   return request({
15
-    url: '/performance/exempt-evaluation',
32
+    url: '/ledger/excluded',
16 33
     method: 'post',
17 34
     data: data
18 35
   })
19 36
 }
20 37
 
21
-// 修改免考核人员
38
+// 修改不参加绩效考核人员名单
22 39
 export function updateExemptEvaluation(data) {
23 40
   return request({
24
-    url: '/performance/exempt-evaluation',
41
+    url: '/ledger/excluded',
25 42
     method: 'put',
26 43
     data: data
27 44
   })
28 45
 }
29 46
 
30
-// 删除免考核人员
47
+// 删除不参加绩效考核人员名单
31 48
 export function delExemptEvaluation(ids) {
32 49
   return request({
33
-    url: `/performance/exempt-evaluation/${ids}`,
50
+    url: `/ledger/excluded/${ids}`,
34 51
     method: 'delete'
35 52
   })
36 53
 }
37 54
 
38
-// 导入免考核人员
55
+// 导入数据列表
39 56
 export function importExemptEvaluation(data) {
40 57
   return request({
41
-    url: '/performance/exempt-evaluation/import',
58
+    url: '/ledger/excluded/importData',
42 59
     method: 'post',
43
-    data: data
60
+    data: data,
61
+    headers: {
62
+      'Content-Type': 'multipart/form-data'
63
+    }
64
+  })
65
+}
66
+
67
+// 获取导入模板
68
+export function importExemptTemplate() {
69
+  return request({
70
+    url: '/ledger/excluded/importTemplate',
71
+    method: 'post'
44 72
   })
45 73
 }

+ 246 - 52
src/views/ledgerManage/contractExpirationLedger/index.vue

@@ -2,7 +2,7 @@
2 2
   <div class="app-container">
3 3
     <div class="filter-container">
4 4
       <el-form :model="queryParams" ref="queryFormRef" :inline="true" class="search-form">
5
-        <el-form-item label="姓名" prop="userName">
5
+        <el-form-item label="姓名" prop="userId">
6 6
           <UserSelect v-model="queryParams.userId" placeholder="请输入姓名搜索" style="width: 200px" />
7 7
         </el-form-item>
8 8
 
@@ -12,32 +12,24 @@
12 12
           </el-select>
13 13
         </el-form-item>
14 14
 
15
-        <el-form-item label="部门" prop="deptName">
16
-          <el-input v-model="queryParams.deptName" placeholder="请输入部门" clearable style="width: 200px" />
17
-        </el-form-item>
18
-
19
-        <el-form-item label="最近合同开始时间" prop="recentContractStartTime">
20
-          <el-date-picker v-model="queryParams.recentContractStartTime" type="date" value-format="YYYY-MM-DD"
21
-            placeholder="选择日期" style="width: 200px" />
22
-        </el-form-item>
23
-
24
-        <el-form-item label="最近合同结束时间" prop="recentContractEndTime">
25
-          <el-date-picker v-model="queryParams.recentContractEndTime" type="date" value-format="YYYY-MM-DD"
26
-            placeholder="选择日期" style="width: 200px" />
27
-        </el-form-item>
28
-
29 15
         <el-form-item label="合同名称" prop="contractName">
30 16
           <el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable style="width: 200px" />
31 17
         </el-form-item>
32 18
 
33
-        <el-form-item label="开始时间" prop="contractStartTime">
34
-          <el-date-picker v-model="queryParams.contractStartTime" type="date" value-format="YYYY-MM-DD"
35
-            placeholder="选择日期" style="width: 200px" />
19
+        <el-form-item label="合同开始日期" prop="contractStartDateQueryStartDate">
20
+          <el-date-picker v-model="queryParams.contractStartDateQueryStartDate" type="date" value-format="YYYY-MM-DD"
21
+            placeholder="开始日期" style="width: 150px" />
22
+          <span style="padding: 0 8px">-</span>
23
+          <el-date-picker v-model="queryParams.contractStartDateQueryEndDate" type="date" value-format="YYYY-MM-DD"
24
+            placeholder="结束日期" style="width: 150px" />
36 25
         </el-form-item>
37 26
 
38
-        <el-form-item label="结束时间" prop="contractEndTime">
39
-          <el-date-picker v-model="queryParams.contractEndTime" type="date" value-format="YYYY-MM-DD"
40
-            placeholder="选择日期" style="width: 200px" />
27
+        <el-form-item label="合同结束日期" prop="contractEndDateQueryStartDate">
28
+          <el-date-picker v-model="queryParams.contractEndDateQueryStartDate" type="date" value-format="YYYY-MM-DD"
29
+            placeholder="开始日期" style="width: 150px" />
30
+          <span style="padding: 0 8px">-</span>
31
+          <el-date-picker v-model="queryParams.contractEndDateQueryEndDate" type="date" value-format="YYYY-MM-DD"
32
+            placeholder="结束日期" style="width: 150px" />
41 33
         </el-form-item>
42 34
 
43 35
         <el-form-item>
@@ -48,23 +40,27 @@
48 40
     </div>
49 41
 
50 42
     <div class="operation-container">
43
+      <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
44
+      <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
45
+      <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
51 46
       <el-button type="info" plain icon="Upload" @click="handleImport">导入</el-button>
52 47
       <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
53 48
     </div>
54 49
 
55 50
     <el-table v-loading="loading" :data="list" border fit highlight-current-row style="width: 100%; margin-top: 20px;"
56
-      @expand-change="handleExpandChange">
51
+      @selection-change="handleSelectionChange" @expand-change="handleExpandChange">
52
+      <el-table-column type="selection" width="55" align="center" />
57 53
       <el-table-column type="expand">
58 54
         <template #default="scope">
59 55
           <div class="detail-container">
60 56
             <div class="detail-title">合同明细</div>
61
-            <el-table :data="scope.row.contractDetailList || []" border fit size="small"
57
+            <el-table :data="scope.row.ledgerContractExpirationDetailList || []" border fit size="small"
62 58
               style="width: 100%; margin-top: 10px;">
63 59
               <el-table-column label="序号" type="index" width="60" align="center" />
64 60
               <el-table-column label="合同名称" prop="contractName" align="center" min-width="200"
65 61
                 show-overflow-tooltip />
66
-              <el-table-column label="开始时间" prop="startTime" align="center" min-width="130" />
67
-              <el-table-column label="结束时间" prop="endTime" align="center" min-width="130" />
62
+              <el-table-column label="开始时间" prop="contractStartDate" align="center" min-width="130" />
63
+              <el-table-column label="结束时间" prop="contractEndDate" align="center" min-width="130" />
68 64
             </el-table>
69 65
           </div>
70 66
         </template>
@@ -80,14 +76,81 @@
80 76
           <dict-tag :options="employment_type" :value="scope.row.employmentType" />
81 77
         </template>
82 78
       </el-table-column>
83
-      <el-table-column label="部门" prop="deptName" align="center" min-width="150" show-overflow-tooltip />
84
-      <el-table-column label="最近合同开始时间" prop="recentContractStartTime" align="center" min-width="150" />
85
-      <el-table-column label="最近合同结束时间" prop="recentContractEndTime" align="center" min-width="150" />
79
+      <el-table-column label="大队名称" prop="brigadeName" align="center" min-width="130" show-overflow-tooltip />
80
+      <el-table-column label="合同名称" prop="contractName" align="center" min-width="150" show-overflow-tooltip />
81
+      <el-table-column label="合同开始日期" prop="contractStartDate" align="center" min-width="130" />
82
+      <el-table-column label="合同结束日期" prop="contractEndDate" align="center" min-width="130" />
86 83
     </el-table>
87 84
 
88 85
     <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
89 86
       @pagination="getList" />
90 87
 
88
+    <!-- 添加或修改合同到期对话框 -->
89
+    <el-dialog :title="title" v-model="open" width="700px" append-to-body destroy-on-close>
90
+      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
91
+        <el-form-item label="姓名" prop="userId">
92
+          <UserSelect v-model="form.userId" placeholder="请选择姓名" style="width: 100%" />
93
+        </el-form-item>
94
+        <el-form-item label="用工形式" prop="employmentType">
95
+          <el-select v-model="form.employmentType" placeholder="请选择用工形式" clearable style="width: 100%">
96
+            <el-option v-for="dict in employment_type" :key="dict.value" :label="dict.label" :value="dict.value" />
97
+          </el-select>
98
+        </el-form-item>
99
+        <el-form-item label="大队名称" prop="brigadeName">
100
+          <el-input v-model="form.brigadeName" placeholder="请输入大队名称" />
101
+        </el-form-item>
102
+        <el-form-item label="合同名称" prop="contractName">
103
+          <el-input v-model="form.contractName" placeholder="请输入合同名称" :disabled="!!form.id" />
104
+        </el-form-item>
105
+        <el-form-item label="合同开始日期" prop="contractStartDate">
106
+          <el-date-picker v-model="form.contractStartDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择合同开始日期" style="width: 100%" :disabled="!!form.id" />
107
+        </el-form-item>
108
+        <el-form-item label="合同结束日期" prop="contractEndDate">
109
+          <el-date-picker v-model="form.contractEndDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择合同结束日期" style="width: 100%" :disabled="!!form.id" />
110
+        </el-form-item>
111
+        <el-form-item label="备注" prop="remark">
112
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
113
+        </el-form-item>
114
+        <el-form-item label="合同明细">
115
+          <div style="width: 100%">
116
+            <el-button type="primary" size="small" icon="Plus" @click="handleAddDetail" style="margin-bottom: 10px">
117
+              新增明细
118
+            </el-button>
119
+            <el-table :data="form.ledgerContractExpirationDetailList || []" border fit size="small" style="width: 100%">
120
+              <el-table-column label="合同名称" min-width="180">
121
+                <template #default="scope">
122
+                  <el-input v-model="scope.row.contractName" placeholder="请输入合同名称" size="small" />
123
+                </template>
124
+              </el-table-column>
125
+              <el-table-column label="开始日期" min-width="140">
126
+                <template #default="scope">
127
+                  <el-date-picker v-model="scope.row.contractStartDate" value-format="YYYY-MM-DD" type="date"
128
+                    placeholder="选择日期" size="small" style="width: 100%" />
129
+                </template>
130
+              </el-table-column>
131
+              <el-table-column label="结束日期" min-width="140">
132
+                <template #default="scope">
133
+                  <el-date-picker v-model="scope.row.contractEndDate" value-format="YYYY-MM-DD" type="date"
134
+                    placeholder="选择日期" size="small" style="width: 100%" />
135
+                </template>
136
+              </el-table-column>
137
+              <el-table-column label="操作" width="80" align="center">
138
+                <template #default="scope">
139
+                  <el-button type="danger" size="small" link icon="Delete" @click="handleDeleteDetail(scope.$index)" />
140
+                </template>
141
+              </el-table-column>
142
+            </el-table>
143
+          </div>
144
+        </el-form-item>
145
+      </el-form>
146
+      <template #footer>
147
+        <div class="dialog-footer">
148
+          <el-button type="primary" @click="submitForm">确 定</el-button>
149
+          <el-button @click="cancel">取 消</el-button>
150
+        </div>
151
+      </template>
152
+    </el-dialog>
153
+
91 154
     <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
92 155
       <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url"
93 156
         :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
@@ -102,7 +165,7 @@
102 165
           <div class="el-upload__tip text-center">
103 166
             <span>仅允许导入xls、xlsx格式文件。</span>
104 167
             <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline"
105
-              @click="importTemplate">下载模板</el-link>
168
+              @click="downloadTemplate">下载模板</el-link>
106 169
           </div>
107 170
         </template>
108 171
       </el-upload>
@@ -117,14 +180,18 @@
117 180
 </template>
118 181
 
119 182
 <script setup name="ContractExpirationLedger">
120
-import { ref, reactive, getCurrentInstance, onMounted } from 'vue'
183
+import { ref, reactive, getCurrentInstance, onMounted, watch } from 'vue'
121 184
 import { UploadFilled } from '@element-plus/icons-vue'
122 185
 import UserSelect from '@/components/UserSelect/index.vue'
123 186
 import {
124 187
   listContractExpirationLedger,
125
-  exportContractExpirationLedger,
126
-  getContractExpirationLedger
188
+  getContractExpirationLedger,
189
+  addContractExpirationLedger,
190
+  updateContractExpirationLedger,
191
+  delContractExpirationLedger,
192
+  exportContractExpirationLedger
127 193
 } from '@/api/ledgerManage/contractExpirationLedger'
194
+import { getUser } from '@/api/system/user'
128 195
 import { getToken } from '@/utils/auth'
129 196
 
130 197
 const { proxy } = getCurrentInstance()
@@ -135,18 +202,23 @@ const loading = ref(false)
135 202
 const total = ref(0)
136 203
 const list = ref([])
137 204
 const queryFormRef = ref(null)
205
+const formRef = ref(null)
206
+const ids = ref([])
207
+const single = ref(true)
208
+const multiple = ref(true)
209
+const open = ref(false)
210
+const title = ref('')
138 211
 
139 212
 const queryParams = reactive({
140 213
   pageNum: 1,
141 214
   pageSize: 10,
142 215
   userId: '',
143 216
   employmentType: '',
144
-  deptName: '',
145
-  recentContractStartTime: '',
146
-  recentContractEndTime: '',
147 217
   contractName: '',
148
-  contractStartTime: '',
149
-  contractEndTime: ''
218
+  contractStartDateQueryStartDate: '',
219
+  contractStartDateQueryEndDate: '',
220
+  contractEndDateQueryStartDate: '',
221
+  contractEndDateQueryEndDate: ''
150 222
 })
151 223
 
152 224
 const upload = reactive({
@@ -159,6 +231,40 @@ const upload = reactive({
159 231
   }
160 232
 })
161 233
 
234
+const form = ref({
235
+  id: undefined,
236
+  userId: '',
237
+  userName: '',
238
+  employmentType: '',
239
+  brigadeName: '',
240
+  contractName: '',
241
+  contractStartDate: '',
242
+  contractEndDate: '',
243
+  remark: '',
244
+  ledgerContractExpirationDetailList: []
245
+})
246
+
247
+watch(() => form.value.userId, async (newVal) => {
248
+  if (newVal) {
249
+    try {
250
+      const res = await getUser(newVal)
251
+      form.value.userName = res.data?.nickName || ''
252
+    } catch {
253
+      form.value.userName = ''
254
+    }
255
+  } else {
256
+    form.value.userName = ''
257
+  }
258
+})
259
+
260
+const rules = reactive({
261
+  userId: [{ required: true, message: '请选择姓名', trigger: 'change' }],
262
+  employmentType: [{ required: true, message: '请选择用工形式', trigger: 'change' }],
263
+  contractName: [{ required: true, message: '请输入合同名称', trigger: 'blur' }],
264
+  contractStartDate: [{ required: true, message: '请选择合同开始日期', trigger: 'change' }],
265
+  contractEndDate: [{ required: true, message: '请选择合同结束日期', trigger: 'change' }]
266
+})
267
+
162 268
 const getList = async () => {
163 269
   loading.value = true
164 270
   try {
@@ -179,45 +285,133 @@ const resetQuery = () => {
179 285
   queryFormRef.value.resetFields()
180 286
   queryParams.userId = ''
181 287
   queryParams.employmentType = ''
182
-  queryParams.deptName = ''
183
-  queryParams.recentContractStartTime = ''
184
-  queryParams.recentContractEndTime = ''
185 288
   queryParams.contractName = ''
186
-  queryParams.contractStartTime = ''
187
-  queryParams.contractEndTime = ''
289
+  queryParams.contractStartDateQueryStartDate = ''
290
+  queryParams.contractStartDateQueryEndDate = ''
291
+  queryParams.contractEndDateQueryStartDate = ''
292
+  queryParams.contractEndDateQueryEndDate = ''
188 293
   handleQuery()
189 294
 }
190 295
 
296
+const handleSelectionChange = (selection) => {
297
+  ids.value = selection.map(item => item.id)
298
+  single.value = selection.length !== 1
299
+  multiple.value = !selection.length
300
+}
301
+
191 302
 const handleExpandChange = async (row, expandedRows) => {
192
-  if (expandedRows.includes(row) && (!row.contractDetailList || row.contractDetailList.length === 0)) {
303
+  if (expandedRows.includes(row) && (!row.ledgerContractExpirationDetailList || row.ledgerContractExpirationDetailList.length === 0)) {
193 304
     try {
194 305
       const res = await getContractExpirationLedger(row.id)
195
-      row.contractDetailList = res.data?.contractDetailList || res.data || []
306
+      row.ledgerContractExpirationDetailList = res.data?.ledgerContractExpirationDetailList || res.data || []
196 307
     } catch (error) {
197
-      row.contractDetailList = []
308
+      row.ledgerContractExpirationDetailList = []
198 309
     }
199 310
   }
200 311
 }
201 312
 
313
+const handleAdd = () => {
314
+  reset()
315
+  open.value = true
316
+  title.value = '添加合同到期信息'
317
+}
318
+
319
+const handleUpdate = async (row) => {
320
+  reset()
321
+  const id = row.id || ids.value[0]
322
+  const res = await getContractExpirationLedger(id)
323
+  form.value = res.data || {}
324
+  open.value = true
325
+  title.value = '修改合同到期信息'
326
+}
327
+
328
+const handleDelete = (row) => {
329
+  const deleteIds = row.id || ids.value
330
+  proxy.$modal.confirm('是否确认删除合同到期信息编号为"' + deleteIds + '"的数据项?').then(() => {
331
+    return delContractExpirationLedger(deleteIds)
332
+  }).then(() => {
333
+    getList()
334
+    proxy.$modal.msgSuccess('删除成功')
335
+  }).catch(() => { })
336
+}
337
+
338
+const handleAddDetail = () => {
339
+  if (!form.value.ledgerContractExpirationDetailList) {
340
+    form.value.ledgerContractExpirationDetailList = []
341
+  }
342
+  form.value.ledgerContractExpirationDetailList.push({
343
+    contractName: '',
344
+    contractStartDate: '',
345
+    contractEndDate: ''
346
+  })
347
+}
348
+
349
+const handleDeleteDetail = (index) => {
350
+  form.value.ledgerContractExpirationDetailList.splice(index, 1)
351
+}
352
+
353
+const submitForm = async () => {
354
+  const valid = await formRef.value.validate().catch(() => false)
355
+  if (!valid) return
356
+
357
+  loading.value = true
358
+  try {
359
+    if (form.value.id) {
360
+      await updateContractExpirationLedger(form.value)
361
+      proxy.$modal.msgSuccess('修改成功')
362
+    } else {
363
+      await addContractExpirationLedger(form.value)
364
+      proxy.$modal.msgSuccess('新增成功')
365
+    }
366
+    open.value = false
367
+    getList()
368
+  } finally {
369
+    loading.value = false
370
+  }
371
+}
372
+
373
+const cancel = () => {
374
+  open.value = false
375
+  reset()
376
+}
377
+
378
+const reset = () => {
379
+  form.value = {
380
+    id: undefined,
381
+    userId: '',
382
+    userName: '',
383
+    employmentType: '',
384
+    brigadeName: '',
385
+    contractName: '',
386
+    contractStartDate: '',
387
+    contractEndDate: '',
388
+    remark: '',
389
+    ledgerContractExpirationDetailList: []
390
+  }
391
+  formRef.value && formRef.value.resetFields()
392
+}
393
+
202 394
 const handleExport = () => {
203 395
   proxy.download(
204
-    'ledger/contract-expiration/export',
396
+    'ledger/contract/export',
205 397
     queryParams,
206
-    `contract_expiration_ledger_${new Date().getTime()}.xlsx`
398
+    `合同到期台账模板_${new Date().getTime()}.xlsx`,
399
+    'post'
207 400
   )
208 401
 }
209 402
 
210 403
 const handleImport = () => {
211
-  upload.title = '合同到期台账导入'
212
-  upload.url = import.meta.env.VITE_APP_BASE_API + '/ledger/contract-expiration/import'
404
+  upload.title = '合同到期导入'
405
+  upload.url = import.meta.env.VITE_APP_BASE_API + '/ledger/contract/importData'
213 406
   upload.open = true
214 407
 }
215 408
 
216
-const importTemplate = () => {
409
+const downloadTemplate = () => {
217 410
   proxy.download(
218
-    'ledger/contract-expiration/importTemplate',
411
+    'ledger/contract/importTemplate',
219 412
     {},
220
-    `contract_expiration_template_${new Date().getTime()}.xlsx`
413
+    `合同到期台账模板_${new Date().getTime()}.xlsx`,
414
+    'post'
221 415
   )
222 416
 }
223 417
 

+ 12 - 14
src/views/ledgerManage/qualificationSummary/index.vue

@@ -6,17 +6,17 @@
6 6
           <UserSelect v-model="queryParams.userId" placeholder="请输入姓名搜索" style="width: 200px" />
7 7
         </el-form-item>
8 8
 
9
-        <el-form-item label="证书等级" prop="certificateLevel">
10
-          <el-select v-model="queryParams.certificateLevel" placeholder="请选择证书等级" clearable style="width: 200px">
11
-            <el-option v-for="dict in certificate_level" :key="dict.value" :label="dict.label" :value="dict.value" />
9
+        <el-form-item label="证书等级" prop="certLevel">
10
+          <el-select v-model="queryParams.certLevel" placeholder="请选择证书等级" clearable style="width: 200px">
11
+            <el-option v-for="dict in sys_user_qualification_level" :key="dict.value" :label="dict.label" :value="dict.label" />
12 12
           </el-select>
13 13
         </el-form-item>
14 14
 
15
-        <el-form-item label="发证时间" prop="issueDate" style="width: 200px">
15
+        <el-form-item label="发证时间" prop="issueDate" style="width: 300px">
16 16
           <el-date-picker v-model="queryParams.issueDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择发证时间" clearable />
17 17
         </el-form-item>
18 18
 
19
-        <el-form-item label="到期日期" prop="expiryDate" style="width: 200px">
19
+        <el-form-item label="到期日期" prop="expiryDate" style="width: 300px">
20 20
           <el-date-picker v-model="queryParams.expiryDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择到期日期" clearable />
21 21
         </el-form-item>
22 22
 
@@ -50,7 +50,7 @@
50 50
       <el-table-column label="姓名" prop="personName" align="center" min-width="100" />
51 51
       <el-table-column label="单位" prop="unitName" align="center" min-width="120" />
52 52
       <el-table-column label="证书等级" prop="certLevel" align="center" min-width="100">
53
-   
53
+        
54 54
       </el-table-column>
55 55
       <el-table-column label="发证时间" prop="issueDate" align="center" min-width="120" />
56 56
       <el-table-column label="证书编号" prop="certNo" align="center" min-width="150" show-overflow-tooltip />
@@ -60,7 +60,7 @@
60 60
       <el-table-column label="服务期(月)" prop="serviceMonths" align="center" min-width="110" />
61 61
       <el-table-column label="到期日期" prop="expiryDate" align="center" min-width="120" />
62 62
       <el-table-column label="状态" prop="status" align="center" min-width="90">
63
-       
63
+      
64 64
       </el-table-column>
65 65
       <el-table-column label="到期天数" prop="expireDays" align="center" min-width="100">
66 66
         <template #default="scope">
@@ -97,7 +97,7 @@
97 97
         </el-form-item>
98 98
         <el-form-item label="证书等级" prop="certLevel">
99 99
           <el-select v-model="form.certLevel" placeholder="请选择证书等级" clearable style="width: 100%">
100
-            <el-option v-for="dict in certificate_level" :key="dict.value" :label="dict.label" :value="dict.value" />
100
+            <el-option v-for="dict in sys_user_qualification_level" :key="dict.value" :label="dict.label" :value="dict.value" />
101 101
           </el-select>
102 102
         </el-form-item>
103 103
         <el-form-item label="发证时间" prop="issueDate">
@@ -125,9 +125,7 @@
125 125
           <el-date-picker v-model="form.expiryDate" value-format="YYYY-MM-DD" type="date" placeholder="请选择到期日期" style="width: 100%" />
126 126
         </el-form-item>
127 127
         <el-form-item label="状态" prop="status">
128
-          <el-select v-model="form.status" placeholder="请选择状态" clearable style="width: 100%">
129
-            <el-option v-for="dict in certificate_status" :key="dict.value" :label="dict.label" :value="dict.value" />
130
-          </el-select>
128
+          <el-input v-model="form.status" placeholder="请输入状态" />
131 129
         </el-form-item>
132 130
         <el-form-item label="备注" prop="remark">
133 131
           <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
@@ -178,7 +176,7 @@ import { getToken } from '@/utils/auth'
178 176
 
179 177
 const { proxy } = getCurrentInstance()
180 178
 
181
-const { certificate_level, certificate_status } = proxy.useDict('certificate_level', 'certificate_status')
179
+const { sys_user_qualification_level, certificate_status } = proxy.useDict('sys_user_qualification_level', 'certificate_status')
182 180
 
183 181
 const loading = ref(false)
184 182
 const total = ref(0)
@@ -350,7 +348,7 @@ const handleExport = () => {
350 348
   proxy.download(
351 349
     'ledger/certificate/export',
352 350
     queryParams,
353
-    `qualification_summary_${new Date().getTime()}.xlsx`,
351
+    `资质汇总表_${new Date().getTime()}.xlsx`,
354 352
     'post'
355 353
   )
356 354
 }
@@ -365,7 +363,7 @@ const downloadTemplate = () => {
365 363
   proxy.download(
366 364
     'ledger/certificate/importTemplate',
367 365
     {},
368
-    `qualification_summary_template_${new Date().getTime()}.xlsx`,
366
+    `资质汇总表模板_${new Date().getTime()}.xlsx`,
369 367
     'post'
370 368
   )
371 369
 }

+ 169 - 20
src/views/performanceManage/exemptEvaluation/index.vue

@@ -2,8 +2,8 @@
2 2
   <div class="app-container">
3 3
     <div class="filter-container">
4 4
       <el-form :model="queryParams" ref="queryFormRef" :inline="true" class="search-form">
5
-        <el-form-item label="考核月份" prop="assessmentMonth">
6
-          <el-date-picker v-model="queryParams.assessmentMonth" type="month" placeholder="请选择考核月份"
5
+        <el-form-item label="年度月份" prop="yearAndMonth">
6
+          <el-date-picker v-model="queryParams.yearAndMonth" type="month" placeholder="请选择年度月份"
7 7
             value-format="YYYY-MM" style="width: 200px" />
8 8
         </el-form-item>
9 9
 
@@ -11,8 +11,8 @@
11 11
           <UserSelect v-model="queryParams.userId" placeholder="请输入姓名搜索" style="width: 200px" />
12 12
         </el-form-item>
13 13
 
14
-        <el-form-item label="不参加考核原因" prop="exemptionReason">
15
-          <el-input v-model="queryParams.exemptionReason" placeholder="请输入原因" clearable style="width: 200px" />
14
+        <el-form-item label="不参加考核原因" prop="reason">
15
+          <el-input v-model="queryParams.reason" placeholder="请输入原因" clearable style="width: 200px" />
16 16
         </el-form-item>
17 17
 
18 18
         <el-form-item>
@@ -23,18 +23,54 @@
23 23
     </div>
24 24
 
25 25
     <div class="operation-container">
26
-      <el-button type="success" plain icon="Upload" @click="handleImport">导入</el-button>
26
+      <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
27
+      <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">修改</el-button>
28
+      <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
29
+      <el-button type="info" plain icon="Upload" @click="handleImport">导入</el-button>
30
+      <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
27 31
     </div>
28 32
 
29
-    <el-table v-loading="loading" :data="list" border fit highlight-current-row style="width: 100%; margin-top: 20px;">
30
-      <el-table-column label="考核月份" prop="assessmentMonth" align="center" min-width="150" />
33
+    <el-table v-loading="loading" :data="list" border fit highlight-current-row style="width: 100%; margin-top: 20px;"
34
+      @selection-change="handleSelectionChange">
35
+      <el-table-column type="selection" width="55" align="center" />
36
+      <el-table-column label="序号" type="index" width="60" align="center">
37
+        <template #default="scope">
38
+          {{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
39
+        </template>
40
+      </el-table-column>
41
+      <el-table-column label="年度月份" prop="yearAndMonth" align="center" min-width="150" />
31 42
       <el-table-column label="姓名" prop="userName" align="center" min-width="120" />
32
-      <el-table-column label="不参加考核原因" prop="exemptionReason" align="center" min-width="200" show-overflow-tooltip />
43
+      <el-table-column label="不参加考核原因" prop="reason" align="center" min-width="200" show-overflow-tooltip />
33 44
     </el-table>
34 45
 
35 46
     <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
36 47
       @pagination="getList" />
37 48
 
49
+    <!-- 添加或修改不参加绩效考核人员对话框 -->
50
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body destroy-on-close>
51
+      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
52
+        <el-form-item label="姓名" prop="userId">
53
+          <UserSelect v-model="form.userId" placeholder="请选择姓名" style="width: 100%" />
54
+        </el-form-item>
55
+        <el-form-item label="年度月份" prop="yearAndMonth">
56
+          <el-date-picker v-model="form.yearAndMonth" type="month" placeholder="请选择年度月份"
57
+            value-format="YYYY-MM" style="width: 100%" />
58
+        </el-form-item>
59
+        <el-form-item label="不参加考核原因" prop="reason">
60
+          <el-input v-model="form.reason" type="textarea" placeholder="请输入不参加考核原因" />
61
+        </el-form-item>
62
+        <el-form-item label="备注" prop="remark">
63
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
64
+        </el-form-item>
65
+      </el-form>
66
+      <template #footer>
67
+        <div class="dialog-footer">
68
+          <el-button type="primary" @click="submitForm">确 定</el-button>
69
+          <el-button @click="cancel">取 消</el-button>
70
+        </div>
71
+      </template>
72
+    </el-dialog>
73
+
38 74
     <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
39 75
       <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url"
40 76
         :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
@@ -49,7 +85,7 @@
49 85
           <div class="el-upload__tip text-center">
50 86
             <span>仅允许导入xls、xlsx格式文件。</span>
51 87
             <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline"
52
-              @click="importTemplate">下载模板</el-link>
88
+              @click="downloadTemplate">下载模板</el-link>
53 89
           </div>
54 90
         </template>
55 91
       </el-upload>
@@ -64,10 +100,11 @@
64 100
 </template>
65 101
 
66 102
 <script setup name="ExemptEvaluation">
67
-import { ref, reactive, getCurrentInstance, onMounted } from 'vue'
103
+import { ref, reactive, getCurrentInstance, onMounted, watch } from 'vue'
68 104
 import { UploadFilled } from '@element-plus/icons-vue'
69 105
 import UserSelect from '@/components/UserSelect/index.vue'
70
-import { listExemptEvaluation, delExemptEvaluation } from '@/api/performance/exemptEvaluation'
106
+import { listExemptEvaluation, addExemptEvaluation, updateExemptEvaluation, delExemptEvaluation, getExemptEvaluation, exportExemptEvaluation } from '@/api/performance/exemptEvaluation'
107
+import { getUser } from '@/api/system/user'
71 108
 import { getToken } from '@/utils/auth'
72 109
 
73 110
 const { proxy } = getCurrentInstance()
@@ -76,13 +113,19 @@ const loading = ref(false)
76 113
 const total = ref(0)
77 114
 const list = ref([])
78 115
 const queryFormRef = ref(null)
116
+const formRef = ref(null)
117
+const ids = ref([])
118
+const single = ref(true)
119
+const multiple = ref(true)
120
+const open = ref(false)
121
+const title = ref('')
79 122
 
80 123
 const queryParams = reactive({
81 124
   pageNum: 1,
82 125
   pageSize: 10,
83
-  assessmentMonth: '',
126
+  yearAndMonth: '',
84 127
   userId: '',
85
-  exemptionReason: ''
128
+  reason: ''
86 129
 })
87 130
 
88 131
 const upload = reactive({
@@ -95,6 +138,34 @@ const upload = reactive({
95 138
   }
96 139
 })
97 140
 
141
+const form = ref({
142
+  id: undefined,
143
+  userId: '',
144
+  userName: '',
145
+  yearAndMonth: '',
146
+  reason: '',
147
+  remark: ''
148
+})
149
+
150
+watch(() => form.value.userId, async (newVal) => {
151
+  if (newVal) {
152
+    try {
153
+      const res = await getUser(newVal)
154
+      form.value.userName = res.data?.nickName || ''
155
+    } catch {
156
+      form.value.userName = ''
157
+    }
158
+  } else {
159
+    form.value.userName = ''
160
+  }
161
+})
162
+
163
+const rules = reactive({
164
+  userId: [{ required: true, message: '请选择姓名', trigger: 'change' }],
165
+  yearAndMonth: [{ required: true, message: '请选择年度月份', trigger: 'change' }],
166
+  reason: [{ required: true, message: '请输入不参加考核原因', trigger: 'blur' }]
167
+})
168
+
98 169
 const getList = async () => {
99 170
   loading.value = true
100 171
   try {
@@ -113,23 +184,101 @@ const handleQuery = () => {
113 184
 
114 185
 const resetQuery = () => {
115 186
   queryFormRef.value.resetFields()
116
-  queryParams.assessmentMonth = ''
187
+  queryParams.yearAndMonth = ''
117 188
   queryParams.userId = ''
118
-  queryParams.exemptionReason = ''
189
+  queryParams.reason = ''
119 190
   handleQuery()
120 191
 }
121 192
 
193
+const handleSelectionChange = (selection) => {
194
+  ids.value = selection.map(item => item.id)
195
+  single.value = selection.length !== 1
196
+  multiple.value = !selection.length
197
+}
198
+
199
+const handleAdd = () => {
200
+  reset()
201
+  open.value = true
202
+  title.value = '添加不参加绩效考核人员'
203
+}
204
+
205
+const handleUpdate = async (row) => {
206
+  reset()
207
+  const id = row.id || ids.value[0]
208
+  const res = await getExemptEvaluation(id)
209
+  form.value = res.data || {}
210
+  open.value = true
211
+  title.value = '修改不参加绩效考核人员'
212
+}
213
+
214
+const handleDelete = (row) => {
215
+  const deleteIds = row.id || ids.value
216
+  proxy.$modal.confirm('是否确认删除不参加绩效考核人员编号为"' + deleteIds + '"的数据项?').then(() => {
217
+    return delExemptEvaluation(deleteIds)
218
+  }).then(() => {
219
+    getList()
220
+    proxy.$modal.msgSuccess('删除成功')
221
+  }).catch(() => { })
222
+}
223
+
224
+const submitForm = async () => {
225
+  const valid = await formRef.value.validate().catch(() => false)
226
+  if (!valid) return
227
+
228
+  loading.value = true
229
+  try {
230
+    if (form.value.id) {
231
+      await updateExemptEvaluation(form.value)
232
+      proxy.$modal.msgSuccess('修改成功')
233
+    } else {
234
+      await addExemptEvaluation(form.value)
235
+      proxy.$modal.msgSuccess('新增成功')
236
+    }
237
+    open.value = false
238
+    getList()
239
+  } finally {
240
+    loading.value = false
241
+  }
242
+}
243
+
244
+const cancel = () => {
245
+  open.value = false
246
+  reset()
247
+}
248
+
249
+const reset = () => {
250
+  form.value = {
251
+    id: undefined,
252
+    userId: '',
253
+    userName: '',
254
+    yearAndMonth: '',
255
+    reason: '',
256
+    remark: ''
257
+  }
258
+  formRef.value && formRef.value.resetFields()
259
+}
260
+
122 261
 const handleImport = () => {
123
-  upload.title = '免考核人员导入'
124
-  upload.url = import.meta.env.VITE_APP_BASE_API + '/performance/exempt-evaluation/import'
262
+  upload.title = '不参加绩效考核人员导入'
263
+  upload.url = import.meta.env.VITE_APP_BASE_API + '/ledger/excluded/importData'
125 264
   upload.open = true
126 265
 }
127 266
 
128
-const importTemplate = () => {
267
+const downloadTemplate = () => {
129 268
   proxy.download(
130
-    'performance/exempt-evaluation/importTemplate',
269
+    'ledger/excluded/importTemplate',
131 270
     {},
132
-    `exempt_evaluation_template_${new Date().getTime()}.xlsx`
271
+    `不参加绩效考核人员模板_${new Date().getTime()}.xlsx`,
272
+    'post'
273
+  )
274
+}
275
+
276
+const handleExport = () => {
277
+  proxy.download(
278
+    'ledger/excluded/export',
279
+    queryParams,
280
+    `不参加绩效考核人员_${new Date().getTime()}.xlsx`,
281
+    'post'
133 282
   )
134 283
 }
135 284