From aae0b49229d8798a2cc31a8449092e2db62e2407 Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期四, 26 三月 2026 11:26:41 +0800
Subject: [PATCH] 绩效管理:人员考勤功能模块
---
src/views/system/user/index.vue | 55 +
src/api/system/user.js | 8
src/views/performance/attendance/index.vue | 644 +++++++++++++++++++++++++++++
src/api/system/post.js | 8
src/views/CNAS/resourceDemand/device/component/acquisitionConfig.vue | 2
package.json | 1
src/views/business/rawMaterialInspection/index.vue | 29 +
src/views/performance/class/index.vue | 85 +--
src/views/business/unpass/components/OAProcess.vue | 2
src/views/performance/attendance/components/staffClockInRecord.vue | 395 +++++++++++++++++
src/api/performance/attendance.js | 66 +++
11 files changed, 1,223 insertions(+), 72 deletions(-)
diff --git a/package.json b/package.json
index 6d2ff7c..3deefe9 100644
--- a/package.json
+++ b/package.json
@@ -44,6 +44,7 @@
"big.js": "^6.2.2",
"clipboard": "2.0.8",
"core-js": "3.37.1",
+ "dayjs": "^1.11.20",
"dom-to-image": "^2.6.0",
"echarts": "5.4.0",
"element-resize-detector": "^1.2.4",
diff --git a/src/api/performance/attendance.js b/src/api/performance/attendance.js
new file mode 100644
index 0000000..653f30b
--- /dev/null
+++ b/src/api/performance/attendance.js
@@ -0,0 +1,66 @@
+// 鐝鐩稿叧鎺ュ彛
+
+import request from "@/utils/request";
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-鏌ヨ浜哄憳鎵撳崱璁板綍
+export function getClockInRecord(query) {
+ return request({
+ url: "/staff/attendance/getClockInRecord",
+ method: "get",
+ params: query,
+ });
+}
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-鍒嗛〉鏌ヨ鑰冨嫟璁板綍
+export function pageAttendanceRecord(query) {
+ return request({
+ url: "/staff/attendance/pageAttendanceRecord",
+ method: "get",
+ params: query,
+ });
+}
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-鏍¢獙閫夋嫨鐨勮�冨嫟鏃堕棿鏄惁瀛樺湪鍚屼竴浜哄憳鐨勮�冨嫟璁板綍
+export function checkDutyDate(query) {
+ return request({
+ url: "/staff/attendance/checkDutyDate",
+ method: "get",
+ params: query,
+ });
+}
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-淇濆瓨鎴栨洿鏂拌�冨嫟璁板綍
+export function saveOrUpdateStaffAttendanceTrackingRecord(data) {
+ return request({
+ url: "/staff/attendance/saveOrUpdateStaffAttendanceTrackingRecord",
+ method: "post",
+ data: data,
+ });
+}
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-鍒犻櫎鑰冨嫟璁板綍
+export function removeStaffAttendanceTrackingRecord(ids) {
+ return request({
+ url: "/staff/attendance/removeStaffAttendanceTrackingRecord",
+ method: "delete",
+ data:ids
+ });
+}
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-鍚屾鑰冨嫟璁板綍
+export function syncAttendanceRecord(query) {
+ return request({
+ url: "/staff/attendance/syncAttendanceRecord",
+ method: "get",
+ params: query
+ });
+}
+
+// 缁╂晥绠$悊-浜哄憳鑰冨嫟-淇敼杩涘嚭璁板綍鐘舵��
+export function changeEnableReport(data) {
+ return request({
+ url: "/staff/attendance/changeEnableReport",
+ method: "post",
+ data: data
+ });
+}
diff --git a/src/api/system/post.js b/src/api/system/post.js
index 1a8e9ca..8c25bc7 100644
--- a/src/api/system/post.js
+++ b/src/api/system/post.js
@@ -9,6 +9,14 @@
})
}
+// 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+export function optionSelect() {
+ return request({
+ url: '/system/post/optionSelect',
+ method: 'get'
+ })
+}
+
// 鏌ヨ宀椾綅璇︾粏
export function getPost(postId) {
return request({
diff --git a/src/api/system/user.js b/src/api/system/user.js
index ad8d3ce..850ab66 100644
--- a/src/api/system/user.js
+++ b/src/api/system/user.js
@@ -195,3 +195,11 @@
params: query,
});
}
+
+// 鑾峰彇鐢ㄦ埛鍒楄〃
+export function selectAllUser() {
+ return request({
+ url: "/system/newUser/selectAllUser",
+ method: "get",
+ });
+}
diff --git a/src/views/CNAS/resourceDemand/device/component/acquisitionConfig.vue b/src/views/CNAS/resourceDemand/device/component/acquisitionConfig.vue
index 2abdc50..5f0165c 100644
--- a/src/views/CNAS/resourceDemand/device/component/acquisitionConfig.vue
+++ b/src/views/CNAS/resourceDemand/device/component/acquisitionConfig.vue
@@ -274,6 +274,8 @@
{ label: "txt", value: ".txt" },
{ label: "mysql", value: ".mysql" },
{ label: "mqtt", value: ".mqtt" },
+ { label: "sqlserver", value: ".sqlserver" },
+ { label: "serialPort", value: ".serialPort" },
{ label: "png", value: ".png" }
],
spanList: [],
diff --git a/src/views/business/rawMaterialInspection/index.vue b/src/views/business/rawMaterialInspection/index.vue
index 7563e12..dfe0014 100644
--- a/src/views/business/rawMaterialInspection/index.vue
+++ b/src/views/business/rawMaterialInspection/index.vue
@@ -5,8 +5,7 @@
<el-row>
<el-form-item label="IFS鍩�" prop="contract">
<el-select @keyup.enter.native="refreshTable" v-model="componentData.contract" clearable placeholder="璇烽�夋嫨" size="small">
- <el-option label="ZTNS" value="ZTNS"/>
- <el-option label="KJNS" value="KJNS"/>
+ <el-option v-for="(item,index) in contractList" :key="index" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
<el-form-item label="鎵瑰彿" prop="updateBatchNo">
@@ -119,12 +118,15 @@
:visible.sync="declareDialogVisible" width="800px" @close="resetFormData">
<el-form ref="declareObj" :inline="true" :model="declareObj" :rules="declareObjRules" label-width="130px"
label-position="right">
- <el-form-item class="declareObj-form-item" label="IFS鍩�:" prop="contract" style="width: calc(50% - 54px)">
- <el-tag :type="declareObj.contract==='ZTNS'?'':'success'">{{declareObj.contract}}</el-tag>
- </el-form-item>
<el-form-item class="declareObj-form-item" label="璁㈠崟鍙�:" prop="orderNo">
<el-input v-model="declareObj.orderNo" :disabled="declareType !== 'add'" class="addObj-info" clearable
- placeholder="" size="small"></el-input>
+ placeholder="" size="small"></el-input>
+ </el-form-item>
+ <el-form-item class="declareObj-form-item" label="IFS鍩�:" prop="contract">
+ <el-select v-model="declareObj.contract" v-if="declareType === 'add'" clearable size="small">
+ <el-option v-for="(item,index) in contractList" :key="index" :label="item.label" :value="item.value"/>
+ </el-select>
+ <el-tag v-else :type="declareObj.contract==='ZTNS'?'':'success'">{{declareObj.contract}}</el-tag>
</el-form-item>
<el-form-item class="declareObj-form-item" label="闆朵欢鍙�:" prop="partNo">
<el-input v-model="declareObj.partNo" :disabled="declareType !== 'add'" class="addObj-info" clearable
@@ -747,6 +749,16 @@
upLoading: false,
orderTypeList: [],
materialPropList: [],
+ contractList:[
+ {
+ label:"ZTNS",
+ value:"ZTNS"
+ },
+ {
+ label:"KJNS",
+ value:"KJNS"
+ },
+ ]
}
},
mounted() {
@@ -1110,7 +1122,9 @@
id: this.declareObj.id,
updateBatchNo: this.declareObj.updateBatchNo,
orderType: this.declareObj.orderType,
- materialProp: this.declareObj.materialProp
+ materialProp: this.declareObj.materialProp,
+ partNo: this.declareObj.partNo,
+ contract: this.declareObj.contract
}).then(res => {
if (res.code === 200) {
this.declareDialogVisible = false
@@ -1195,6 +1209,7 @@
buyUnitMeas: '', // 鍗曚綅
isExpire: '', // 鍗曚綅
orderType: null, // 閿�鍞鍗曞垎绫�
+ materialProp: null, // 鐗╂枡灞炴��
}
}
},
diff --git a/src/views/business/unpass/components/OAProcess.vue b/src/views/business/unpass/components/OAProcess.vue
index eba813d..4becedd 100644
--- a/src/views/business/unpass/components/OAProcess.vue
+++ b/src/views/business/unpass/components/OAProcess.vue
@@ -105,7 +105,7 @@
},
{
id: 6,
- name: "6璐ㄩ噺閮�",
+ name: "6璐ㄩ噺閮ㄥ鐞嗘剰瑙�",
info: "",
time: "",
operator: "",
diff --git a/src/views/performance/attendance/components/staffClockInRecord.vue b/src/views/performance/attendance/components/staffClockInRecord.vue
new file mode 100644
index 0000000..c1860c2
--- /dev/null
+++ b/src/views/performance/attendance/components/staffClockInRecord.vue
@@ -0,0 +1,395 @@
+<script>
+import {getClockInRecord,changeEnableReport} from '@/api/performance/attendance'
+
+export default {
+ name: "staffClockInRecord",
+ props: {
+ queryParams: {
+ type: Object,
+ default: () => ({
+ personCode:null,//浜哄憳缂栧彿
+ swingDate:null,//鍒峰崱鏃堕棿
+ shiftId:null//鐝id
+ }),
+ },
+ },
+ data() {
+ return {
+ loading: false,
+ tableData: [],
+ //杩涘嚭闂ㄧ被鍨嬪垪琛�
+ enterOrExitList:[
+ {
+ label:'杩涢棬',
+ value:1
+ },
+ {
+ label:'鍑洪棬',
+ value:2
+ },
+ {
+ label:'杩�/鍑洪棬',
+ value:3
+ }
+ ],
+ //寮�闂ㄧ被鍨嬪垪琛�
+ openTypeList:[
+ {
+ "value": 42,
+ "label": "鍚堟硶瀵嗙爜寮�闂�"
+ },
+ {
+ "value": 43,
+ "label": "闈炴硶瀵嗙爜寮�闂�"
+ },
+ {
+ "value": 45,
+ "label": "鍚堟硶鎸囩汗寮�闂�"
+ },
+ {
+ "value": 46,
+ "label": "闈炴硶鎸囩汗寮�闂�"
+ },
+ {
+ "value": 48,
+ "label": "杩滅▼寮�闂�"
+ },
+ {
+ "value": 49,
+ "label": "鎸夐挳寮�闂�"
+ },
+ {
+ "value": 50,
+ "label": "閽ュ寵寮�闂�"
+ },
+ {
+ "value": 51,
+ "label": "鍚堟硶鍒峰崱寮�闂�"
+ },
+ {
+ "value": 52,
+ "label": "闈炴硶鍒峰崱寮�闂�"
+ },
+ {
+ "value": 53,
+ "label": "闂ㄧ浜嬩欢"
+ },
+ {
+ "value": 54,
+ "label": "寮傚父寮�闂�"
+ },
+ {
+ "value": 55,
+ "label": "寮傚父鍏抽棬"
+ },
+ {
+ "value": 56,
+ "label": "姝e父鍏抽棬"
+ },
+ {
+ "value": 57,
+ "label": "姝e父寮�闂�"
+ },
+ {
+ "value": 59,
+ "label": "瀵硅璇锋眰浜嬩欢"
+ },
+ {
+ "value": 61,
+ "label": "浜鸿劯鍚堟硶寮�闂�"
+ },
+ {
+ "value": 62,
+ "label": "浜鸿劯闈炴硶寮�闂�"
+ },
+ {
+ "value": 1421,
+ "label": "RFID鏈夋簮鍚堟硶"
+ },
+ {
+ "value": 1422,
+ "label": "RFID鏃犳簮鍚堟硶"
+ },
+ {
+ "value": 1423,
+ "label": "RFID鏈夋簮闈炴硶"
+ },
+ {
+ "value": 1424,
+ "label": "RFID鏃犳簮闈炴硶"
+ },
+ {
+ "value": 1433,
+ "label": "榛戝悕鍗曚簨浠�"
+ },
+ {
+ "value": 1436,
+ "label": "浜鸿瘉鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1437,
+ "label": "浜鸿瘉闈炴硶寮�闂�"
+ },
+ {
+ "value": 1438,
+ "label": "浜鸿瘉鍜岃韩浠借瘉闈炴硶寮�闂�"
+ },
+ {
+ "value": 1439,
+ "label": "浜鸿瘉鍜岃韩浠借瘉鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1448,
+ "label": "RFID鎰熷簲浜嬩欢"
+ },
+ {
+ "value": 1449,
+ "label": "RFID闈炴硶鎰熷簲浜嬩欢"
+ },
+ {
+ "value": 1450,
+ "label": "RFID鎸夐敭浜嬩欢"
+ },
+ {
+ "value": 1451,
+ "label": "RFID闈炴硶鎸夐敭浜嬩欢"
+ },
+ {
+ "value": 1455,
+ "label": "鍏堝埛鍗″悗瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1456,
+ "label": "鍏堝埛鍗″悗瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1461,
+ "label": "鍒峰崱+鎸囩汗缁勫悎鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1462,
+ "label": "鍒峰崱+鎸囩汗缁勫悎闈炴硶寮�闂�"
+ },
+ {
+ "value": 1463,
+ "label": "澶氫汉鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1464,
+ "label": "澶氫汉闈炴硶寮�闂�"
+ },
+ {
+ "value": 1467,
+ "label": "浜哄憳缂栧彿+瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1468,
+ "label": "浜哄憳缂栧彿+瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1469,
+ "label": "浜鸿劯+瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1470,
+ "label": "浜鸿劯+瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1471,
+ "label": "鎸囩汗+瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1472,
+ "label": "鎸囩汗+瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1473,
+ "label": "鎸囩汗+浜鸿劯鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1474,
+ "label": "鎸囩汗+浜鸿劯闈炴硶寮�闂�"
+ },
+ {
+ "value": 1475,
+ "label": "鍒峰崱+浜鸿劯鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1476,
+ "label": "鍒峰崱+浜鸿劯闈炴硶寮�闂�"
+ },
+ {
+ "value": 1487,
+ "label": "鎸囩汗+浜鸿劯+瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1488,
+ "label": "鎸囩汗+浜鸿劯+瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1489,
+ "label": "鍒峰崱+浜鸿劯+瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1490,
+ "label": "鍒峰崱+浜鸿劯+瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1491,
+ "label": "鍒峰崱+鎸囩汗+瀵嗙爜鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1492,
+ "label": "鍒峰崱+鎸囩汗+瀵嗙爜闈炴硶寮�闂�"
+ },
+ {
+ "value": 1493,
+ "label": "鍗�+鎸囩汗+浜鸿劯缁勫悎鍚堟硶寮�闂�"
+ },
+ {
+ "value": 1494,
+ "label": "鍗�+鎸囩汗+浜鸿劯缁勫悎闈炴硶寮�闂�"
+ },
+ {
+ "value": 4603,
+ "label": "鍗�+鎸囩汗+浜鸿劯+瀵嗙爜缁勫悎鍚堟硶寮�闂�"
+ },
+ {
+ "value": 4604,
+ "label": "鍗�+鎸囩汗+浜鸿劯+瀵嗙爜缁勫悎闈炴硶寮�闂�"
+ },
+ {
+ "value": 4626,
+ "label": "浜鸿劯+瀹夊叏甯藉悎娉曞紑闂�"
+ },
+ {
+ "value": 4627,
+ "label": "浜鸿劯+瀹夊叏甯介潪娉曞紑闂�"
+ },
+ {
+ "value": 10001,
+ "label": "鍋ュ悍鐮佸悎娉曞紑闂�"
+ },
+ {
+ "value": 10002,
+ "label": "寮傚父鍋ュ悍鐮佸紑闂�"
+ }
+ ]
+ };
+ },
+ watch: {
+ queryParams: {
+ handler(newVal, oldVal) {
+ this.refreshTable();
+ },
+ deep: true,
+ },
+ },
+ created() {
+ this.refreshTable();
+ },
+ methods: {
+ changeEnableReport(row){
+ let data = {
+ id:row.id,
+ enableReport:row.enableReport
+ }
+ changeEnableReport(data).then(res=>{
+ if(res.code===200){
+ this.$message.success("鎿嶄綔鎴愬姛")
+ this.refreshTable()
+ }
+ })
+ },
+ formatterAttendanceType(value){
+ let label = "";
+ this.openTypeList.forEach(item=>{
+ if(item.value===value){
+ label = item.label
+ }
+ })
+ return label;
+ },
+ formatterEnterOrExitType(value){
+ let label = "";
+ this.enterOrExitList.forEach(item=>{
+ if(item.value===value){
+ label = item.label
+ }
+ })
+ return label;
+ },
+ getDataSourceTypeTag(type) {
+ const tagMap = {
+ 0: 'success',
+ 1: '',
+ };
+ return tagMap[type] || '';
+ },
+ getDataSourceTypeText(type) {
+ const textMap = {
+ 0: 'ICC鍚屾',
+ 1: '鎵嬪姩鏂板',
+ };
+ return textMap[type] || '鏈煡';
+ },
+ refreshTable() {
+ this.loading = true;
+ getClockInRecord({...this.queryParams}).then(res => {
+ this.tableData = res.data;
+ this.loading = false;
+ }).catch(() => {
+ this.loading = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="clock-in-record">
+ <div v-loading="loading">
+ <el-table
+ :data="tableData"
+ border
+ style="width: 100%"
+ height="300"
+ :header-cell-style="{textAlign:'center'}"
+ :cell-style="{textAlign:'center'}"
+ >
+ <el-table-column type="index" label="搴忓彿" width="60"></el-table-column>
+ <el-table-column label="鏄惁绾冲叆鑰冨嫟" prop="enableReport" width="120">
+ <template slot-scope="scope">
+ <el-switch
+ @change="changeEnableReport(scope.row)"
+ v-model="scope.row.enableReport"
+ active-color="#13ce66"
+ inactive-color="#ff4949">
+ </el-switch>
+ </template>
+ </el-table-column>
+ <el-table-column prop="personCode" label="宸ュ彿" min-width="150" width="150"></el-table-column>
+ <el-table-column prop="personName" label="濮撳悕" min-width="150" width="150"></el-table-column>
+ <el-table-column prop="deptName" label="閮ㄩ棬鍚嶇О" min-width="150" width="150"></el-table-column>
+ <el-table-column prop="cardNumber" label="鍗″彿" min-width="150" width="150"></el-table-column>
+ <el-table-column prop="swingTime" label="鍒峰崱鏃堕棿" min-width="180" width="180"></el-table-column>
+ <el-table-column prop="channelName" label="鑰冨嫟鐐归�氶亾鍚嶇О" min-width="180" width="180"></el-table-column>
+ <el-table-column prop="deviceName" label="鑰冨嫟璁惧鍚嶇О" min-width="150" width="150"></el-table-column>
+ <el-table-column prop="deviceCode" label="鑰冨嫟璁惧缂栫爜" min-width="150" width="150"></el-table-column>
+ <el-table-column prop="enterOrExit" label="杩涘嚭闂ㄧ被鍨�" min-width="150" width="150" :formatter="(row)=>formatterEnterOrExitType(row.enterOrExit)"></el-table-column>
+ <el-table-column prop="openType" label="寮�闂ㄧ被鍨�" min-width="150" width="150" :formatter="(row)=>formatterAttendanceType(row.openType)"></el-table-column>
+ <el-table-column prop="isSync" label="鏁版嵁鏉ユ簮" min-width="150" width="150">
+ <template slot-scope="scope">
+ <el-tag :type="getDataSourceTypeTag(scope.row.isSync)">
+ {{ getDataSourceTypeText(scope.row.isSync) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+</template>
+
+<style scoped lang="scss">
+
+</style>
diff --git a/src/views/performance/attendance/index.vue b/src/views/performance/attendance/index.vue
new file mode 100644
index 0000000..3726bc0
--- /dev/null
+++ b/src/views/performance/attendance/index.vue
@@ -0,0 +1,644 @@
+<template>
+ <div class="attendance-page">
+ <div class="search">
+ <div class="search_thing">
+ <div class="search_input">
+ <el-date-picker
+ v-model="dateRange"
+ type="datetimerange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ :default-time="['00:00:00', '23:59:59']"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ style="width: 340px"
+ size="small"
+ @change="refreshTable"
+ ></el-date-picker>
+ </div>
+ </div>
+ <div class="search_thing">
+ <div class="search_input">
+ <el-input
+ v-model="queryParams.keyword"
+ placeholder="宸ュ彿鎴栧憳宸ュ悕绉�"
+ size="small"
+ style="width: 200px"
+ clearable
+ @keyup.enter.native="refreshTable"
+ ></el-input>
+ </div>
+ </div>
+ <div class="search_thing">
+ <el-button size="mini" type="primary" @click="refreshTable()"
+ >鏌� 璇�</el-button
+ >
+ <el-button size="mini" @click="resetQuery">閲嶇疆</el-button>
+ <el-button size="mini" type="primary" @click="openAddAttendanceDialog()">鎵嬪姩鏂板</el-button>
+ <el-button size="mini" type="success" @click="openSyncAttendanceDialog()">鍚屾鑰冨嫟璁板綍</el-button>
+ </div>
+ </div>
+ <div class="container">
+ <div v-loading="loading">
+ <el-table
+ :data="tableData"
+ border
+ :height="tableHeight"
+ style="width: 100%"
+ :header-cell-style="{textAlign:'center'}"
+ :cell-style="{textAlign:'center'}"
+ >
+ <el-table-column type="index" label="搴忓彿" width="60"></el-table-column>
+ <el-table-column prop="personCode" label="宸ュ彿" min-width="120" width="120"></el-table-column>
+ <el-table-column prop="personName" label="濮撳悕" min-width="120" width="120"></el-table-column>
+ <el-table-column prop="deptName" label="閮ㄩ棬鍚嶇О" min-width="120" width="120"></el-table-column>
+ <el-table-column prop="shiftId" label="鐝绫诲瀷" min-width="120" width="120">
+ <template slot-scope="scope">
+ <el-tag :type="getDictTypeByShift(scope.row.shiftId)">{{ getShiftByDic(scope.row.shiftId) }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="result" label="鑰冨嫟缁撴灉" min-width="120" width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="getResultTag(scope.row.result)" :type="getResultTag(scope.row.result).type">{{getResultTag(scope.row.result).label}}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="swingDate" label="鑰冨嫟鏃堕棿" min-width="150" width="150"></el-table-column>
+ <el-table-column label="绛惧叆/绛惧嚭鎯呭喌">
+ <el-table-column prop="workDateTime" label="涓婄彮鏃堕棿" min-width="160" width="160">
+ <template slot-scope="scope">
+ <el-tag type="success" v-if="scope.row.workDateTime && scope.row.workClockInState===1">{{ scope.row.workDateTime }}</el-tag>
+ <el-tag type="danger" v-else-if="scope.row.workDateTime && scope.row.workClockInState===0">{{ scope.row.workDateTime }}</el-tag>
+ <span v-else>{{ scope.row.workDateTime }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="offWorkDateTime" label="涓嬬彮鏃堕棿" min-width="160" width="160">
+ <template slot-scope="scope">
+ <el-tag type="success" v-if="scope.row.offWorkDateTime && scope.row.offClockInState===1">{{ scope.row.offWorkDateTime }}</el-tag>
+ <el-tag type="danger" v-else-if="scope.row.offWorkDateTime && scope.row.offClockInState===0">{{ scope.row.offWorkDateTime }}</el-tag>
+ <span v-else>{{ scope.row.offWorkDateTime }}</span>
+ </template>
+ </el-table-column>
+ </el-table-column>
+ <el-table-column label="鑰冨嫟鏃堕暱(h)">
+ <el-table-column prop="plannedWorkHours" label="搴斿嫟鏃堕暱" min-width="80" width="80"></el-table-column>
+ <el-table-column prop="actualWorkHours" label="瀹為檯鏃堕暱" min-width="80" width="80"></el-table-column>
+ <el-table-column prop="absenceWorkHours" label="缂哄嫟鏃堕暱" min-width="80" width="80"></el-table-column>
+ </el-table-column>
+ <el-table-column prop="isSync" label="鏁版嵁鏉ユ簮" min-width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="scope.row.isSync===0" type="success">ICC鍚屾</el-tag>
+ <el-tag v-else-if="scope.row.isSync===1" type="info">鎵嬪姩鏂板</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="createUser" label="鍒涘缓浜�" min-width="150" width="150" :formatter="(row)=>formatterUserName(row.createUser)"></el-table-column>
+ <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" min-width="180" width="180"></el-table-column>
+ <el-table-column prop="updateUser" label="鏇存柊浜�" min-width="150" width="150" :formatter="(row)=>formatterUserName(row.updateUser)"></el-table-column>
+ <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" min-width="180" width="180"></el-table-column>
+ <el-table-column fixed="right" width="180" label="鎿嶄綔">
+ <template slot-scope="scope">
+ <el-button type="text" @click="openClockInDialog(scope.row)">杩涘嚭璁板綍</el-button>
+ <el-button :disabled="scope.row.isSync===0" type="text" @click="openAddAttendanceDialog(scope.row)">缂栬緫</el-button>
+ <el-button :disabled="scope.row.isSync===0" type="text" class="remove-btn" @click="confirmRemoveRecord(scope.row)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination
+ :total="pagination.total"
+ :page.sync="pagination.current"
+ :limit.sync="pagination.size"
+ @pagination="handlePageChange"
+ />
+ </div>
+ </div>
+ <el-dialog
+ title="杩涘嚭璁板綍"
+ :visible.sync="dialogVisible"
+ width="60%">
+ <staff-clock-in-record :key="Math.random()" :query-params="clockInQueryParams" ></staff-clock-in-record>
+ </el-dialog>
+ <el-dialog
+ :title="attendanceForm.id?'缂栬緫鑰冨嫟璁板綍':'鏂板鑰冨嫟璁板綍'"
+ :visible.sync="addAttendanceVisible"
+ @closed="closeAttendanceDialog"
+ width="50%">
+ <el-form ref="attendanceForm" style="margin-top:20px" :model="attendanceForm" :rules="attendanceRule" label-position="right" label-width="100px">
+ <div>
+ <el-divider content-position="left">鍩烘湰淇℃伅</el-divider>
+ <el-row >
+ <el-col :span="12">
+ <el-form-item label="宸ュ彿" prop="personCode">
+ <el-input size="small" v-model="attendanceForm.personCode" disabled></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="濮撳悕" prop="personName">
+ <el-select size="small" style="width:100%" v-model="attendanceForm.personName" placeholder="璇烽�夋嫨鍛樺伐濮撳悕" @change="selectedPersonName" clearable>
+ <el-option v-for="(item,index) in userList" :key="index" :label="item.name" :value="item.name"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row >
+ <el-col :span="12">
+ <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName">
+ <el-input size="small" v-model="attendanceForm.deptName" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" clearable></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鑰冨嫟鏃堕棿" prop="swingDate">
+ <el-date-picker size="small" clearable style="width:100%" type="date" placeholder="璇烽�夋嫨鏃ユ湡" value-format="yyyy-MM-dd" v-model="attendanceForm.swingDate" @change="checkDutyDate"></el-date-picker>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row >
+ <el-col :span="12">
+ <el-form-item label="鐝绫诲瀷" prop="shiftId">
+ <el-select disabled size="small" style="width:100%" v-model="attendanceForm.shiftId" placeholder="璇烽�夋嫨鐝绫诲瀷" clearable>
+ <el-option v-for="(item,index) in dailyTypeList" :key="index" :label="item.dictLabel" :value="item.dictValue"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+<!-- <el-form-item label="鑰冨嫟缁撴灉" prop="result">-->
+<!-- <el-select size="small" style="width:100%" clearable v-model="attendanceForm.result" placeholder="璇烽�夋嫨鑰冨嫟缁撴灉">-->
+<!-- <el-option v-for="(item,index) in resultList" :key="index" :label="item.label" :value="item.value"/>-->
+<!-- </el-select>-->
+<!-- </el-form-item>-->
+ </el-col>
+ </el-row>
+ <el-divider content-position="left">绛惧叆/绛惧嚭鎯呭喌</el-divider>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="涓婄彮鏃堕棿" prop="workTime">
+ <el-time-picker
+ style="width:100%"
+ value-format="HH:mm"
+ v-model="attendanceForm.workDateTime"
+ format="HH:mm"
+ placeholder="涓婄彮鏃堕棿">
+ </el-time-picker>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓嬬彮鏃堕棿" prop="offWorkTime">
+ <el-time-picker
+ style="width:100%"
+ value-format="HH:mm"
+ format="HH:mm"
+ v-model="attendanceForm.offWorkDateTime"
+ placeholder="涓嬬彮鏃堕棿">
+ </el-time-picker>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </div>
+ </el-form>
+ <span slot="footer" class="dialog-footer">
+ <el-button @click="addAttendanceVisible = false">鍙� 娑�</el-button>
+ <el-button type="primary" @click="confirmAddAttendance()">纭� 瀹�</el-button>
+ </span>
+ </el-dialog>
+ <el-dialog
+ title="鍚屾鑰冨嫟璁板綍"
+ :visible.sync="syncAttendanceVisible"
+ @close="()=>{syncDateRange=[]}"
+ width="25%">
+ <el-date-picker
+ style="width:100%"
+ v-model="syncDateRange"
+ type="datetimerange"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ :default-time="['00:00:00', '23:59:59']"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡">
+ </el-date-picker>
+ <span slot="footer" class="dialog-footer">
+ <el-button @click="syncAttendanceVisible = false">鍙� 娑�</el-button>
+ <el-button type="primary" @click="confirmSyncAttendance">纭� 瀹�</el-button>
+ </span>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import StaffClockInRecord from "./components/staffClockInRecord.vue";
+import {selectAllUser} from '@/api/system/user'
+import {
+ pageAttendanceRecord,
+ checkDutyDate,
+ saveOrUpdateStaffAttendanceTrackingRecord,
+ removeStaffAttendanceTrackingRecord,
+ syncAttendanceRecord
+} from '@/api/performance/attendance'
+import {getDicts} from "@/api/system/dict/data";
+import dayjs from 'dayjs';
+export default {
+ name: "Attendance",
+ components: {
+ StaffClockInRecord
+ },
+ data() {
+ return {
+ syncDateRange:[],
+ syncAttendanceVisible: false,
+ attendanceForm:{
+ workDataId: null,
+ offWorkDataId: null,
+ personCode: null,
+ personName: null,
+ deptName: "璐ㄩ噺閮�",
+ shiftId: null,
+ swingDate: null,
+ workDateTime: null,
+ offWorkDateTime: null,
+ result: null,
+ },
+ attendanceRule:{
+ personName:{required:true,message:'璇烽�夋嫨鍛樺伐濮撳悕',trigger:'change'},
+ deptName:{required:true,message:'璇疯緭鍏ラ儴闂ㄥ悕绉�',trigger:'blur'},
+ dailyName:{required:true,message:'璇疯緭鍏ョ彮娆″悕绉�',trigger:'blur'},
+ shiftId:{required:true,message:'璇烽�夋嫨鐝绫诲瀷',trigger:'change'},
+ swingDate:{required:true,message:'璇烽�夋嫨鑰冨嫟鏃堕棿',trigger:'change'},
+ workDateTime:{required:true,message:'璇烽�夋嫨涓婄彮鏃堕棿',trigger:'change'},
+ offWorkDateTime:{required:true,message:'璇烽�夋嫨涓嬬彮鏃堕棿',trigger:'change'},
+ result:{required:true,message:'璇烽�夋嫨鑰冨嫟缁撴灉',trigger:'change'},
+ },
+ addAttendanceVisible:false,
+ dialogVisible:false,
+ dateRange: [],
+ queryParams: {
+ startDate: "",
+ endDate: "",
+ keyword: "",
+ },
+ userList:[],
+ loading: false,
+ tableData: [],
+ pagination: {
+ current: 1,
+ size: 20,
+ total: 0,
+ },
+ tableHeight:0,
+ resizeHandler: null, // 闃叉姈鍑芥暟寮曠敤
+ clockInQueryParams:{
+ personCode:null,//浜哄憳缂栧彿
+ swingDate:null,//鑰冨嫟鏃堕棿
+ shiftId:null//鐝id
+ },
+ dailyTypeList:[],
+ resultList:[
+ {
+ label:"姝e父",
+ value:1,
+ type:"success"
+ },
+ {
+ label:"寮傚父",
+ value:0,
+ type:"danger"
+ },
+ ],
+ };
+ },
+ created() {
+ this.selectEnumByCategory()
+ this.getUserList()
+ this.getTableHeight();
+ this.dateRange = this.getTimeRange()
+ this.resizeHandler = this.debounce(() => {
+ this.getTableHeight();
+ }, 200);
+ this.refreshTable();
+ },
+ mounted(){
+ this.getTableHeight();
+ window.addEventListener("resize",this.resizeHandler)
+ },
+ beforeDestroy(){
+ window.removeEventListener("resize",this.resizeHandler)
+ },
+ methods: {
+ getShiftByDic(e) {
+ let obj = this.dailyTypeList.find((m) => m.dictValue == e);
+ if (obj) {
+ return obj.dictLabel;
+ }
+ return "鏃�";
+ },
+ getDictTypeByShift(e) {
+ let obj = this.dailyTypeList.find((m) => m.dictValue == e);
+ if (obj) {
+ return obj.listClass;
+ }
+ return "";
+ },
+ selectEnumByCategory() {
+ getDicts("sys_class_type").then((response) => {
+ this.dailyTypeList = response.data;
+ });
+ },
+ /**
+ * 鍒濆鍖栭粯璁ゆ棩鏈熻寖鍥达細杩戜竴涓湀锛堝綋鍓嶆棩鏈� - 30澶� 鑷� 褰撳墠鏃ユ湡锛�
+ */
+ getTimeRange(format = 'YYYY-MM-DD HH:mm:ss') {
+ // 鑾峰彇褰撳墠鏃堕棿
+ const now = dayjs();
+ // 鑾峰彇褰撳墠鏃ユ湡鐨勩�屾棩銆嶏紙1-31锛�
+ const currentDate = now.date();
+
+ let startTime, endTime;
+
+ // 鏍稿績閫昏緫锛氬垽鏂綋鍓嶆棩鏈熸槸鍚﹀ぇ浜�25鍙�
+ if (currentDate > 25) {
+ // 鉁� 鎯呭喌1锛氬綋鍓嶆棩>25 鈫� 褰撴湀26鍙� ~ 娆℃湀25鍙�
+ startTime = now.startOf('month').add(25, 'day'); // 褰撴湀1鍙� +25澶� = 26鍙�
+ endTime = startTime.add(1, 'month').date(25).hour(23)
+ .minute(59)
+ .second(59); // 娆℃湀25鍙凤紙dayjs鑷姩澶勭悊璺ㄥ勾锛�
+ } else {
+ // 鉁� 鎯呭喌2锛氬綋鍓嶆棩鈮�25 鈫� 涓婃湀26鍙� ~ 褰撴湀25鍙�
+ startTime = now.subtract(1, 'month').startOf('month').add(25, 'day'); // 涓婃湀26鍙�
+ endTime = now.date(25).hour(23)
+ .minute(59)
+ .second(59); // 褰撴湀25鍙�
+ }
+
+ // 杩斿洖鏍煎紡鍖栧悗鐨勬椂闂存暟缁�
+ return [startTime.format(format), endTime.format(format)];
+ },
+ //鍚屾鑰冨嫟璁板綍
+ confirmSyncAttendance(){
+ if(!this.syncDateRange || this.syncDateRange.length<2){
+ this.$message.warning("璇烽�夋嫨鍚屾鏃ユ湡");
+ return
+ }
+ syncAttendanceRecord({
+ startDate:this.syncDateRange[0],
+ endDate:this.syncDateRange[1]
+ }).then(res=>{
+ if(res.code===200){
+ this.$message.success("鍚庡彴鍚屾鑰冨嫟璁板綍涓紝璇峰埛鏂拌〃鏍兼煡鐪�")
+ this.refreshTable()
+ }
+ }).catch(error=>{
+ console.error(error)
+ })
+ this.$nextTick(()=>{
+ this.syncAttendanceVisible = false
+ })
+ },
+ //鎵撳紑鍚屾鑰冨嫟璁板綍寮规
+ openSyncAttendanceDialog(){
+ this.syncAttendanceVisible = true
+ },
+ //鍒犻櫎鑰冨嫟璁板綍
+ confirmRemoveRecord(row){
+ if(!row){
+ this.$message.warning("璇烽�夋嫨涓�鏉¤褰�")
+ return
+ }
+ this.$confirm('鏄惁纭鍒犻櫎璇ユ潯鑰冨嫟璁板綍', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ let ids = [row.workDataId,row.offWorkDataId]
+ removeStaffAttendanceTrackingRecord(ids).then(res=>{
+ if(res.code===200){
+ this.$message.success("鍒犻櫎鎴愬姛")
+ this.refreshTable()
+ }
+ }).catch(error=>{
+ console.error(error)
+ })
+ }).catch(() => { });
+ },
+ //鍏抽棴鏂板/缂栬緫鑰冨嫟璁板綍寮规
+ closeAttendanceDialog(){
+ this.attendanceForm.id = null
+ this.$refs.attendanceForm.resetFields()
+ },
+ //閲嶇疆鑰冨嫟璁板綍寮规琛ㄥ崟
+ resetAttendanceForm(){
+ this.attendanceForm = {
+ workDataId: null,
+ offWorkDataId: null,
+ personCode: null,
+ personName: null,
+ deptName: "璐ㄩ噺閮�",
+ shiftId: null,
+ swingDate: null,
+ workDateTime: null,
+ offWorkDateTime: null,
+ result: null,
+ }
+ this.$refs.attendanceForm.resetFields()
+ this.$nextTick(()=>{
+ this.addAttendanceVisible = false
+ })
+ },
+ //纭淇濆瓨鑰冨嫟璁板綍
+ confirmAddAttendance(){
+ this.$refs.attendanceForm.validate(valid=>{
+ if(valid){
+ saveOrUpdateStaffAttendanceTrackingRecord(this.attendanceForm).then(res=>{
+ if(res.code===200){
+ this.$message.success('淇濆瓨鎴愬姛')
+ this.refreshTable()
+ this.resetAttendanceForm()
+ }
+ }).catch(error=>{
+ console.error(error)
+ })
+ }
+ })
+ },
+ //鏍¢獙鎵�閫夎�冨嫟鏃ユ湡鏄惁瀛樺湪璇ヤ汉鍛樼殑鑰冨嫟璁板綍
+ checkDutyDate(val){
+ if(!this.attendanceForm.personCode){
+ this.$message.warning("璇峰厛閫夋嫨浜哄憳鍚嶇О")
+ this.attendanceForm.dutyDate = null
+ return
+ }
+ let params = {
+ personCode:this.attendanceForm.personCode,
+ swingDate: val
+ }
+ checkDutyDate(params).then(res=>{
+ if(res.code===200&&res.data){
+ this.attendanceForm.result = 1//榛樿姝e父
+ this.attendanceForm.shiftId = res.data.shift
+ this.attendanceForm.workDateTime = res.data.startTime
+ this.attendanceForm.offWorkDateTime = res.data.endTime
+ }
+ }).catch(error=>{
+ console.error(error)
+ this.attendanceForm.swingDate = null
+ })
+ },
+ //閫夋嫨浜哄憳鍚嶇О甯﹀嚭宸ュ彿
+ selectedPersonName(val){
+ let account = ""
+ this.userList.forEach(item=>{
+ if(item.name===val){
+ account = item.account
+ }
+ })
+ this.attendanceForm.personCode = account
+ },
+ //鎵撳紑鏂板/缂栬緫鑰冨嫟璁板綍寮规
+ openAddAttendanceDialog(row){
+ if(row){
+ //澶勭悊涓�/涓嬬彮鏃堕棿鏍煎紡
+ let workTime = row.workDateTime&&row.workDateTime.length>8?row.workDateTime.substring(11,16):row.workDateTime
+ let offWorkTime = row.offWorkDateTime&&row.offWorkDateTime.length>8?row.offWorkDateTime.substring(11,16):row.offWorkDateTime
+ row.workDateTime = workTime
+ row.offWorkDateTime = offWorkTime
+ this.attendanceForm = {...row}
+ }
+ this.addAttendanceVisible = true
+ },
+ //鎵撳紑鏌ョ湅鎵撳崱璁板綍寮规
+ openClockInDialog(row){
+ if(row){
+ this.clockInQueryParams.personCode = row.personCode
+ this.clockInQueryParams.shiftId = row.shiftId
+ this.clockInQueryParams.swingDate = row.swingDate
+ }
+ this.$nextTick(()=>{
+ this.dialogVisible = true
+ })
+ },
+ //鏍煎紡鍖栦汉鍛樺悕绉�
+ formatterUserName(value){
+ let userName = ""
+ this.userList.forEach(item=>{
+ if(item.id===value){
+ userName = item.name
+ }
+ })
+ return userName;
+ },
+ //鏍煎紡鍖栬�冨嫟缁撴灉
+ getResultTag(type) {
+ let typeItem = null
+ this.resultList.forEach(item=>{
+ if(item.value===type){
+ typeItem = item
+ }
+ })
+ return typeItem;
+ },
+ //闃叉姈鍑芥暟
+ debounce(fn, delay) {
+ let timer = null;
+ return (...args) => {
+ clearTimeout(timer);
+ timer = setTimeout(() => fn.apply(this, args), delay);
+ };
+ },
+ //鍔ㄦ�佽幏鍙栬〃鏍奸珮搴�
+ getTableHeight(){
+ const innerHeight = window.innerHeight
+ const naviHeight = 96
+ const otherHeight = 128
+ this.tableHeight = innerHeight - naviHeight - otherHeight
+ },
+ //鍒锋柊琛ㄦ牸
+ refreshTable() {
+ this.loading = true;
+ if (this.dateRange && this.dateRange.length === 2) {
+ this.queryParams.startDate = this.dateRange[0];
+ this.queryParams.endDate = this.dateRange[1];
+ } else {
+ this.queryParams.startDate = "";
+ this.queryParams.endDate = "";
+ }
+ pageAttendanceRecord({...this.queryParams, ...this.pagination}).then(res => {
+ this.tableData = res.data.records;
+ this.pagination.total = res.data.total;
+ this.pagination.current = res.data.current;
+ this.loading = false;
+ }).catch(() => {
+ this.loading = false;
+ });
+ },
+ //鍒嗛〉鍒囨崲
+ handlePageChange(page) {
+ this.pagination.current = page.page;
+ this.pagination.size = page.limit;
+ this.refreshTable();
+ },
+ //鏌ヨ鐢ㄦ埛鍒楄〃
+ getUserList(){
+ selectAllUser().then(res=>{
+ this.userList = res.data
+ }).catch(error=>{
+ console.error(error)
+ })
+ },
+ //閲嶇疆鎸夐挳
+ resetQuery() {
+ this.dateRange = this.getTimeRange();
+ this.queryParams = {
+ startDate: "",
+ endDate: "",
+ keyword: "",
+ };
+ this.$nextTick(()=>{
+ this.refreshTable()
+ })
+ },
+ },
+};
+</script>
+
+<style scoped lang="scss">
+.attendance-page {
+ padding: 10px;
+}
+.remove-btn.el-button--text{
+ color:#ff4949
+}
+.search {
+ height: 50px;
+ display: flex;
+ align-items: center;
+ background-color: #fff;
+ margin-left:16px;
+}
+
+.search_thing {
+ display: flex;
+ align-items: center;
+ height: 50px;
+ margin-right: 30px
+}
+
+.search_label {
+ width: 90px;
+ font-size: 14px;
+ text-align: right;
+}
+
+.search_input {
+ display: flex;
+ align-items: center;
+}
+
+.container {
+ background-color: #fff;
+ padding: 0 16px;
+ min-height: calc(100vh - 180px);
+}
+
+::v-deep .el-tabs__header {
+ margin-bottom: 16px;
+}
+
+::v-deep .el-tabs__content {
+ padding: 0;
+}
+</style>
diff --git a/src/views/performance/class/index.vue b/src/views/performance/class/index.vue
index ca34134..f6c52f0 100644
--- a/src/views/performance/class/index.vue
+++ b/src/views/performance/class/index.vue
@@ -265,10 +265,26 @@
<span style="color: red; margin-right: 4px">*</span>浜哄憳鍚嶇О锛�
</div>
<div class="search_input" style="width: calc(100% - 90px)">
- <el-select v-model="schedulingQuery.userId" placeholder="璇烽�夋嫨" style="width: 100%" multiple clearable
- collapse-tags>
- <el-option v-for="item in personList" :key="item.id" :label="item.name" :value="item.id">
- </el-option>
+ <el-select v-model="schedulingQuery.userId" popper-class="select-with-all" placeholder="璇烽�夋嫨" style="width: 100%" multiple collapse-tags clearable>
+<!-- <el-option v-for="item in personList" :key="item.id" :label="item.name" :value="item.id">-->
+<!-- </el-option>-->
+ <template slot="prefix">
+ <el-button
+ type="text"
+ size="mini"
+ @click="handleSelectAll"
+ style="margin: 4px 0;"
+ >
+ {{ isAllSelected ? '鍙栨秷鍏ㄩ��' : '鍏ㄩ��' }}
+ </el-button>
+ <el-divider style="margin: 5px 0;" />
+ </template>
+ <el-option
+ v-for="item in personList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
</el-select>
</div>
</div>
@@ -378,7 +394,7 @@
loading: false,
schedulingQuery: {
week: "",
- userId: null,
+ userId: [],
shift: "",
},
list: [],
@@ -399,6 +415,11 @@
menuY: 0,
selectedTarget: null,
};
+ },
+ computed:{
+ isAllSelected() {
+ return this.schedulingQuery.userId.length === this.personList.length && this.personList.length > 0;
+ },
},
watch: {
@@ -423,6 +444,14 @@
document.removeEventListener('click', this.handleClickOutside)
},
methods: {
+ handleSelectAll() {
+ if (this.isAllSelected) {
+ this.schedulingQuery.userId = [];
+ } else {
+ // 鍙�変腑鍙敤閫夐」鐨剉alue
+ this.schedulingQuery.userId = this.personList.map(item => item.id);
+ }
+ },
handleContextMenu(target,e) {
// 闃绘娴忚鍣ㄩ粯璁ゅ彸閿彍鍗�
e.preventDefault()
@@ -526,40 +555,6 @@
this.initYear();
}
},
- transFromNumber(num) {
- let changeNum = [
- "闆�",
- "涓�",
- "浜�",
- "涓�",
- "鍥�",
- "浜�",
- "鍏�",
- "涓�",
- "鍏�",
- "涔�",
- ]; //changeNum[0] = "闆�"
- let unit = ["", "鍗�", "鐧�", "鍗�", "涓�"];
- num = parseInt(num);
- let getWan = (temp) => {
- let strArr = temp.toString().split("").reverse();
- let newNum = "";
- for (var i = 0; i < strArr.length; i++) {
- newNum =
- (i == 0 && strArr[i] == 0
- ? ""
- : i > 0 && strArr[i] == 0 && strArr[i - 1] == 0
- ? ""
- : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i])) +
- newNum;
- }
- return newNum;
- };
- let overWan = Math.floor(num / 10000);
- let noWan = num % 10000;
- if (noWan.toString().length < 4) noWan = "0" + noWan;
- return overWan ? getWan(overWan) + "涓�" + getWan(noWan) : getWan(num);
- },
init() {
this.pageLoading = true;
let year = this.query.year.getFullYear();
@@ -574,16 +569,6 @@
}).then((res) => {
this.pageLoading = false;
this.list = res.data.page
- // this.list = res.data.page.map((item) => {
- // for (let key in item.monthlyAttendance) {
- // let type = this.getDayByDic(key);
- // if (type != undefined || type != null) {
- // item[`day${type}`] = item.monthlyAttendance[key];
- // }
- // }
- // return item;
- // });
- console.log(this.list)
let headerList = res.data.headerList;
this.weeks = [];
headerList.forEach((item) => {
@@ -649,7 +634,7 @@
this.schedulingVisible = false;
this.schedulingQuery = {
week: "",
- userId: null,
+ userId: [],
shift: "",
};
this.refresh();
diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue
index 9dd89c3..3306ae7 100644
--- a/src/views/system/user/index.vue
+++ b/src/views/system/user/index.vue
@@ -114,48 +114,61 @@
</el-row>
<el-row>
<el-col :span="12">
+ <el-form-item label="宀椾綅">
+ <el-select style="width:100%" v-model="form.postIds" multiple placeholder="璇烽�夋嫨">
+ <el-option
+ v-for="item in postOptions"
+ :key="item.postId"
+ :label="item.postName"
+ :value="item.postId"
+ :disabled="item.status == 1"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
<el-form-item label="瑙掕壊" prop="roleIds">
- <el-select v-model="form.roleIds" multiple placeholder="璇烽�夋嫨瑙掕壊" clearable>
+ <el-select style="width:100%" v-model="form.roleIds" multiple placeholder="璇烽�夋嫨瑙掕壊" clearable>
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId"
:disabled="item.status == 1"></el-option>
</el-select>
</el-form-item>
</el-col>
+ </el-row>
+ <el-row>
<el-col :span="12">
<el-form-item label="瀵嗙爜" prop="password">
<el-input v-model="form.password" placeholder="璇疯緭鍏ョ敤鎴峰瘑鐮�" type="password" maxlength="20" show-password />
</el-form-item>
</el-col>
- </el-row>
- <el-row>
<el-col :span="12">
<el-form-item label="濮撳悕EN" prop="nameEn">
<el-input v-model="form.nameEn" placeholder="璇疯緭鍏ュ鍚岴N" maxlength="50" />
</el-form-item>
</el-col>
+ </el-row>
+ <el-row>
<el-col :span="12">
<el-form-item label="閭" prop="email">
<el-input v-model="form.email" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
</el-form-item>
</el-col>
- </el-row>
- <el-row>
<el-col :span="12">
<el-form-item label="鍗曚綅" prop="company">
<el-select v-model="form.company" placeholder="璇烽�夋嫨鍗曚綅" style="width: 100%" clearable>
- <el-option v-for="item in postOptions" :key="item.id" :label="item.company"
+ <el-option v-for="item in companyOptions" :key="item.id" :label="item.company"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
+ </el-row>
+ <el-row>
<el-col :span="12">
<el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
<treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true"
- placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" />
+ placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" />
</el-form-item>
</el-col>
- </el-row>
- <el-row>
<el-col :span="12">
<el-form-item label="绛惧悕">
<el-upload class="avatar-uploader" :action="uploadAction" :show-file-list="false"
@@ -166,11 +179,13 @@
</el-upload>
</el-form-item>
</el-col>
+ </el-row>
+ <el-row>
<el-col :span="12">
<el-form-item label="涓汉鐓х墖">
<el-upload class="avatar-uploader" :action="uploadAction" :show-file-list="false"
- :headers="upload.headers" accept=".png, .jpg, .jpeg, .gif" :on-error="handleUploadError1"
- :on-success="handleUploadSuccess1" :before-upload="handleBeforeUpload1">
+ :headers="upload.headers" accept=".png, .jpg, .jpeg, .gif" :on-error="handleUploadError1"
+ :on-success="handleUploadSuccess1" :before-upload="handleBeforeUpload1">
<img v-if="form.pictureUrl" :src="javaApi + '/img/' + form.pictureUrl" class="avatar" alt="">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
@@ -278,8 +293,15 @@
resetUserPwd,
changeUserStatus,
deptTreeSelect,
- selectCompaniesList, selectSimpleList, addPersonUser, uploadFile, selectRoleList, selectCustomEnum, addDepartment
+ selectCompaniesList,
+ selectSimpleList,
+ addPersonUser,
+ uploadFile,
+ selectRoleList,
+ selectCustomEnum,
+ addDepartment
} from "@/api/system/user";
+import {optionSelect} from '@/api/system/post'
import { getToken } from "@/utils/auth";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
@@ -323,6 +345,8 @@
dateRange: [],
// 宀椾綅閫夐」
postOptions: [],
+ //鍗曚綅閫夐」
+ companyOptions:[],
// 瑙掕壊閫夐」
roleOptions: [],
// 琛ㄥ崟鍙傛暟
@@ -703,10 +727,11 @@
this.reset();
this.open = true;
selectCustomEnum().then(res => {
- this.postOptions = res.data;
+ this.companyOptions = res.data;
})
getUser().then(response => {
this.roleOptions = response.roles;
+ this.postOptions = response.posts
this.title = "娣诲姞鐢ㄦ埛";
});
},
@@ -714,7 +739,7 @@
handleUpdate(row) {
this.reset();
selectCustomEnum().then(res => {
- this.postOptions = res.data;
+ this.companyOptions = res.data;
})
const userId = row.userId || this.ids;
getUser(userId).then(response => {
@@ -722,6 +747,8 @@
this.form.password = ''
this.roleOptions = response.roles;
this.$set(this.form, "roleIds", response.roleIds);
+ this.postOptions = response.posts
+ this.$set(this.form, "postIds", response.postIds);
this.open = true;
this.title = "淇敼鐢ㄦ埛";
});
--
Gitblit v1.9.3