npmapps 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,436 @@
1
+ <template>
2
+ <div class="employeeSchedulingManagement">
3
+ <div class="header" v-if="!isShiftChange">
4
+ <div class="left">
5
+ <el-input
6
+ size="mini"
7
+ placeholder="请输入内容"
8
+ :value="attendanceCycleByMonthObj.monthName"
9
+ class="input-with-select"
10
+ style="margin-right: 10px"
11
+ >
12
+ <el-button
13
+ slot="append"
14
+ icon="el-icon-search"
15
+ @click="openAttendanceCycle"
16
+ ></el-button>
17
+ </el-input>
18
+ <el-button size="mini" type="" @click="openBatchScheduling">批量排班</el-button>
19
+ <el-button size="mini" type="">导出排班</el-button>
20
+
21
+ <el-button size="mini" type="" @click="openBatchShiftChange">批量调班</el-button>
22
+ <el-button size="mini" type="" @click="shiftChangeForSelected"
23
+ >为选中人员调班</el-button
24
+ >
25
+ <el-button size="mini" type="">导入排班</el-button>
26
+ <el-button size="mini" type="" @click="openShiftChangeRecord">查看调班记录</el-button>
27
+ <el-checkbox style="margin-left: 10px" v-model="showOnlyUnscheduled"
28
+ >只显示未排班人员</el-checkbox
29
+ >
30
+ </div>
31
+ <div class="right">
32
+ <el-input
33
+ size="mini"
34
+ placeholder="考勤组"
35
+ :value="attendanceGroupObj.monthName"
36
+ class="input-with-select"
37
+ style="margin-right: 10px"
38
+ >
39
+ <el-button
40
+ slot="append"
41
+ icon="el-icon-search"
42
+ @click="openAttendanceGroup"
43
+ ></el-button>
44
+ </el-input>
45
+ </div>
46
+ </div>
47
+ <div class="header" v-else>
48
+ <div class="left">
49
+ <el-button size="mini" type="" @click="saveShiftChange">保存</el-button>
50
+ <el-button size="mini" type="" @click="closeShiftChange"
51
+ >取消</el-button
52
+ >
53
+ </div>
54
+ </div>
55
+ <el-table
56
+ v-loading="loading"
57
+ size="mini"
58
+ :data="tableData"
59
+ style="width: 100%"
60
+ border
61
+ @selection-change="handleSelectionChange"
62
+ ref="multipleTable"
63
+ >
64
+ <el-table-column
65
+ v-if="!isShiftChange"
66
+ type="selection"
67
+ width="55"
68
+ ></el-table-column>
69
+ <el-table-column prop="employeeId" label="工号" width="180" fixed="left">
70
+ <template slot="header">
71
+ <div style="padding-left: 6px">工号</div>
72
+ </template>
73
+ </el-table-column>
74
+ <el-table-column prop="name" label="姓名" width="180" fixed="left">
75
+ <template slot="header">
76
+ <div style="padding-left: 6px">姓名</div>
77
+ </template>
78
+ </el-table-column>
79
+ <el-table-column prop="organization" label="机构" show-overflow-tooltip>
80
+ <template slot="header">
81
+ <div style="padding-left: 6px">机构</div>
82
+ </template>
83
+ </el-table-column>
84
+ <el-table-column prop="department" label="部门" show-overflow-tooltip>
85
+ <template slot="header">
86
+ <div style="padding-left: 6px">部门</div>
87
+ </template>
88
+ </el-table-column>
89
+ <el-table-column prop="position" label="岗位" show-overflow-tooltip>
90
+ <template slot="header">
91
+ <div style="padding-left: 6px">岗位</div>
92
+ </template>
93
+ </el-table-column>
94
+ <el-table-column prop="city" label="城市" show-overflow-tooltip>
95
+ <template slot="header">
96
+ <div style="padding-left: 6px">城市</div>
97
+ </template>
98
+ </el-table-column>
99
+ <el-table-column
100
+ v-for="item in shiftPlan"
101
+ :key="item.tdDate"
102
+ :prop="'shift_' + item.day"
103
+ :label="item.day + '(' + item.week + ')'"
104
+ :width="isShiftChange ? 100 : 50"
105
+ >
106
+ <template slot="header" slot-scope="scope">
107
+ <div class="flex">
108
+ <div style="border-bottom: 1px solid #ccc; padding-left: 6px">
109
+ {{ item.day }}
110
+ </div>
111
+ <div style="padding-left: 6px">
112
+ {{ item.week }}
113
+ <i
114
+ v-if="isShiftChange && item.editFlag !== '0'"
115
+ class="el-icon-edit"
116
+ ></i>
117
+ </div>
118
+ </div>
119
+ </template>
120
+ <template slot-scope="scope">
121
+ <shiftItem
122
+ :scope="scope"
123
+ :shiftColor="shiftColor"
124
+ :isShiftChange="isShiftChange"
125
+ :columnItem="item"
126
+ />
127
+ <!-- <div>
128
+ <div class="tag" :style="`background-color: ${handleShiftColor(scope, 'color')};`">{{
129
+ handleShiftColor(scope,'font') }}</div>
130
+ </div> -->
131
+ </template>
132
+ </el-table-column>
133
+ </el-table>
134
+ <div class="footer">
135
+ <div class="left">
136
+ <div v-for="item in shiftColor" :key="item.shiftId" class="flex">
137
+ <div class="tag" :style="`background-color: ${item.color};`">
138
+ {{ item.font }}
139
+ </div>
140
+ <div>{{ item.shiftName }}</div>
141
+ </div>
142
+ </div>
143
+ <div class="right">
144
+ <el-pagination
145
+ @size-change="handleSizeChange"
146
+ @current-change="handleCurrentChange"
147
+ :current-page="currentPage"
148
+ :page-sizes="[10, 20, 30, 100]"
149
+ :page-size="10"
150
+ layout="total, sizes, prev, pager, next"
151
+ :total="total"
152
+ >
153
+ </el-pagination>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ </template>
158
+
159
+ <script>
160
+ import { getTableDataApi, getShiftPlanApi, getShiftColorApi } from "./data";
161
+ import shiftItem from "./shiftItem.vue";
162
+ import { dialogFn } from "../dialogFnJsx/index.js";
163
+ import attendanceCycle from "../components/attendanceCycle/index.vue";
164
+ import attendanceGroup from "../components/attendanceGroup/index.vue";
165
+ import batchScheduling from "./batchScheduling";
166
+ import batchShiftChange from "./batchShiftChange";
167
+ import shiftChangeRecord from "./shiftChangeRecord";
168
+ export default {
169
+ components: {
170
+ shiftItem,
171
+ },
172
+ data() {
173
+ return {
174
+ tableData: [],
175
+ shiftPlan: [],
176
+ shiftColor: [],
177
+ isShiftChange: false,
178
+ currentPage: 4,
179
+ total: 10000,
180
+ attendanceCycleByMonthObj: {
181
+ name: "2025年度4月",
182
+ id: 1,
183
+ startDate: "2025-04-01",
184
+ endDate: "2025-04-30",
185
+ },
186
+ attendanceGroupObj: {
187
+ name: "2025年度4月",
188
+ id: 1,
189
+ startDate: "2025-04-01",
190
+ endDate: "2025-04-30",
191
+ },
192
+ loading: false,
193
+ showOnlyUnscheduled: false,
194
+ multipleSelection: [],
195
+ };
196
+ },
197
+ created() {
198
+ this.getTableData();
199
+ this.getShiftPlan();
200
+ this.getShiftColor();
201
+ },
202
+ methods: {
203
+ handleSizeChange(val) {
204
+ console.log(`每页 ${val} 条`);
205
+ },
206
+ handleCurrentChange(val) {
207
+ console.log(`当前页: ${val}`);
208
+ },
209
+ getTableData() {
210
+ this.loading = true;
211
+ getTableDataApi().then((res) => {
212
+ this.tableData = res;
213
+ this.loading = false;
214
+ console.log(this.tableData, "this.tableData");
215
+ });
216
+ },
217
+ getShiftPlan() {
218
+ getShiftPlanApi().then((res) => {
219
+ this.shiftPlan = res;
220
+ });
221
+ },
222
+ getShiftColor() {
223
+ getShiftColorApi().then((res) => {
224
+ this.shiftColor = res;
225
+ });
226
+ },
227
+ handleShiftColor({ row, column }, keyName) {
228
+ const property = column.property || "";
229
+ const list = property.split("_") || [];
230
+ const key = list[1];
231
+ let shiftId;
232
+ if (key) {
233
+ shiftId = row.shiftPlanDetails[key].shiftId;
234
+ const sc = this.shiftColor.find((item) => item.shiftId === shiftId);
235
+ return sc[keyName];
236
+ }
237
+ },
238
+ shiftChangeForSelected() {
239
+ if (!this.multipleSelection.length) {
240
+ return this.$message.error("请选择要修改的行");
241
+ }
242
+ this.tableData = this.multipleSelection;
243
+ this.isShiftChange = true;
244
+ this.clearSelection();
245
+ this.multipleSelection = [];
246
+ console.log(this.tableData, "tableData");
247
+ },
248
+ openAttendanceCycle() {
249
+ const config = {
250
+ props: {
251
+ title: "选择考勤周期",
252
+ width: "50%",
253
+ },
254
+ slots: {
255
+ default: (
256
+ <attendanceCycle
257
+ close={() => close()}
258
+ setData={(row) => this.attendanceCycleChange(row)}
259
+ />
260
+ ),
261
+ },
262
+ };
263
+ let { close } = this.$dialogFnByJsx(config);
264
+ },
265
+ openAttendanceGroup() {
266
+ const config = {
267
+ props: {
268
+ title: "选择考勤组",
269
+ width: "50%",
270
+ },
271
+ slots: {
272
+ default: (
273
+ <attendanceGroup
274
+ close={() => close()}
275
+ setData={(row) => this.attendanceGroupChange(row)}
276
+ />
277
+ ),
278
+ },
279
+ };
280
+ let { close } = this.$dialogFnByJsx(config);
281
+ },
282
+ attendanceCycleChange(row) {
283
+ this.attendanceCycleByMonthObj = row;
284
+ this.getTableData();
285
+ this.getShiftPlan();
286
+ this.getShiftColor();
287
+ },
288
+ attendanceGroupChange(row) {
289
+ this.attendanceGroupObj = row;
290
+ },
291
+
292
+ handleSelectionChange(val) {
293
+ this.multipleSelection = val;
294
+ },
295
+ clearSelection() {
296
+ this.$refs.multipleTable.clearSelection();
297
+ },
298
+ saveShiftChange() {
299
+ console.log(this.tableData, "this.tableData");
300
+ this.closeShiftChange();
301
+ },
302
+ closeShiftChange() {
303
+ this.isShiftChange = false;
304
+ this.getTableData();
305
+ },
306
+
307
+ openBatchScheduling() {
308
+ const config = {
309
+ props: {
310
+ title: "批量排班",
311
+ width: "80%",
312
+ top: "20px",
313
+ },
314
+ slots: {
315
+ default: (
316
+ <batchScheduling
317
+ close={() => close()}
318
+ />
319
+ ),
320
+ },
321
+ };
322
+ let { close } = this.$dialogFnByJsx(config);
323
+ },
324
+
325
+ openBatchShiftChange() {
326
+ const config = {
327
+ props: {
328
+ title: "批量调班",
329
+ width: "80%",
330
+ top: "20px",
331
+ },
332
+ slots: {
333
+ default: (
334
+ <batchShiftChange
335
+ close={() => close()}
336
+ />
337
+ ),
338
+ },
339
+ };
340
+ let { close } = this.$dialogFnByJsx(config);
341
+ },
342
+
343
+ openShiftChangeRecord() {
344
+ if(this.multipleSelection.length === 0) return this.$message.error("请选择");
345
+ const config = {
346
+ props: {
347
+ title: "调班记录",
348
+ width: "80%",
349
+ },
350
+ slots: {
351
+ default: (
352
+ <shiftChangeRecord
353
+ close={() => close()}
354
+ personnelList = {this.multipleSelection}
355
+ />
356
+ ),
357
+ },
358
+ };
359
+ let {close} = this.$dialogFnByJsx(config);
360
+ },
361
+ },
362
+ };
363
+ </script>
364
+
365
+ <style lang="less">
366
+ .employeeSchedulingManagement {
367
+ .header {
368
+ display: flex;
369
+ justify-content: space-between;
370
+ align-items: center;
371
+ height: 40px;
372
+ .left {
373
+ display: flex;
374
+ align-items: center;
375
+ }
376
+ }
377
+
378
+ .el-table {
379
+ .el-table__header-wrapper {
380
+ .el-table__cell {
381
+ padding-top: 6px;
382
+ padding-bottom: 6px;
383
+ }
384
+
385
+ .cell {
386
+ padding-left: 0 !important;
387
+ padding-right: 0 !important;
388
+ }
389
+ }
390
+
391
+ .tag {
392
+ border-radius: 4px;
393
+ display: flex;
394
+ justify-content: center;
395
+ align-items: center;
396
+ height: 20px;
397
+ color: #fff;
398
+ }
399
+ }
400
+ .footer {
401
+ display: flex;
402
+ justify-content: space-between;
403
+ align-items: center;
404
+ height: 40px;
405
+ .right {
406
+ margin-left: 20px;
407
+ }
408
+ .left {
409
+ flex: 1;
410
+ display: flex;
411
+ align-items: center;
412
+ overflow: hidden;
413
+ &:hover {
414
+ overflow-x: auto;
415
+ margin-top: 15px;
416
+ }
417
+ .flex {
418
+ display: flex;
419
+ align-items: center;
420
+ flex-shrink: 0;
421
+ margin-right: 20px;
422
+ }
423
+ .tag {
424
+ margin-right: 6px;
425
+ padding: 0 10px;
426
+ height: 20px;
427
+ border-radius: 4px;
428
+ display: flex;
429
+ justify-content: center;
430
+ align-items: center;
431
+ flex-shrink: 0;
432
+ }
433
+ }
434
+ }
435
+ }
436
+ </style>
@@ -0,0 +1,250 @@
1
+ <template>
2
+ <div class="shiftChangeRecord">
3
+ <div class="header">
4
+ <div class="left">
5
+ <el-image
6
+ style="width: 60px; height: 60px; border-radius: 50%"
7
+ src=""
8
+ ></el-image>
9
+ </div>
10
+ <div class="right">
11
+ <div class="top">
12
+ <div class="name">许XX(男)</div>
13
+ <div class="id">011111</div>
14
+ </div>
15
+ <div class="bottom">
16
+ <div>董事长</div>
17
+ <div>董事长 总裁室 xxxx</div>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <div class="content">
22
+ <div class="content-header">
23
+ <div class="left">
24
+ <el-input
25
+ size="mini"
26
+ placeholder="请输入内容"
27
+ :value="attendanceCycleObj.monthName"
28
+ class="input-with-select"
29
+ style="margin-right: 10px; width: 200px"
30
+ >
31
+ <el-button
32
+ slot="append"
33
+ icon="el-icon-search"
34
+ @click="openAttendanceCycle"
35
+ ></el-button>
36
+ </el-input>
37
+ <el-input
38
+ style="width: 120px"
39
+ size="mini"
40
+ :value="attendanceCycleObj.name"
41
+ readonly
42
+ />
43
+ <span style="margin: 0 5px">至</span>
44
+ <el-input
45
+ style="width: 120px"
46
+ size="mini"
47
+ :value="attendanceCycleObj.name"
48
+ readonly
49
+ />
50
+ </div>
51
+ <div class="right">
52
+ <el-button
53
+ type=""
54
+ size="mini"
55
+ :disabled="previousItemDisabled"
56
+ @click="onPreviousItem"
57
+ >上一条</el-button
58
+ ><el-button
59
+ type=""
60
+ size="mini"
61
+ :disabled="nextItemDisabled"
62
+ @click="onNextItem"
63
+ >下一条</el-button
64
+ >
65
+ <el-select
66
+ style="width: 120px; margin-left: 10px"
67
+ size="mini"
68
+ v-model="personnelId"
69
+ >
70
+ <el-option
71
+ v-for="item in personnelList"
72
+ :key="item.employeeId"
73
+ :label="item.name"
74
+ :value="item.employeeId"
75
+ ></el-option>
76
+ </el-select>
77
+ </div>
78
+ </div>
79
+ <div>
80
+ <el-table v-loading="tableLoading" size="mini" :data="tableData" style="width: 100%" border>
81
+ <el-table-column label="工作日期" prop="workDate"></el-table-column>
82
+ <el-table-column
83
+ label="调整前班次"
84
+ prop="previousShift"
85
+ ></el-table-column>
86
+ <el-table-column label="调整后班次" prop="newShift"></el-table-column>
87
+ <el-table-column
88
+ label="调整后班次"
89
+ prop="dataSource"
90
+ ></el-table-column>
91
+ </el-table>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </template>
96
+
97
+ <script>
98
+ import attendanceCycle from "../../components/attendanceCycle/index.vue";
99
+ import { getShiftChangeRecordTableDataApi } from "../data";
100
+ export default {
101
+ // 调班记录
102
+ name: "shiftChangeRecord",
103
+ props: {
104
+ close: {
105
+ type: Function,
106
+ default: () => {},
107
+ },
108
+ personnelList: {
109
+ type: Array,
110
+ default: () => [],
111
+ },
112
+ },
113
+ data() {
114
+ return {
115
+ attendanceCycleObj: {
116
+ name: "2025年度4月",
117
+ id: 1,
118
+ startDate: "2025-04-01",
119
+ endDate: "2025-04-30",
120
+ },
121
+ personnelId: "",
122
+ tableData: [],
123
+ nextItemDisabled: false,
124
+ previousItemDisabled: false,
125
+ tableLoading: false,
126
+ };
127
+ },
128
+ watch: {
129
+ personnelId(val) {
130
+ this.getTableData();
131
+ this.nextItemDisabled = false;
132
+ this.previousItemDisabled = false;
133
+ const index = this.personnelList.findIndex(
134
+ (item) => item.employeeId === val
135
+ );
136
+ if (index === -1) return;
137
+ if (index === 0) this.previousItemDisabled = true;
138
+ if (index === this.personnelList.length - 1) this.nextItemDisabled = true;
139
+ },
140
+ },
141
+ mounted() {
142
+ this.getTableData();
143
+ this.initPersonneId();
144
+ },
145
+ methods: {
146
+ initPersonneId() {
147
+ if (this.personnelList.length)
148
+ this.personnelId = this.personnelList[0].employeeId;
149
+ },
150
+ openAttendanceCycle() {
151
+ const config = {
152
+ props: {
153
+ title: "选择考勤周期",
154
+ width: "80%",
155
+ },
156
+ slots: {
157
+ default: (
158
+ <attendanceCycle
159
+ close={() => close()}
160
+ setData={(row) => this.attendanceCycleChange(row)}
161
+ />
162
+ ),
163
+ },
164
+ };
165
+ let { close } = this.$dialogFnByJsx(config);
166
+ },
167
+ attendanceCycleChange(row) {
168
+ this.attendanceCycleByMonthObj = row;
169
+ this.getTableData();
170
+ this.getShiftPlan();
171
+ this.getShiftColor();
172
+ },
173
+ async getTableData() {
174
+ try {
175
+ this.tableLoading = true;
176
+ const res = await getShiftChangeRecordTableDataApi();
177
+ this.tableData = res;
178
+ this.tableLoading = false;
179
+ } catch (error) {
180
+ this.tableLoading = false;
181
+ }
182
+ },
183
+ onPreviousItem() {
184
+ const index = this.personnelList.findIndex(
185
+ (item) => item.employeeId === this.personnelId
186
+ );
187
+ console.log(index, "onPreviousItem");
188
+
189
+ if (index > 0) {
190
+ this.personnelId = this.personnelList[index - 1].employeeId;
191
+ }
192
+ },
193
+ onNextItem() {
194
+ const index = this.personnelList.findIndex(
195
+ (item) => item.employeeId === this.personnelId
196
+ );
197
+ console.log(index, "onNextItem");
198
+
199
+ if (index < this.personnelList.length - 1) {
200
+ this.personnelId = this.personnelList[index + 1].employeeId;
201
+ }
202
+ },
203
+ },
204
+ };
205
+ </script>
206
+
207
+ <style lang="less">
208
+ .shiftChangeRecord {
209
+ .header {
210
+ display: flex;
211
+ border: 1px solid #ccc;
212
+ padding: 10px;
213
+ .left {
214
+ width: 60px;
215
+ margin-right: 10px;
216
+ }
217
+ .right {
218
+ width: 300px;
219
+ padding: 5px;
220
+ .top {
221
+ display: flex;
222
+ height: 24px;
223
+ align-items: center;
224
+ .name {
225
+ font-size: 16px;
226
+ font-weight: 600;
227
+ }
228
+ }
229
+ .bottom {
230
+ display: flex;
231
+ height: 24px;
232
+ align-items: center;
233
+ }
234
+ }
235
+ }
236
+ .content {
237
+ .content-header {
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: space-between;
241
+ height: 40px;
242
+ margin: 10px 0;
243
+ .left {
244
+ display: flex;
245
+ align-items: center;
246
+ }
247
+ }
248
+ }
249
+ }
250
+ </style>