考勤明细修改审批流程更改,增加上传附件字段

This commit is contained in:
lSun 2025-02-19 19:30:44 +08:00
parent 6abb87b4ca
commit d7bec1d23f
7 changed files with 870 additions and 258 deletions

View File

@ -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
})
}

56
src/utils/base64Utils.js Normal file
View File

@ -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;

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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>

View File

@ -406,7 +406,7 @@
//
this.open = true;
this.isView = false;
this.title = "编辑";
this.title = "审核";
});
},
handleView(row) {

View File

@ -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]
// toWorkAttCurrentTimetoWorkAttStatus
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' })
}
// offWorkAttCurrentTimeoffWorkAttStatus
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>