考勤明细修改审批流程更改,增加上传附件字段
This commit is contained in:
parent
6abb87b4ca
commit
d7bec1d23f
|
|
@ -163,3 +163,14 @@ export function updateMonthReportData(query) {
|
|||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function singleUploadFile(data) {
|
||||
return request({
|
||||
url: '/system/fileUpload/singleUploadFile',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// base64Utils.js
|
||||
let _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
const useBase64 = {
|
||||
encode64:(e) => {
|
||||
let t = "";
|
||||
let f = 0;
|
||||
e = useBase64.encodeUTF8(e);
|
||||
while (f < e.length) {
|
||||
const n = e.charCodeAt(f++);
|
||||
const r = e.charCodeAt(f++);
|
||||
const i = e.charCodeAt(f++);
|
||||
let s = n >> 2;
|
||||
let o = (n & 3) << 4 | r >> 4;
|
||||
let u = (r & 15) << 2 | i >> 6;
|
||||
let a = i & 63;
|
||||
if (isNaN(r)) {
|
||||
u = a = 64;
|
||||
} else if (isNaN(i)) {
|
||||
a = 64;
|
||||
}
|
||||
t += _keyStr[s] + _keyStr[o] + _keyStr[u] + _keyStr[a];
|
||||
}
|
||||
return t;
|
||||
},
|
||||
decode64: (e) => {
|
||||
let t = "";
|
||||
let f = 0;
|
||||
e = e.replace(/[^A-Za-z0-9+/=]/g, "");
|
||||
while (f < e.length) {
|
||||
const s = _keyStr.indexOf(e.charAt(f++));
|
||||
const o = _keyStr.indexOf(e.charAt(f++));
|
||||
const u = _keyStr.indexOf(e.charAt(f++));
|
||||
const a = _keyStr.indexOf(e.charAt(f++));
|
||||
let n = s << 2 | o >> 4;
|
||||
let r = (o & 15) << 4 | u >> 2;
|
||||
let i = (u & 3) << 6 | a;
|
||||
t += String.fromCharCode(n);
|
||||
if (u !== 64) {
|
||||
t += String.fromCharCode(r);
|
||||
}
|
||||
if (a !== 64) {
|
||||
t += String.fromCharCode(i);
|
||||
}
|
||||
}
|
||||
return useBase64.decodeUTF8(t);
|
||||
},
|
||||
|
||||
encodeUTF8: (input) => {
|
||||
return unescape(encodeURIComponent(input));
|
||||
},
|
||||
|
||||
decodeUTF8: (input) => {
|
||||
return decodeURIComponent(escape(input));
|
||||
},
|
||||
}
|
||||
export default useBase64;
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
export function lookFile(){
|
||||
return 'http://192.168.0.14:21626/file/statics' //14服务器
|
||||
// return 'http://112.29.103.165:14413/file/statics' //1.6演示服务器
|
||||
// return 'http://218.21.27.6:1999/file/statics' //生产服务器
|
||||
}
|
||||
export function lookFaceFile(){
|
||||
return 'http://192.168.0.14:21626/file/statics/' //14服务器
|
||||
//return 'http://112.29.103.165:14413/file/statics/' //1.6演示服务器
|
||||
// return 'http://218.21.27.6:1999/file/statics/' //生产服务器
|
||||
}
|
||||
export function filePreview(){
|
||||
return 'http://192.168.0.14:8012/onlinePreview?url=' //14服务器
|
||||
// return 'http://112.29.103.165:8012/onlinePreview?url=' //1.6演示服务器
|
||||
// return 'http://218.21.27.6:18013/onlinePreview?url='
|
||||
}
|
||||
|
||||
export function lookMioIoFile() {
|
||||
// return 'http://218.21.27.6:19090/nxdt-courseware' //14服务器
|
||||
return 'http://192.168.0.14:9090/nxdt-courseware' //14服务器
|
||||
// return 'http://112.29.103.165:14413/file/statics' //1.6演示服务器
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param filePath 文件路径
|
||||
* @param fileName 文件名称 如果没有名称 请填写 "" 不要填 null
|
||||
*/
|
||||
export function downloadFile(filePath, fileName) {
|
||||
let lookFiles = lookFile()
|
||||
let lookFaceFiles = lookFaceFile()
|
||||
showLoadingIndicator();
|
||||
//判断filePath第一个字符是否/
|
||||
if (filePath.charAt(0) === '/') {
|
||||
filePath = filePath.includes('http') ? filePath : `${lookFiles}${filePath}`
|
||||
}else{
|
||||
filePath = filePath.includes('http') ? filePath : `${lookFaceFiles}${filePath}`
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', filePath, true);
|
||||
xhr.responseType = 'blob';
|
||||
|
||||
xhr.onload = () => {
|
||||
const blob = xhr.response;
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = url;
|
||||
a.download = fileName === "" ? filePath.split("/")[filePath.split("/").length - 1] : fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
// Hide loading indicator
|
||||
hideLoadingIndicator();
|
||||
};
|
||||
|
||||
xhr.onerror = () => {
|
||||
// Hide loading indicator in case of error
|
||||
hideLoadingIndicator();
|
||||
console.error('File download failed');
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function showLoadingIndicator() {
|
||||
const loadingDiv = document.createElement('div');
|
||||
loadingDiv.id = 'loading-indicator';
|
||||
loadingDiv.style.position = 'fixed';
|
||||
loadingDiv.style.top = '50%';
|
||||
loadingDiv.style.left = '50%';
|
||||
loadingDiv.style.transform = 'translate(-50%, -50%)';
|
||||
loadingDiv.style.padding = '15px';
|
||||
loadingDiv.style.backgroundColor = 'rgba(66,65,65,0.7)';
|
||||
loadingDiv.style.color = 'white';
|
||||
loadingDiv.style.borderRadius = '5px';
|
||||
loadingDiv.innerText = 'Loading...';
|
||||
document.body.appendChild(loadingDiv);
|
||||
}
|
||||
|
||||
function hideLoadingIndicator() {
|
||||
const loadingDiv = document.getElementById('loading-indicator');
|
||||
if (loadingDiv) {
|
||||
document.body.removeChild(loadingDiv);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
<template>
|
||||
<div class="dataDiv">
|
||||
<div v-if="loading" class="loading">
|
||||
<div class="spinner"></div>
|
||||
<div>{{ loadingMessage }}</div>
|
||||
</div>
|
||||
<el-button type="primary" @click="download" style="position: absolute;left: 92%;top: -7%">下载</el-button>
|
||||
<iframe :src="file" frameborder="0" width="100%" height="720px" @load="onIframeLoad"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { filePreview, lookFaceFile, lookFile, lookMioIoFile,downloadFile } from '@/utils/bns-kkFile-preview' // Assuming Base64 is saved as a separate module
|
||||
import useBase64 from '@/utils/base64Utils'
|
||||
import { encryptCBC } from '@/utils/aescbc'
|
||||
|
||||
export default {
|
||||
name: 'FileHandler',
|
||||
props: {
|
||||
items: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
filePreviewUrl: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
fileType: {
|
||||
type: String,
|
||||
default: '' // docx: word
|
||||
},
|
||||
lookType: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// lookFile: 'http://218.21.27.6:1999/nxnyback/statics',
|
||||
// filePreviewPath: 'http://218.21.27.6:8012/onlinePreview?url=',
|
||||
// lookFile: 'http://112.29.103.165:14413/file/statics',
|
||||
lookFile: '',
|
||||
filePreviewPath: '',
|
||||
file: '',
|
||||
loading: true,
|
||||
loadingMessage: 'Loading...'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
console.log('this.lookType', this.lookType)
|
||||
console.log(this.$prop.items)
|
||||
if (this.lookType === 'normal') {
|
||||
this.lookFile = lookFile()
|
||||
} else {
|
||||
this.lookFile = lookMioIoFile()
|
||||
}
|
||||
this.filePreviewPath = filePreview()
|
||||
},
|
||||
methods: {
|
||||
setParam() {
|
||||
this.filePreviewPath = filePreview()
|
||||
if (this.lookType === 'normal') {
|
||||
this.lookFile = lookFile()
|
||||
} else {
|
||||
this.lookFile = lookMioIoFile()
|
||||
}
|
||||
console.log(`${this.lookFile}/${this.items.filePreviewUrl}`)
|
||||
this.file = ''
|
||||
this.loading = true
|
||||
this.loadingMessage = 'Loading...'
|
||||
this.updateLoadingMessage()
|
||||
let filePath = this.items.filePreviewUrl
|
||||
let fileNames = this.items.fileName
|
||||
let suffix = ''
|
||||
if (fileNames && fileNames !== 'null' && fileNames !== 'undefined') {
|
||||
suffix = fileNames.substring(fileNames.lastIndexOf('.') + 1)
|
||||
}
|
||||
|
||||
let fileUploadPath = filePath
|
||||
let filePreviewPath
|
||||
let time = encryptCBC(Math.floor(Date.now()).toString())
|
||||
if (suffix.toLowerCase() === 'pdf') {
|
||||
filePreviewPath = filePath.includes('http') ? filePath : `${this.lookFile}/${filePath}`
|
||||
this.showDownloadButton = false
|
||||
console.log('filePreviewPath', filePreviewPath)
|
||||
} else {
|
||||
const encodedPath = filePath.includes('http')
|
||||
? encodeURIComponent(useBase64.encode64(`${filePath}`))
|
||||
: encodeURIComponent(useBase64.encode64(`${this.lookFile}/${filePath}`))
|
||||
filePreviewPath = `${this.filePreviewPath}${encodedPath}&token=${time}`
|
||||
console.log('filePreviewPath', filePreviewPath)
|
||||
if (fileNames.length > 50) {
|
||||
this.fileName = `${fileNames.substring(0, 50)}...`
|
||||
} else {
|
||||
this.fileName = fileNames
|
||||
}
|
||||
|
||||
this.showDownloadButton = !['jpg', 'png', 'JPG', 'PNG'].includes(suffix)
|
||||
console.log('encodedPath', encodedPath)
|
||||
}
|
||||
console.log('filePreviewPath', filePreviewPath)
|
||||
const isEdgeOrOther = /Edg|Chrome|Firefox|Safari/.test(navigator.userAgent)
|
||||
if (isEdgeOrOther) {
|
||||
const url = new URL(filePreviewPath)
|
||||
url.searchParams.append('preventDownload', 'true')
|
||||
filePreviewPath = url.toString()
|
||||
}
|
||||
console.log('filePreviewPath', filePreviewPath)
|
||||
this.file = filePreviewPath
|
||||
this.fileUploadPath = fileUploadPath
|
||||
},
|
||||
onIframeLoad() {
|
||||
this.loading = false
|
||||
this.loadingMessage = ''
|
||||
},
|
||||
updateLoadingMessage() {
|
||||
let dots = 0
|
||||
const interval = setInterval(() => {
|
||||
if (!this.loading) {
|
||||
clearInterval(interval)
|
||||
return
|
||||
}
|
||||
dots = (dots + 1) % 4
|
||||
this.loadingMessage = 'Loading' + '.'.repeat(dots)
|
||||
}, 500)
|
||||
},
|
||||
fillInComments() {
|
||||
this.$prompt('请填写意见', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消'
|
||||
}).then(({ value }) => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '填写成功'
|
||||
})
|
||||
this.$emit('fillInComments', value)
|
||||
}).catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '取消输入'
|
||||
})
|
||||
})
|
||||
},
|
||||
download() {
|
||||
if (this.fileType === 'docx') {
|
||||
// 将路径 .pdf的 替换为 .doc, 下载docx文件
|
||||
this.fileUploadPath = this.fileUploadPath.replace('.pdf', '.docx')
|
||||
console.log('🚀 ~ download ~ this.fileUploadPath:', this.fileUploadPath)
|
||||
}
|
||||
downloadFile(this.fileUploadPath, this.$props.items.fileName)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
items: {
|
||||
handler: 'setParam',
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.dataDiv {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 20px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 4px solid rgba(0, 0, 0, 0.1);
|
||||
border-left-color: #000;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -79,8 +79,8 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="审批状态" align="center" prop="isCheck" :show-overflow-tooltip="true" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span v-show="scope.row.isCheck=='0'">待审批</span>
|
||||
<span v-show="scope.row.isCheck=='1'">已通过</span>
|
||||
<span v-show="scope.row.isCheck=='0'">待运维人员处理</span>
|
||||
<span v-show="scope.row.isCheck=='1'">已处理</span>
|
||||
<span v-show="scope.row.isCheck=='2'">未通过</span>
|
||||
<span v-show="scope.row.isCheck=='3'">撤回</span>
|
||||
</template>
|
||||
|
|
@ -113,6 +113,12 @@
|
|||
v-if="scope.row.isCheck==0||scope.row.isCheck==2||scope.row.isCheck==3"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
|
||||
<el-button
|
||||
size="mini"
|
||||
v-if="scope.row.isCheck==0"
|
||||
@click="handleCheck(scope.row)"
|
||||
>是否处理</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
@ -223,6 +229,92 @@
|
|||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="openCheck" width="1000px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="170px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请人:" prop="userName">
|
||||
<el-input v-model="form.userName" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="变更前部门:" prop="oldOrgId" >
|
||||
<el-input v-model="form.oldOrgName" disabled></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="变更后部门:" prop="newOrgId" >
|
||||
<el-input v-model="form.newOrgName" disabled></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="考勤规则组变更:" prop="isChangeAttGroup">
|
||||
<el-radio-group v-model="form.isChangeAttGroup" disabled>
|
||||
<el-radio
|
||||
v-for="item in isAgreeList"
|
||||
:key="item.id"
|
||||
:label="item.id"
|
||||
>{{item.name}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-if="form.isChangeAttGroup == '1'">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="变更前规则组:" prop="attGroupName">
|
||||
<el-input v-model="form.oldAttGroupName" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="变更后规则组:" prop="newAttGroup">
|
||||
<el-input v-model="form.newAttGroupName" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="变更生效日期:" prop="changeEffectiveDate">
|
||||
<el-date-picker
|
||||
v-model="form.changeEffectiveDate" :clearable="false" disabled
|
||||
type="date" value-format="yyyy-MM-dd" style="width: 100%;"
|
||||
placeholder="变更生效日期" >
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注:">
|
||||
<el-input type="textarea" placeholder="输入内容" v-model="form.remark" maxlength="100" disabled></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24" v-if="form.checkOpinion">
|
||||
<el-form-item label="审批意见:" prop="checkOpinion">
|
||||
<el-input type="textarea" v-model="form.checkOpinion" maxlength="100" disabled ></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="pass" >已处理</el-button>
|
||||
<el-button @click="cancel">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -243,7 +335,7 @@
|
|||
//组织机构
|
||||
orgList:this.$store.state.user.orgList,
|
||||
//审核状态
|
||||
isCheckList:[{id:'0',name:"待审批"},{id:'1',name:"已通过"},{id:'2',name:"未通过"},{id:'3',name:"撤回"}],
|
||||
isCheckList:[{id:'0',name:"待运维人员处理"},{id:'1',name:"已处理"}],
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 选中数组
|
||||
|
|
@ -262,6 +354,7 @@
|
|||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
openCheck: false,
|
||||
isEdit: false,
|
||||
isView: false,
|
||||
userList:[],
|
||||
|
|
@ -364,6 +457,7 @@
|
|||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.openCheck = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
|
|
@ -530,6 +624,59 @@
|
|||
};
|
||||
},
|
||||
|
||||
handleCheck(row) {
|
||||
this.reset();
|
||||
const Id = row.id
|
||||
getOrg(Id).then(orgResponse => {
|
||||
// 更新表单的 org 信息
|
||||
this.form ={
|
||||
...orgResponse.data,
|
||||
newAttGroup:orgResponse.data.newAttGroup?Number(orgResponse.data.newAttGroup):""
|
||||
};
|
||||
this.form.attGroupName = orgResponse.data.oldOrgName;
|
||||
// 更新视图状态
|
||||
this.openCheck = true;
|
||||
this.title = "审核";
|
||||
});
|
||||
},
|
||||
|
||||
pass(){
|
||||
this.$refs["form"].validate(valid => {
|
||||
var name = "";
|
||||
const selectedOrg = this.orgList.find(org => org.id == this.form.orgId);
|
||||
if (selectedOrg) {
|
||||
name = selectedOrg.name;
|
||||
} else {
|
||||
name = '';
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
console.log("同意",this.form)
|
||||
let param = {
|
||||
id:this.form.id,
|
||||
isCheck:'1',
|
||||
examineOpinion:this.form.examineOpinion,
|
||||
oldOrgId:this.form.oldOrgId,
|
||||
oldOrgName:this.form.oldOrgName,
|
||||
newOrgId:this.form.newOrgId,
|
||||
newOrgName:this.form.newOrgName,
|
||||
userId:this.form.userId,
|
||||
}
|
||||
this.changExamStatus(param)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** 提交 */
|
||||
changExamStatus(param) {
|
||||
console.log(param)
|
||||
changeOrgStatus(param).then(response => {
|
||||
this.$modal.msgSuccess("操作成功");
|
||||
this.openCheck = false;
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@
|
|||
// 更新视图状态
|
||||
this.open = true;
|
||||
this.isView = false;
|
||||
this.title = "编辑";
|
||||
this.title = "审核";
|
||||
});
|
||||
},
|
||||
handleView(row) {
|
||||
|
|
|
|||
|
|
@ -3,29 +3,43 @@
|
|||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="姓名" prop="userName">
|
||||
<el-input v-model="queryParams.userName" placeholder="请输入姓名" clearable style="width: 240px"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="部门" prop="orgId">
|
||||
<treeselect v-model="queryParams.orgId" :options="deptOptions" :normalizer="normalizer" placeholder="选择部门"
|
||||
style="width: 240px" />
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="attStatus">
|
||||
<el-select v-model="queryParams.attStatus" placeholder="状态" clearable style="width: 240px">
|
||||
<el-option v-for="dict in dict.type.att_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
<el-option v-for="dict in dict.type.att_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" style="margin-right: 10px;">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery" >重置</el-button>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" style="margin-right: 10px;"
|
||||
v-tooltip="{ content: '请谨慎操作', placement: 'top' }"
|
||||
>搜索
|
||||
</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
|
||||
v-tooltip="{ content: '请谨慎操作', placement: 'top' }"
|
||||
>重置
|
||||
</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['att:attReport:export']">导出</el-button>
|
||||
v-hasPermi="['att:attReport:export']"
|
||||
>导出
|
||||
</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['att:attReport:abnormal']">异常数据导出</el-button>
|
||||
<el-button type="primary" size="mini" @click="openDialog" v-hasPermi="['att:attReport:batch']">批量修改</el-button>
|
||||
v-hasPermi="['att:attReport:abnormal']"
|
||||
>异常数据导出
|
||||
</el-button>
|
||||
<el-button type="primary" size="mini" @click="openDialog" v-hasPermi="['att:attReport:batch']">批量修改
|
||||
</el-button>
|
||||
|
||||
<el-button type="primary" size="mini" @click="openData" v-hasPermi="['att:attReport:syn']">数据同步</el-button>
|
||||
</el-form-item>
|
||||
|
|
@ -45,14 +59,14 @@
|
|||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="selection" width="55" align="center"/>
|
||||
<el-table-column label="序号" align="center" width="80" type="index">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="姓名" align="center" prop="userName" />
|
||||
<el-table-column label="所属部门" align="center" prop="orgName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="姓名" align="center" prop="userName"/>
|
||||
<el-table-column label="所属部门" align="center" prop="orgName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="考勤日期" align="center" prop="attCurrentDay" width="180" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatDate(scope.row.attCurrentDay) }}</span>
|
||||
|
|
@ -76,31 +90,35 @@
|
|||
<el-table-column label="上班打卡时间" align="center" prop="toWorkAttCurrentTime" width="180"></el-table-column>
|
||||
<el-table-column label="上班状态" align="center" prop="toWorkAttStatus">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.att_status" :value="scope.row.toWorkAttStatus" />
|
||||
<dict-tag :options="dict.type.att_status" :value="scope.row.toWorkAttStatus"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="打卡地址" align="center" prop="toWorkAttAddress" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="异常备注" align="center" prop="toWorkErrorRemake" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="打卡地址" align="center" prop="toWorkAttAddress" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="异常备注" align="center" prop="toWorkErrorRemake" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="下班打卡时间" align="center" prop="offWorkAttCurrentTime" width="180"></el-table-column>
|
||||
<el-table-column label="下班状态" align="center" prop="offWorkAttStatus">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.att_status" :value="scope.row.offWorkAttStatus" />
|
||||
<dict-tag :options="dict.type.att_status" :value="scope.row.offWorkAttStatus"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="打卡地址" align="center" prop="offWorkAttAddress" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="异常备注" align="center" prop="offWorkErrorRemake" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="打卡地址" align="center" prop="offWorkAttAddress" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="异常备注" align="center" prop="offWorkErrorRemake" :show-overflow-tooltip="true"/>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<el-dialog title="批量修改" :visible.sync="open" width="1200px" append-to-body @close="cancel">
|
||||
<el-table v-loading="loading" :data="dialogList" width="100%" height="500px">
|
||||
<el-table-column label="序号" type="index" width="55" align="center" fixed />
|
||||
<el-table-column label="姓名" align="center" prop="userName" fixed />
|
||||
<el-table-column label="所属部门" align="center" prop="orgName" :show-overflow-tooltip="true" width="150" fixed />
|
||||
<el-table-column label="序号" type="index" width="55" align="center" fixed/>
|
||||
<el-table-column label="姓名" align="center" prop="userName" fixed/>
|
||||
<el-table-column label="所属部门" align="center" prop="orgName" :show-overflow-tooltip="true" width="150"
|
||||
fixed
|
||||
/>
|
||||
<el-table-column label="考勤日期" align="center" prop="attCurrentDay" :show-overflow-tooltip="true" width="180"
|
||||
fixed>
|
||||
fixed
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatDate(scope.row.attCurrentDay) }}</span>
|
||||
</template>
|
||||
|
|
@ -111,24 +129,49 @@
|
|||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-date-picker v-model="scope.row.toWorkAttCurrentTime" :clearable="false" type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss" style="width: 95%" placeholder="选择上班时间">
|
||||
value-format="yyyy-MM-dd HH:mm:ss" style="width: 95%" placeholder="选择上班时间"
|
||||
>
|
||||
</el-date-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" prop="toWorkAttStatus" width="180">
|
||||
<template slot="header">
|
||||
<span class="required-star">*</span> 修改上班状态
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.toWorkAttStatus" @change="changeToWorkAttStatus" placeholder="修改后上班状态"
|
||||
style="width: 95%">
|
||||
style="width: 95%"
|
||||
>
|
||||
<el-option v-for="dict in dict.type.att_status" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value" />
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" prop="toFilePath" width="180">
|
||||
<template slot="header">
|
||||
<span class="required-star">*</span> 修改上班附件
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action="#"
|
||||
:http-request="options => requestUpload(options, scope.$index, '1')"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<el-button size="small" type="primary">选择文件</el-button>
|
||||
</el-upload>
|
||||
<div style="cursor:pointer " v-if="getFileName(scope.row.filesVoList, '1')" @click="previewFile(getFilePath(scope.row.filesVoList, '1'))">
|
||||
{{ getFileName(scope.row.filesVoList, '1') }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="打卡地址" align="center" prop="toWorkAttAddress" :show-overflow-tooltip="true"
|
||||
width="180" />
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column align="center" prop="toErrorRemake" width="200">
|
||||
<template slot="header">
|
||||
<span class="required-star">*</span> 原因说明
|
||||
|
|
@ -144,7 +187,8 @@
|
|||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-date-picker v-model="scope.row.offWorkAttCurrentTime" :clearable="false" type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss" style="width: 95%" placeholder="选择下班时间">
|
||||
value-format="yyyy-MM-dd HH:mm:ss" style="width: 95%" placeholder="选择下班时间"
|
||||
>
|
||||
</el-date-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -155,12 +199,34 @@
|
|||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.offWorkAttStatus" placeholder="修改后下班状态" style="width: 95%">
|
||||
<el-option v-for="dict in dict.type.att_status" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value" />
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="打卡地址" align="center" prop="offWorkAttAddress" :show-overflow-tooltip="true"
|
||||
width="180"></el-table-column>
|
||||
width="180"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column align="center" prop="offFilePath" width="180">
|
||||
<template slot="header">
|
||||
<span class="required-star">*</span> 修改下班附件
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action="#"
|
||||
:http-request="options => requestUpload(options, scope.$index, '2')"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<el-button size="small" type="primary">选择文件</el-button>
|
||||
</el-upload>
|
||||
<div style="cursor:pointer" v-if="getFileName(scope.row.filesVoList, '2')" @click="previewFile(getFilePath(scope.row.filesVoList, '2'))">
|
||||
{{ getFileName(scope.row.filesVoList, '2') }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" prop="offErrorRemake" width="200">
|
||||
<template slot="header">
|
||||
<span class="required-star">*</span> 原因说明
|
||||
|
|
@ -180,9 +246,11 @@
|
|||
<!-- 外出次数查询 -->
|
||||
<el-dialog :title="title" :visible.sync="showOutCount" width="1200px" height="1000px" append-to-body>
|
||||
<el-form :model="queryRecord" ref="queryFormRecord" size="small" :inline="true" v-show="showSearch"
|
||||
label-width="110px">
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExportOutCountList">导出</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExportOutCountList">导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
|
@ -197,19 +265,21 @@
|
|||
<span>{{ formatDate(scope.row.attCurrentDay) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="打卡时间" align="center" prop="attCurrentTime" sortable :show-overflow-tooltip="true" />
|
||||
<el-table-column label="打卡地址" align="center" prop="attAddress" sortable :show-overflow-tooltip="true" />
|
||||
<el-table-column label="打卡时间" align="center" prop="attCurrentTime" sortable :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="打卡地址" align="center" prop="attAddress" sortable :show-overflow-tooltip="true"/>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="totalTwo > 0" :total="totalTwo" :page.sync="queryRecord.pageNum"
|
||||
:limit.sync="queryRecord.pageSize" @pagination="getOutCountList" />
|
||||
:limit.sync="queryRecord.pageSize" @pagination="getOutCountList"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
<!-- 打卡次数记录 -->
|
||||
<el-dialog :title="title" :visible.sync="showAttCount" width="1200px" height="1000px" append-to-body>
|
||||
<el-form :model="queryRecord" ref="queryFormRecord" size="small" :inline="true" v-show="showSearch"
|
||||
label-width="110px">
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item>
|
||||
<!-- <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>-->
|
||||
</el-form-item>
|
||||
|
|
@ -226,12 +296,13 @@
|
|||
<span>{{ formatDate(scope.row.attCurrentDay) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="打卡时间" align="center" prop="attCurrentTime" sortable :show-overflow-tooltip="true" />
|
||||
<el-table-column label="打卡地址" align="center" prop="attAddress" sortable :show-overflow-tooltip="true" />
|
||||
<el-table-column label="打卡时间" align="center" prop="attCurrentTime" sortable :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="打卡地址" align="center" prop="attAddress" sortable :show-overflow-tooltip="true"/>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="totalAttCount > 0" :total="totalAttCount" :page.sync="queryAttCount.pageNum"
|
||||
:limit.sync="queryAttCount.pageSize" @pagination="getAttCountList" />
|
||||
:limit.sync="queryAttCount.pageSize" @pagination="getAttCountList"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 数据同步对话框 -->
|
||||
|
|
@ -240,62 +311,21 @@
|
|||
<el-row>
|
||||
<el-form-item label="日期" prop="dateRange">
|
||||
<el-date-picker v-model="form2.dateRange" style="width: 100%" value-format="yyyy-MM-dd" type="daterange"
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
|
||||
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
<el-row class="button-row">
|
||||
<el-col class="button-col">
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.考勤人员列表<br>2.基模版数据生成
|
||||
</template>
|
||||
<el-button style="margin-left: 10px;" type="primary" plain @click="operMethod(1)">1.模版数据(必须)</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.旷工判断
|
||||
</template>
|
||||
<el-button type="primary" plain @click="operMethod(3)">3.旷工更新(非必)</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.请假数据更新<br>2.更新到前15天<br>3.范围更新只更新最后一天
|
||||
</template>
|
||||
<el-button type="primary" plain @click="operMethod(5)">5.请假日更新(非必)</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.月报表模版生成
|
||||
</template>
|
||||
<el-button type="primary" plain @click="operMethod(7)">7.月报表模版(非必)</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col class="button-col">
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.考勤数据拉取<br>2.考勤数据更新
|
||||
</template>
|
||||
<el-button type="primary" style="margin-left: 10px;" plain @click="operMethod(2)">2.数据拉取(必须)</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.法假节假日更新
|
||||
</template>
|
||||
<el-button type="primary" plain @click="operMethod(4)">4.法假更新(非必)</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.日报表数据生成<br>2.每次更新数据都要执行
|
||||
</template>
|
||||
<el-button type="primary" plain @click="operMethod(6)">6.日报表更新(必须)</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="right">
|
||||
<template #content>
|
||||
1.月报表更新
|
||||
</template>
|
||||
<el-button type="primary" plain @click="operMethod(8)">8.月报表更新(必须)</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-row style="margin-top: 10px;">
|
||||
<el-button type="primary" plain @click="operMethod(1)">1.模版数据(必须)</el-button>
|
||||
<el-button type="primary" plain @click="operMethod(2)">2.数据拉取(必须)</el-button>
|
||||
<el-button type="primary" plain @click="operMethod(3)">3.旷工更新(非必)</el-button>
|
||||
<el-button type="primary" plain @click="operMethod(4)">4.法假更新(非必)</el-button>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 10px;">
|
||||
<el-button type="primary" plain @click="operMethod(5)">5.请假日更新(非必)</el-button>
|
||||
<el-button type="primary" plain @click="operMethod(6)">6.日报表更新(必须)</el-button>
|
||||
<el-button type="primary" plain @click="operMethod(7)">7.月报表模版(非必)</el-button>
|
||||
<el-button type="primary" plain @click="operMethod(8)">8.月报表更新(必须)</el-button>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
|
|
@ -303,6 +333,12 @@
|
|||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="文件预览" :visible.sync="fileView" width="1200px" height="1200px" >
|
||||
<bns-kk-file-preview :items="kkFilePreview">
|
||||
|
||||
</bns-kk-file-preview>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -324,17 +360,18 @@ import {
|
|||
insertDayReportData,
|
||||
insertMonthReportTempData,
|
||||
updateMonthReportData,
|
||||
} from "@/api/report/attReport";
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import { checkPersonAssignment } from "@/api/system/userInfo";
|
||||
import { getDetail } from "@/api/report/monthlyError";
|
||||
import { Tooltip } from 'element-ui';
|
||||
singleUploadFile
|
||||
} from '@/api/report/attReport'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import BnsKkFilePreview from '@/views/bns-kkFile-preview'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import { checkPersonAssignment } from '@/api/system/userInfo'
|
||||
import { getDetail } from '@/api/report/monthlyError'
|
||||
|
||||
export default {
|
||||
name: "AttDetails",
|
||||
name: 'AttDetails',
|
||||
dicts: ['att_status'],
|
||||
components: { Treeselect },
|
||||
components: { Treeselect,BnsKkFilePreview },
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
|
|
@ -352,7 +389,7 @@ export default {
|
|||
// 字典表格数据
|
||||
typeList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
dialogList: [],
|
||||
|
|
@ -373,7 +410,7 @@ export default {
|
|||
pageSize: 10,
|
||||
userId: undefined,
|
||||
attCurrentDay: undefined,
|
||||
userName: undefined,
|
||||
userName: undefined
|
||||
},
|
||||
showOutCount: false,
|
||||
totalTwo: 0,
|
||||
|
|
@ -381,13 +418,12 @@ export default {
|
|||
loadingTwo: false,
|
||||
tableDataOutCount: [],
|
||||
|
||||
|
||||
queryAttCount: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userId: undefined,
|
||||
attCurrentDay: undefined,
|
||||
userName: undefined,
|
||||
userName: undefined
|
||||
},
|
||||
showAttCount: false,
|
||||
totalAttCount: 0,
|
||||
|
|
@ -397,58 +433,65 @@ export default {
|
|||
dataAyscTitle: '数据同步',
|
||||
dataAyscOpen: false,
|
||||
form2: {
|
||||
dateRange:[this.getToday(),this.getToday()]
|
||||
dateRange: [this.getToday(), this.getToday()]
|
||||
},
|
||||
};
|
||||
|
||||
fileView: false,
|
||||
fileData:[],
|
||||
kkFilePreview: {
|
||||
filePreviewUrl: "http://192.168.0.14:31909/file/ynRealName/proFile/2025/02/19/5bb40b949c3b490b85540e6289a24c962.docx",
|
||||
fileName: "aaaa.docx",
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getWeekDates();
|
||||
this.getDeptList();
|
||||
this.getList();
|
||||
this.getWeekDates()
|
||||
this.getDeptList()
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getWeekDates() {
|
||||
const now = new Date();
|
||||
const dayOfWeek = now.getDay();
|
||||
const dayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
||||
const now = new Date()
|
||||
const dayOfWeek = now.getDay()
|
||||
const dayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek
|
||||
|
||||
const monday = new Date(now);
|
||||
monday.setDate(monday.getDate() + dayOffset);
|
||||
const monday = new Date(now)
|
||||
monday.setDate(monday.getDate() + dayOffset)
|
||||
|
||||
const sunday = new Date(monday);
|
||||
sunday.setDate(sunday.getDate() + 6);
|
||||
this.dateRange[0] = monday.toISOString().split('T')[0];
|
||||
this.dateRange[1] = sunday.toISOString().split('T')[0];
|
||||
const sunday = new Date(monday)
|
||||
sunday.setDate(sunday.getDate() + 6)
|
||||
this.dateRange[0] = monday.toISOString().split('T')[0]
|
||||
this.dateRange[1] = sunday.toISOString().split('T')[0]
|
||||
},
|
||||
formatDate(dateString) {
|
||||
const date = new Date(dateString); // 创建日期对象
|
||||
const year = date.getFullYear(); // 获取年份
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); // 获取月份(注意:月份从0开始)
|
||||
const day = String(date.getDate()).padStart(2, '0'); // 获取日期
|
||||
const weekdays = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; // 星期几数组
|
||||
const weekday = weekdays[date.getDay()]; // 获取星期几
|
||||
const date = new Date(dateString) // 创建日期对象
|
||||
const year = date.getFullYear() // 获取年份
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0') // 获取月份(注意:月份从0开始)
|
||||
const day = String(date.getDate()).padStart(2, '0') // 获取日期
|
||||
const weekdays = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'] // 星期几数组
|
||||
const weekday = weekdays[date.getDay()] // 获取星期几
|
||||
|
||||
return `${year}-${month}-${day} ${weekday}`; // 组合成所需格式
|
||||
return `${year}-${month}-${day} ${weekday}` // 组合成所需格式
|
||||
},
|
||||
getDeptList() {
|
||||
listDept().then(response => {
|
||||
this.deptOptions = this.handleTree(response.data, "id");
|
||||
});
|
||||
this.deptOptions = this.handleTree(response.data, 'id')
|
||||
})
|
||||
},
|
||||
/** 转换部门数据结构 */
|
||||
normalizer(node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children;
|
||||
delete node.children
|
||||
}
|
||||
return {
|
||||
id: node.id,
|
||||
label: node.orgName,
|
||||
children: node.children
|
||||
};
|
||||
}
|
||||
},
|
||||
/** 查询字典类型列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
console.log(this.dateRange)
|
||||
if (this.dateRange && this.dateRange.length > 0) {
|
||||
this.queryParams.startDate = this.dateRange[0]
|
||||
|
|
@ -458,89 +501,105 @@ export default {
|
|||
this.queryParams.endDate = undefined
|
||||
}
|
||||
getDetailsList(this.queryParams).then(response => {
|
||||
this.typeList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
this.typeList = response.rows
|
||||
this.total = response.total
|
||||
this.loading = false
|
||||
}
|
||||
)
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.getWeekDates();
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
this.getWeekDates()
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.dialogList = selection.slice();
|
||||
this.dialogList = selection.slice()
|
||||
},
|
||||
openDialog() {
|
||||
console.log(this.dialogList)
|
||||
if (this.dialogList.length > 0) {
|
||||
this.open = true;
|
||||
this.dialogListOld = JSON.parse(JSON.stringify(this.dialogList));
|
||||
this.open = true
|
||||
this.dialogListOld = JSON.parse(JSON.stringify(this.dialogList))
|
||||
} else {
|
||||
this.$message({ message: '请先勾选数据!', type: 'warning' })
|
||||
}
|
||||
},
|
||||
openData() {
|
||||
this.dataAyscOpen = true;
|
||||
this.dataAyscOpen = true
|
||||
},
|
||||
getToday() {
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
const date = new Date()
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
},
|
||||
operMethod(type){
|
||||
operMethod(type) {
|
||||
const query = {
|
||||
startDate:this.form2.dateRange[0],
|
||||
endDate:this.form2.dateRange[1],
|
||||
startDate: this.form2.dateRange[0],
|
||||
endDate: this.form2.dateRange[1]
|
||||
}
|
||||
let loading = this.$loading({
|
||||
lock: true,
|
||||
text: "数据同步中,请稍候...",
|
||||
text: '数据同步中,请稍候...',
|
||||
background: 'rgba(0,0,0,0.2)'
|
||||
})
|
||||
if(type === 1){
|
||||
getAttTempData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 2){
|
||||
getAttDataPull(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 3){
|
||||
getAbsenteeismData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 4){
|
||||
getLegalHolidayData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 5){
|
||||
getLeaveData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 6){
|
||||
insertDayReportData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 7){
|
||||
insertMonthReportTempData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
}else if(type === 8){
|
||||
updateMonthReportData(query).then(res=>{
|
||||
loading.close();
|
||||
}).catch(err=>{loading.close();});
|
||||
if (type === 1) {
|
||||
getAttTempData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 2) {
|
||||
getAttDataPull(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 3) {
|
||||
getAbsenteeismData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 4) {
|
||||
getLegalHolidayData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 5) {
|
||||
getLeaveData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 6) {
|
||||
insertDayReportData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 7) {
|
||||
insertMonthReportTempData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
} else if (type === 8) {
|
||||
updateMonthReportData(query).then(res => {
|
||||
loading.close()
|
||||
}).catch(err => {
|
||||
loading.close()
|
||||
})
|
||||
}
|
||||
},
|
||||
openData2() {
|
||||
|
|
@ -557,23 +616,23 @@ export default {
|
|||
this.$modal.confirm(`是否开始数据同步"${this.queryParams.startDate}~${this.queryParams.endDate}"的数据项?`)
|
||||
.then(() => {
|
||||
// 开启加载状态
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
|
||||
// 执行同步操作
|
||||
return synchronous(param);
|
||||
return synchronous(param)
|
||||
})
|
||||
.then(response => {
|
||||
// 同步成功后关闭加载状态并显示成功信息
|
||||
this.loading = false;
|
||||
this.$modal.msgSuccess("数据同步成功");
|
||||
this.loading = false
|
||||
this.$modal.msgSuccess('数据同步成功')
|
||||
})
|
||||
.catch(error => {
|
||||
// 处理任何可能发生的错误,包括确认对话框被取消的情况
|
||||
this.loading = false; // 确保加载状态关闭
|
||||
this.loading = false // 确保加载状态关闭
|
||||
if (error && error !== 'cancel') {
|
||||
this.$modal.msgError("数据同步失败:" + error.message || "未知错误");
|
||||
this.$modal.msgError('数据同步失败:' + error.message || '未知错误')
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
this.$message({ message: '请先选择日期!', type: 'warning' })
|
||||
}
|
||||
|
|
@ -581,29 +640,32 @@ export default {
|
|||
|
||||
submitEdit() {
|
||||
let paramList = []
|
||||
let hasError = false;
|
||||
let hasError = false
|
||||
|
||||
this.dialogList.forEach((newItem, index) => {
|
||||
const oldItem = this.dialogListOld[index];
|
||||
const oldItem = this.dialogListOld[index]
|
||||
|
||||
|
||||
// 检查toWorkAttCurrentTime或toWorkAttStatus是否改变
|
||||
if ((newItem.toWorkAttCurrentTime !== oldItem.toWorkAttCurrentTime || newItem.toWorkAttStatus !== oldItem.toWorkAttStatus) &&
|
||||
(!newItem.toErrorRemake || newItem.toErrorRemake === "")) {
|
||||
hasError = true;
|
||||
this.$message({ message: '上班时间或状态改变时,原因说明不能为空!', type: 'warning' });
|
||||
(!newItem.toErrorRemake || newItem.toErrorRemake === '' || !this.hasAttachments(newItem.filesVoList, '1') )) {
|
||||
hasError = true
|
||||
this.$message({ message: '上班时间或状态改变时,原因说明、附件不能为空!', type: 'warning' })
|
||||
}
|
||||
|
||||
// 检查offWorkAttCurrentTime或offWorkAttStatus是否改变
|
||||
if ((newItem.offWorkAttCurrentTime !== oldItem.offWorkAttCurrentTime || newItem.offWorkAttStatus !== oldItem.offWorkAttStatus) &&
|
||||
(!newItem.offErrorRemake || newItem.offErrorRemake === "")) {
|
||||
hasError = true;
|
||||
this.$message({ message: '下班时间或状态改变时,原因说明不能为空!', type: 'warning' });
|
||||
(!newItem.offErrorRemake || newItem.offErrorRemake === '' || !this.hasAttachments(newItem.filesVoList, '1') )) {
|
||||
hasError = true
|
||||
this.$message({ message: '下班时间或状态改变时,原因说明、附件不能为空!', type: 'warning' })
|
||||
}
|
||||
|
||||
|
||||
// 如果没有错误,则构建参数对象
|
||||
if (!hasError) {
|
||||
let obj = {
|
||||
userId: newItem.userId,
|
||||
userName:newItem.userName,
|
||||
orgId: newItem.orgId,
|
||||
attCurrentDay: newItem.attCurrentDay,
|
||||
toWorkAttCurrentTime: newItem.toWorkAttCurrentTime,
|
||||
|
|
@ -612,76 +674,81 @@ export default {
|
|||
offWorkAttCurrentTime: newItem.offWorkAttCurrentTime,
|
||||
offWorkAttStatus: newItem.offWorkAttStatus,
|
||||
offErrorRemake: newItem.offErrorRemake,
|
||||
};
|
||||
paramList.push(obj);
|
||||
filesVoList: newItem.filesVoList
|
||||
}
|
||||
paramList.push(obj)
|
||||
}
|
||||
});
|
||||
})
|
||||
console.log("aa=",paramList)
|
||||
if (!hasError) {
|
||||
updateAttDetails(paramList).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.$modal.msgSuccess("修改申请提交成功,耐心等待审批,请勿重复提交!");
|
||||
this.dialogList = [];
|
||||
this.open = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess('修改申请提交成功,耐心等待审批,请勿重复提交!')
|
||||
this.dialogList = []
|
||||
this.open = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.$message({ message: '修改申请提交失败!', type: 'warning' });
|
||||
this.$message({ message: response.msg, type: 'warning' })
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
// 如果存在错误,则不清空或提交数据
|
||||
console.log("存在错误,未提交数据。");
|
||||
console.log('存在错误,未提交数据。')
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.getList();
|
||||
this.open = false;
|
||||
this.getList()
|
||||
this.open = false
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.queryParams.exportType = "考勤明细"
|
||||
this.queryParams.exportType = '考勤明细'
|
||||
exportAttRecord(this.queryParams).then(res => {
|
||||
this.downloadFile({ fileName: `考勤记录_${new Date().getTime()}.xlsx`, fileData: res, fileType: 'application/vnd.ms-excel;charset=utf-8' })
|
||||
this.downloadFile({
|
||||
fileName: `考勤记录_${new Date().getTime()}.xlsx`,
|
||||
fileData: res,
|
||||
fileType: 'application/vnd.ms-excel;charset=utf-8'
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
//打开工作时间外出次数
|
||||
openOutCountList(row) {
|
||||
this.title = "工作时间外出次数";
|
||||
this.queryRecord.userId = row.userId;
|
||||
this.queryRecord.attCurrentDay = row.attCurrentDay;
|
||||
this.showOutCount = true;
|
||||
this.getOutCountList();
|
||||
this.title = '工作时间外出次数'
|
||||
this.queryRecord.userId = row.userId
|
||||
this.queryRecord.attCurrentDay = row.attCurrentDay
|
||||
this.showOutCount = true
|
||||
this.getOutCountList()
|
||||
},
|
||||
|
||||
/** 查询工作时间外出次数列表 */
|
||||
getOutCountList() {
|
||||
this.loadingTwo = true;
|
||||
this.loadingTwo = true
|
||||
getOutCountList(this.queryRecord).then(response => {
|
||||
this.tableDataOutCount = response.rows;
|
||||
this.totalTwo = response.total;
|
||||
this.loadingTwo = false;
|
||||
});
|
||||
this.tableDataOutCount = response.rows
|
||||
this.totalTwo = response.total
|
||||
this.loadingTwo = false
|
||||
})
|
||||
},
|
||||
|
||||
//打开打卡次数记录
|
||||
openAttCountList(row) {
|
||||
this.title = "打卡记录";
|
||||
this.queryAttCount.userId = row.userId;
|
||||
this.queryAttCount.userName = row.userName;
|
||||
this.queryAttCount.attCurrentDay = row.attCurrentDay;
|
||||
this.showAttCount = true;
|
||||
this.getAttCountList();
|
||||
this.title = '打卡记录'
|
||||
this.queryAttCount.userId = row.userId
|
||||
this.queryAttCount.userName = row.userName
|
||||
this.queryAttCount.attCurrentDay = row.attCurrentDay
|
||||
this.showAttCount = true
|
||||
this.getAttCountList()
|
||||
},
|
||||
|
||||
/** 查询打卡次数记录列表 */
|
||||
getAttCountList() {
|
||||
this.loadingAttCount = true;
|
||||
this.loadingAttCount = true
|
||||
getAttCountList(this.queryAttCount).then(response => {
|
||||
this.tableDataAttCount = response.rows;
|
||||
this.totalAttCount = response.total;
|
||||
this.loadingAttCount = false;
|
||||
});
|
||||
this.tableDataAttCount = response.rows
|
||||
this.totalAttCount = response.total
|
||||
this.loadingAttCount = false
|
||||
})
|
||||
},
|
||||
|
||||
/** 导出按钮操作 */
|
||||
|
|
@ -695,8 +762,74 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
//先上传文件
|
||||
async requestUpload(options, rowIndex, attType) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', options.file)
|
||||
try {
|
||||
const response = await singleUploadFile(formData)
|
||||
if (response.code == '200' || response.code == 200) {
|
||||
var fileName = response.data.fileName
|
||||
var filePath = response.data.filePath
|
||||
|
||||
this.updateFilesVoList(rowIndex, fileName, filePath, attType);
|
||||
} else {
|
||||
this.$message.success(response.msg)
|
||||
}
|
||||
// 更新uploadedFiles或其他必要的操作
|
||||
} catch (error) {
|
||||
this.$message.error('文件上传失败')
|
||||
}
|
||||
},
|
||||
|
||||
previewFile(filePath) {
|
||||
// 根据文件路径打开预览窗口
|
||||
this.fileView= true;
|
||||
this.fileData = filePath;
|
||||
this.kkFilePreview = {
|
||||
// filePreviewUrl: filePath.data[0].filePath,
|
||||
// fileName: filePath.data[0].fileName,
|
||||
filePreviewUrl: "http://192.168.0.14:31909/file/ynRealName/proFile/2025/02/19/5bb40b949c3b490b85540e6289a24c962.docx",
|
||||
fileName: "aaaa.docx",
|
||||
showDownloadButton: false
|
||||
}
|
||||
console.log(this.kkFilePreview)
|
||||
},
|
||||
|
||||
//获取对应的文件名称
|
||||
getFileName(filesVoList, attType) {
|
||||
if (!filesVoList) return '';
|
||||
const file = filesVoList.find(file => file.attType === attType);
|
||||
return file ? file.fileName : '';
|
||||
},
|
||||
//获取对应的文件路径
|
||||
getFilePath(filesVoList, attType) {
|
||||
if (!filesVoList) return '';
|
||||
const file = filesVoList.find(file => file.attType === attType);
|
||||
return file ? file.filePath : '';
|
||||
},
|
||||
//更新对应的文件名称,路径
|
||||
updateFilesVoList(rowIndex, fileName, filePath, attType) {
|
||||
const row = this.dialogList[rowIndex];
|
||||
if (!row.filesVoList) {
|
||||
this.$set(row, 'filesVoList', []);
|
||||
}
|
||||
const existingFile = row.filesVoList.find(file => file.attType == attType);
|
||||
if (existingFile) {
|
||||
existingFile.fileName = fileName;
|
||||
existingFile.filePath = filePath;
|
||||
} else {
|
||||
row.filesVoList.push({ fileName, filePath, attType });
|
||||
}
|
||||
},
|
||||
|
||||
hasAttachments(filesVoList, attType) {
|
||||
if (!filesVoList) return false;
|
||||
return filesVoList.some(file => file.attType === attType);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -708,20 +841,4 @@ export default {
|
|||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.button-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 48%;
|
||||
}
|
||||
.button-col .el-button {
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue