gz-att-web-new/src/views/report/attReport/index.vue

1012 lines
38 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container" id="attDetails">
<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"
/>
</el-form-item>
<el-form-item label="部门" prop="orgIdList">
<treeselect v-model="queryParams.orgIdList" :options="deptOptions" :normalizer="normalizer" placeholder="选择部门"
style="width: 240px" :multiple="true"
/>
</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-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>
</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="warning" icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['att:attReport:export']"
>导出
</el-button>
<el-button type="warning" icon="el-icon-download" size="mini" @click="abnormalRankingExport"
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>
</el-form>
<el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col> -->
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
<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="attCurrentDay" width="180" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ formatDate(scope.row.attCurrentDay) }}</span>
</template>
</el-table-column>
<el-table-column label="工作时间外出次数" align="center" prop="normalNum" width="180">
<template slot-scope="scope">
<div @click="openOutCountList(scope.row)" style="color: #02a7f0; cursor: pointer">
{{ scope.row.outCount }}
</div>
</template>
</el-table-column>
<el-table-column label="打卡记录" align="center" prop="normalNum">
<template slot-scope="scope">
<div @click="openAttCountList(scope.row)" style="color: #02a7f0; cursor: pointer">
{{ scope.row.attCount }}
</div>
</template>
</el-table-column>
<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"/>
</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="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"/>
</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>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@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="考勤日期" align="center" prop="attCurrentDay" :show-overflow-tooltip="true" width="180"
fixed
>
<template slot-scope="scope">
<span>{{ formatDate(scope.row.attCurrentDay) }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="toWorkAttCurrentTime" width="240">
<template slot="header">
<span class="required-star">*</span> 修改上班时间
</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="选择上班时间"
>
</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%"
>
<el-option v-for="dict in dict.type.att_status" :key="dict.value" :label="dict.label"
: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;color: #29C9C9 " v-if="getFileName(scope.row.filesVoList, '1')" @click="previewFile(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"
/>
<el-table-column align="center" prop="toErrorRemake" width="200">
<template slot="header">
<span class="required-star">*</span> 原因说明
</template>
<template slot-scope="scope">
<el-input type="textarea" v-model="scope.row.toErrorRemake" maxlength="100"></el-input>
</template>
</el-table-column>
<el-table-column align="center" prop="offWorkAttCurrentTime" width="240">
<template slot="header">
<span class="required-star">*</span> 修改下班时间
</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="选择下班时间"
>
</el-date-picker>
</template>
</el-table-column>
<el-table-column align="center" prop="offWorkAttStatus" width="180">
<template slot="header">
<span class="required-star">*</span> 修改下班状态
</template>
<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"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="打卡地址" align="center" prop="offWorkAttAddress" :show-overflow-tooltip="true"
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;color: #29C9C9" v-if="getFileName(scope.row.filesVoList, '2')" @click="previewFile(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> 原因说明
</template>
<template slot-scope="scope">
<el-input type="textarea" v-model="scope.row.offErrorRemake" maxlength="100"></el-input>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitEdit">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- 外出次数查询 -->
<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"
>
<el-form-item>
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExportOutCountList">导出
</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loadingTwo" :data="tableDataOutCount" width="900px" height="600px" row-key="id">
<el-table-column label="序号" align="center" width="80" type="index">
<template slot-scope="scope">
<span>{{ (queryRecord.pageNum - 1) * queryRecord.pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="考勤日期" align="center" prop="attCurrentDay" :show-overflow-tooltip="true">
<template slot-scope="scope">
<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>
<pagination v-show="totalTwo > 0" :total="totalTwo" :page.sync="queryRecord.pageNum"
: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"
>
<el-form-item>
<!-- <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>-->
</el-form-item>
</el-form>
<el-table v-loading="loadingAttCount" :data="tableDataAttCount" width="900px" height="600px" row-key="id">
<el-table-column label="序号" align="center" width="80" type="index">
<template slot-scope="scope">
<span>{{ (queryAttCount.pageNum - 1) * queryAttCount.pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="考勤日期" align="center" prop="attCurrentDay" :show-overflow-tooltip="true">
<template slot-scope="scope">
<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>
<pagination v-show="totalAttCount > 0" :total="totalAttCount" :page.sync="queryAttCount.pageNum"
:limit.sync="queryAttCount.pageSize" @pagination="getAttCountList"
/>
</el-dialog>
<!-- 数据同步对话框 -->
<el-dialog :title="dataAyscTitle" :visible.sync="dataAyscOpen" width="500px" append-to-body>
<el-form ref="form2" :model="form2" label-width="80px">
<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>
</el-form-item>
</el-row>
<el-row class="button-row">
<el-col class="button-col">
<el-tooltip placement="left">
<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="left">
<template #content>
1.每日是否旷工判断<br>2.每日的数据都会在当天更新,后续无需手动更新
</template>
<el-button type="primary" plain @click="operMethod(3)">3.旷工更新(非必)</el-button>
</el-tooltip>
<el-tooltip placement="left">
<template #content>
1.请假数据更新<br>2.更新到前15天<br>3.范围更新只更新最后一天<br>4.日月报表必须紧随它更新
</template>
<el-button type="primary" plain @click="operMethod(5)">5.请假日更新(非必)</el-button>
</el-tooltip>
<el-tooltip placement="left">
<template #content>
1.月报表模版生成<br>2.每月的数据都会月初生成
</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>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dataAyscOpen = !dataAyscOpen">取 消</el-button>
</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>
<script>
import {
getDetailsList,
updateAttDetails,
exportAttRecord,
exportAbnormalRanking,
synchronous,
listDept,
getOutCountList,
getAttCountList,
exportOutCountList,
getAttTempData,
getAttDataPull,
getAbsenteeismData,
getLegalHolidayData,
getLeaveData,
insertDayReportData,
insertMonthReportTempData,
updateMonthReportData,
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'
import { getToken } from '@/utils/auth'
export default {
name: 'AttDetails',
dicts: ['att_status'],
components: { Treeselect,BnsKkFilePreview },
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 字典表格数据
typeList: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
dialogList: [],
dialogListOld: [],
// 日期范围
dateRange: [],
deptOptions: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
orgIdList: undefined,
attStatus: undefined,
orgIds:undefined
},
queryRecord: {
pageNum: 1,
pageSize: 10,
userId: undefined,
attCurrentDay: undefined,
userName: undefined
},
showOutCount: false,
totalTwo: 0,
// 遮罩层
loadingTwo: false,
tableDataOutCount: [],
queryAttCount: {
pageNum: 1,
pageSize: 10,
userId: undefined,
attCurrentDay: undefined,
userName: undefined
},
showAttCount: false,
totalAttCount: 0,
// 遮罩层
loadingAttCount: false,
tableDataAttCount: [],
dataAyscTitle: '数据同步',
dataAyscOpen: false,
form2: {
dateRange: [this.getToday(), this.getToday()]
},
fileView: false,
fileData:[],
kkFilePreview: {
filePreviewUrl: undefined,
fileName: undefined,
}
}
},
created() {
this.getWeekDates()
this.getDeptList()
this.getList()
},
methods: {
getWeekDates() {
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 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()] // 获取星期几
return `${year}-${month}-${day} ${weekday}` // 组合成所需格式
},
getDeptList() {
listDept().then(response => {
this.deptOptions = this.handleTree(response.data, 'id')
})
},
/** 转换部门数据结构 */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children
}
return {
id: node.id,
label: node.orgName,
children: node.children
}
},
/** 查询字典类型列表 */
getList() {
this.loading = true
console.log(this.dateRange)
if (this.dateRange && this.dateRange.length > 0) {
this.queryParams.startDate = this.dateRange[0]
this.queryParams.endDate = this.dateRange[1]
} else {
this.queryParams.startDate = undefined
this.queryParams.endDate = undefined
}
if (this.queryParams.orgIdList && this.queryParams.orgIdList.length > 0) {
// 将数组中的每个元素转换为字符串(如果需要)
this.queryParams.orgIds = this.queryParams.orgIdList.map(id => id.toString());
}else{
this.queryParams.orgIds = undefined
}
getDetailsList(this.queryParams).then(response => {
this.typeList = response.rows
this.total = response.total
this.loading = false
}
)
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.getWeekDates()
this.resetForm('queryForm')
this.queryParams.orgIdList =undefined
this.queryParams.orgIds = undefined
this.handleQuery()
},
// 多选框选中数据
handleSelectionChange(selection) {
this.dialogList = selection.slice()
},
openDialog() {
if (this.dialogList.length > 0) {
this.dialogList.forEach(item => {
item.filesVoList = [];
item.toErrorRemake = "";
item.offErrorRemake = "";
});
console.log(this.dialogList)
this.open = true
this.dialogListOld = JSON.parse(JSON.stringify(this.dialogList))
} else {
this.$message({ message: '请先勾选数据!', type: 'warning' })
}
},
openData() {
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}`
},
operMethod(type) {
const query = {
startDate: this.form2.dateRange[0],
endDate: this.form2.dateRange[1]
}
let loading = this.$loading({
lock: true,
text: '数据同步中,请稍候...',
background: 'rgba(0,0,0,0.2)'
})
if (type === 1) {
getAttTempData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 2) {
getAttDataPull(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 3) {
getAbsenteeismData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 4) {
getLegalHolidayData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 5) {
getLeaveData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 6) {
insertDayReportData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 7) {
insertMonthReportTempData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
} else if (type === 8) {
updateMonthReportData(query).then(res => {
loading.close()
if(res.code === 200){
this.$message({ message: '数据同步成功', type:'success' })
}else{
this.$message({ message: '数据同步失败', type: 'error' })
}
}).catch(err => {
loading.close()
})
}
},
openData2() {
if (this.dateRange && this.dateRange.length > 0) {
this.queryParams.startDate = this.dateRange[0]
this.queryParams.endDate = this.dateRange[1]
let param = {
startDate: this.queryParams.startDate,
endDate: this.queryParams.endDate,
id: '1'
}
console.log(param)
this.$modal.confirm(`是否开始数据同步"${this.queryParams.startDate}~${this.queryParams.endDate}"的数据项?`)
.then(() => {
// 开启加载状态
this.loading = true
// 执行同步操作
return synchronous(param)
})
.then(response => {
// 同步成功后关闭加载状态并显示成功信息
this.loading = false
this.$modal.msgSuccess('数据同步成功')
})
.catch(error => {
// 处理任何可能发生的错误,包括确认对话框被取消的情况
this.loading = false // 确保加载状态关闭
if (error && error !== 'cancel') {
this.$modal.msgError('数据同步失败:' + error.message || '未知错误')
}
})
} else {
this.$message({ message: '请先选择日期!', type: 'warning' })
}
},
submitEdit() {
let paramList = []
let hasError = false
let hasChanges = false;
let isErrorMsg = '';
this.dialogList.some((newItem, index) => {
const oldItem = this.dialogListOld[index]
// 检查toWorkAttCurrentTime或toWorkAttStatus是否改变
if ((newItem.toWorkAttCurrentTime !== oldItem.toWorkAttCurrentTime || newItem.toWorkAttStatus !== oldItem.toWorkAttStatus) &&
(!newItem.toErrorRemake || newItem.toErrorRemake === '' || !this.hasAttachments(newItem.filesVoList, '1') )) {
hasError = true
// this.$message({ message: '上班时间或状态改变时,原因说明、附件不能为空!', type: 'warning' })
isErrorMsg = '上班时间或状态改变时,原因说明、附件不能为空!';
return true;
}
if(newItem.toErrorRemake!=""&&this.hasAttachments(newItem.filesVoList, '1')){
hasChanges = true
}
// 检查offWorkAttCurrentTime或offWorkAttStatus是否改变
if ((newItem.offWorkAttCurrentTime !== oldItem.offWorkAttCurrentTime || newItem.offWorkAttStatus !== oldItem.offWorkAttStatus) &&
(!newItem.offErrorRemake || newItem.offErrorRemake === '' || !this.hasAttachments(newItem.filesVoList, '2') )) {
hasError = true
// this.$message({ message: '下班时间或状态改变时,原因说明、附件不能为空!', type: 'warning' })
isErrorMsg = '下班时间或状态改变时,原因说明、附件不能为空!';
return true;
}
if(newItem.offErrorRemake!=""&&this.hasAttachments(newItem.filesVoList, '2')){
hasChanges = true
}
// 如果没有错误,则构建参数对象
if (!hasError) {
let obj = {
userId: newItem.userId,
userName:newItem.userName,
orgId: newItem.orgId,
attCurrentDay: newItem.attCurrentDay,
toWorkAttCurrentTime: newItem.toWorkAttCurrentTime,
toWorkAttStatus: newItem.toWorkAttStatus,
toErrorRemake: newItem.toErrorRemake,
offWorkAttCurrentTime: newItem.offWorkAttCurrentTime,
offWorkAttStatus: newItem.offWorkAttStatus,
offErrorRemake: newItem.offErrorRemake,
filesVoList: newItem.filesVoList
}
paramList.push(obj)
}
})
if(isErrorMsg){
return this.$message({ message: isErrorMsg, type: 'warning' })
}
console.log("aa=",paramList)
if(!hasChanges){
this.$message({ message: '没有数据变化,无需更新!', type: 'info' });
return;
}
if (!hasError) {
updateAttDetails(paramList).then(response => {
if (response.code === 200) {
this.$modal.msgSuccess('修改申请提交成功,耐心等待审批,请勿重复提交!')
this.dialogList = []
this.open = false
this.getList()
} else {
this.$message({ message: response.msg, type: 'warning' })
}
})
} else {
// 如果存在错误,则不清空或提交数据
console.log('存在错误,未提交数据。')
}
},
cancel() {
this.getList()
this.open = false
},
/** 导出按钮操作 */
handleExport() {
this.queryParams.exportType = '考勤明细'
if (this.queryParams.orgIdList && this.queryParams.orgIdList.length > 0) {
// 将数组中的每个元素转换为字符串(如果需要)
this.queryParams.orgIds = this.queryParams.orgIdList.map(id => id.toString());
}else{
this.queryParams.orgIds = undefined
}
exportAttRecord(this.queryParams).then(res => {
this.downloadFile({
fileName: `考勤记录_${new Date().getTime()}.xlsx`,
fileData: res,
fileType: 'application/vnd.ms-excel;charset=utf-8'
})
})
},
/** 异常排名导出 */
abnormalRankingExport() {
this.queryParams.exportType = '异常排名导出'
if (this.queryParams.orgIdList && this.queryParams.orgIdList.length > 0) {
// 将数组中的每个元素转换为字符串(如果需要)
this.queryParams.orgIds = this.queryParams.orgIdList.map(id => id.toString());
}else{
this.queryParams.orgIds = undefined
}
exportAbnormalRanking(this.queryParams).then(res => {
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()
},
/** 查询工作时间外出次数列表 */
getOutCountList() {
this.loadingTwo = true
getOutCountList(this.queryRecord).then(response => {
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()
},
/** 查询打卡次数记录列表 */
getAttCountList() {
this.loadingAttCount = true
getAttCountList(this.queryAttCount).then(response => {
this.tableDataAttCount = response.rows
this.totalAttCount = response.total
this.loadingAttCount = false
})
},
/** 导出按钮操作 */
handleExportOutCountList() {
exportOutCountList(this.queryRecord).then(res => {
this.downloadFile({
fileName: `工作时间外出次数记录_${new Date().getTime()}.xlsx`,
fileData: res,
fileType: 'application/vnd.ms-excel;charset=utf-8'
})
})
},
//先上传文件
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(filesVoList,type) {
var filePath = this.getFilePath(filesVoList, type);
var fileName = this.getFileName(filesVoList, type);
// var url_=this.$baseUrl + filePath +"?token="+ getToken();
// var url_ = "http://127.0.0.1:1810/statics" + filePath +"?token="+ getToken();
// window.open(url_)
var url_=this.$baseUrl + filePath ;
// 根据文件路径打开预览窗口
this.fileView= true;
this.kkFilePreview = {
filePreviewUrl: url_,
fileName: 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>
.required-star {
color: red;
}
.dialog-footer {
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>