fix
This commit is contained in:
@@ -1,121 +1,113 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="薪资导出" width="650px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
type="month"
|
||||
format="YYYY-M"
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="劳务日期锁定">
|
||||
<el-radio-group v-model="lockedLw">
|
||||
<el-radio :label="1">是</el-radio>
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<el-tag type="warning">选择是,则本月其他造单批次无法指定到当前月份。如需解锁,请前往「薪资导出记录」删除记录即可。</el-tag>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span v-if="showBtn" class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button type="primary" @click="exportSalaryData" :loading="btnLoading">导 出</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="visible" title="薪资导出" width="650px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker v-model="chooseDate" type="month" format="YYYY-M" value-format="YYYY-M" placeholder="请选择日期" @change="handleChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="劳务日期锁定">
|
||||
<el-radio-group v-model="lockedLw">
|
||||
<el-radio :label="1">是</el-radio>
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<el-tag type="warning">选择是,则本月其他造单批次无法指定到当前月份。如需解锁,请前往「薪资导出记录」删除记录即可。</el-tag>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span v-if="showBtn" class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button type="primary" @click="exportSalaryData" :loading="btnLoading">导 出</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import request from '/@/utils/request'
|
||||
import { ref } from 'vue';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import request from '/@/utils/request';
|
||||
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
const message = useMessage();
|
||||
|
||||
// 对话框显示状态
|
||||
const visible = ref(false)
|
||||
const visible = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const chooseDate = ref('')
|
||||
const showBtn = ref(false)
|
||||
const btnLoading = ref(false)
|
||||
const lockedLw = ref(1)
|
||||
const chooseDate = ref('');
|
||||
const showBtn = ref(false);
|
||||
const btnLoading = ref(false);
|
||||
const lockedLw = ref(1);
|
||||
|
||||
// 初始化
|
||||
const init = () => {
|
||||
chooseDate.value = ''
|
||||
showBtn.value = false
|
||||
btnLoading.value = false
|
||||
lockedLw.value = 1
|
||||
visible.value = true
|
||||
}
|
||||
chooseDate.value = '';
|
||||
showBtn.value = false;
|
||||
btnLoading.value = false;
|
||||
lockedLw.value = 1;
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 日期改变
|
||||
const handleChange = () => {
|
||||
if (chooseDate.value) {
|
||||
showBtn.value = true
|
||||
} else {
|
||||
showBtn.value = false
|
||||
}
|
||||
}
|
||||
if (chooseDate.value) {
|
||||
showBtn.value = true;
|
||||
} else {
|
||||
showBtn.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 下载文件
|
||||
const downLoadFile = async (url: string) => {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: url,
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
}
|
||||
return request({
|
||||
method: 'get',
|
||||
url: url,
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + Session.getToken(),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 导出薪资数据
|
||||
const exportSalaryData = async () => {
|
||||
if (!chooseDate.value) {
|
||||
message.warning('请选择日期')
|
||||
return
|
||||
}
|
||||
|
||||
btnLoading.value = true
|
||||
try {
|
||||
const res = await downLoadFile(`/professional/file/exportSalary?chooseDate=${chooseDate.value}&state=${lockedLw.value}`)
|
||||
|
||||
// 处理返回的文件流
|
||||
const blob = new Blob([res.data])
|
||||
const elink = document.createElement('a')
|
||||
elink.download = "薪资表.xls"
|
||||
elink.style.display = 'none'
|
||||
elink.href = URL.createObjectURL(blob)
|
||||
document.body.appendChild(elink)
|
||||
elink.click()
|
||||
URL.revokeObjectURL(elink.href) // 释放URL 对象
|
||||
document.body.removeChild(elink)
|
||||
|
||||
message.success('导出成功')
|
||||
visible.value = false
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '导出失败')
|
||||
} finally {
|
||||
btnLoading.value = false
|
||||
}
|
||||
}
|
||||
if (!chooseDate.value) {
|
||||
message.warning('请选择日期');
|
||||
return;
|
||||
}
|
||||
|
||||
btnLoading.value = true;
|
||||
try {
|
||||
const res = await downLoadFile(`/professional/file/exportSalary?chooseDate=${chooseDate.value}&state=${lockedLw.value}`);
|
||||
|
||||
// 处理返回的文件流
|
||||
const blob = new Blob([res.data]);
|
||||
const elink = document.createElement('a');
|
||||
elink.download = '薪资表.xls';
|
||||
elink.style.display = 'none';
|
||||
elink.href = URL.createObjectURL(blob);
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
URL.revokeObjectURL(elink.href); // 释放URL 对象
|
||||
document.body.removeChild(elink);
|
||||
|
||||
message.success('导出成功');
|
||||
visible.value = false;
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '导出失败');
|
||||
} finally {
|
||||
btnLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
init,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,170 +1,165 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="薪资导入" width="600px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
type="month"
|
||||
format="YYYY-M"
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-upload
|
||||
v-if="showUpload"
|
||||
:headers="headers"
|
||||
class="upload-demo"
|
||||
:action="url"
|
||||
:limit="1"
|
||||
:with-credentials="true"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<template #tip>
|
||||
<div class="el-upload-list__item-name">{{ fileName }}</div>
|
||||
</template>
|
||||
<el-button
|
||||
v-if="hasAuth('professional_salary_import')"
|
||||
size="small"
|
||||
type="primary">选择文件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button type="primary" @click="submitUpload" :loading="btnLoading">导入</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="visible" title="薪资导入" width="600px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
type="month"
|
||||
format="YYYY-M"
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-upload
|
||||
v-if="showUpload"
|
||||
:headers="headers"
|
||||
class="upload-demo"
|
||||
:action="url"
|
||||
:limit="1"
|
||||
:with-credentials="true"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<template #tip>
|
||||
<div class="el-upload-list__item-name">{{ fileName }}</div>
|
||||
</template>
|
||||
<el-button v-if="hasAuth('professional_salary_import')" size="small" type="primary">选择文件 </el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button type="primary" @click="submitUpload" :loading="btnLoading">导入</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useAuth } from '/@/hooks/auth'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import request from '/@/utils/request'
|
||||
import { ref, computed } from 'vue';
|
||||
import { useAuth } from '/@/hooks/auth';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import request from '/@/utils/request';
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'refreshData'): void
|
||||
}>()
|
||||
(e: 'refreshData'): void;
|
||||
}>();
|
||||
|
||||
const { hasAuth } = useAuth()
|
||||
const { hasAuth } = useAuth();
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
const message = useMessage();
|
||||
|
||||
// 对话框显示状态
|
||||
const visible = ref(false)
|
||||
const visible = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const chooseDate = ref('')
|
||||
const url = ref('')
|
||||
const showUpload = ref(false)
|
||||
const fileList = ref<any[]>([])
|
||||
const btnLoading = ref(false)
|
||||
const fileName = ref('')
|
||||
const files = ref<File | null>(null)
|
||||
const chooseDate = ref('');
|
||||
const url = ref('');
|
||||
const showUpload = ref(false);
|
||||
const fileList = ref<any[]>([]);
|
||||
const btnLoading = ref(false);
|
||||
const fileName = ref('');
|
||||
const files = ref<File | null>(null);
|
||||
|
||||
// 请求头
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
return {
|
||||
Authorization: 'Bearer ' + Session.getToken(),
|
||||
};
|
||||
});
|
||||
|
||||
// 日期改变
|
||||
const handleChange = () => {
|
||||
if (chooseDate.value) {
|
||||
showUpload.value = true
|
||||
url.value = `/professional/file/importTeacherPayslpi?chooseDate=${chooseDate.value}`
|
||||
} else {
|
||||
showUpload.value = false
|
||||
}
|
||||
}
|
||||
if (chooseDate.value) {
|
||||
showUpload.value = true;
|
||||
url.value = `/professional/file/importTeacherPayslpi?chooseDate=${chooseDate.value}`;
|
||||
} else {
|
||||
showUpload.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
const init = () => {
|
||||
fileList.value = []
|
||||
files.value = null
|
||||
fileName.value = ''
|
||||
chooseDate.value = ''
|
||||
showUpload.value = false
|
||||
visible.value = true
|
||||
}
|
||||
fileList.value = [];
|
||||
files.value = null;
|
||||
fileName.value = '';
|
||||
chooseDate.value = '';
|
||||
showUpload.value = false;
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 上传前验证
|
||||
const beforeUpload = (file: File) => {
|
||||
files.value = file
|
||||
const fileLast = file.name.split('.')
|
||||
const extension = fileLast[fileLast.length - 1] === 'xls'
|
||||
const extension2 = fileLast[fileLast.length - 1] === 'xlsx'
|
||||
const isLt2M = file.size / 1024 / 1024 < 20
|
||||
|
||||
if (!extension && !extension2) {
|
||||
message.warning('上传模板只能是 xls、xlsx格式!')
|
||||
return false
|
||||
}
|
||||
if (!isLt2M) {
|
||||
message.warning('上传模板大小不能超过 20MB!')
|
||||
return false
|
||||
}
|
||||
fileName.value = file.name
|
||||
return false // 返回false不会自动上传
|
||||
}
|
||||
files.value = file;
|
||||
const fileLast = file.name.split('.');
|
||||
const extension = fileLast[fileLast.length - 1] === 'xls';
|
||||
const extension2 = fileLast[fileLast.length - 1] === 'xlsx';
|
||||
const isLt2M = file.size / 1024 / 1024 < 20;
|
||||
|
||||
if (!extension && !extension2) {
|
||||
message.warning('上传模板只能是 xls、xlsx格式!');
|
||||
return false;
|
||||
}
|
||||
if (!isLt2M) {
|
||||
message.warning('上传模板大小不能超过 20MB!');
|
||||
return false;
|
||||
}
|
||||
fileName.value = file.name;
|
||||
return false; // 返回false不会自动上传
|
||||
};
|
||||
|
||||
// 导入提交
|
||||
const submitUpload = async () => {
|
||||
btnLoading.value = true
|
||||
if (fileName.value === "") {
|
||||
message.warning('请选择要上传的文件!')
|
||||
btnLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (!files.value) {
|
||||
message.warning('请选择要上传的文件!')
|
||||
btnLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const fileFormData = new FormData()
|
||||
fileFormData.append('file', files.value, fileName.value)
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: url.value,
|
||||
method: 'post',
|
||||
data: fileFormData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
|
||||
if (res.data.data && res.data.data.code == 1) {
|
||||
message.error(`导入失败,${res.data.data.title}: ${res.data.data.msg}`)
|
||||
} else {
|
||||
message.success("导入成功")
|
||||
visible.value = false
|
||||
emit('refreshData')
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '导入失败')
|
||||
} finally {
|
||||
btnLoading.value = false
|
||||
}
|
||||
}
|
||||
btnLoading.value = true;
|
||||
if (fileName.value === '') {
|
||||
message.warning('请选择要上传的文件!');
|
||||
btnLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!files.value) {
|
||||
message.warning('请选择要上传的文件!');
|
||||
btnLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const fileFormData = new FormData();
|
||||
fileFormData.append('file', files.value, fileName.value);
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: url.value,
|
||||
method: 'post',
|
||||
data: fileFormData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
|
||||
if (res.data.data && res.data.data.code == 1) {
|
||||
message.error(`导入失败,${res.data.data.title}: ${res.data.data.msg}`);
|
||||
} else {
|
||||
message.success('导入成功');
|
||||
visible.value = false;
|
||||
emit('refreshData');
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '导入失败');
|
||||
} finally {
|
||||
btnLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
init,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,172 +1,167 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="税金导入" width="600px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
type="month"
|
||||
format="YYYY-M"
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-upload
|
||||
v-if="showUpload"
|
||||
:headers="headers"
|
||||
class="upload-demo"
|
||||
:action="url"
|
||||
:limit="1"
|
||||
:with-credentials="true"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<template #tip>
|
||||
<div class="el-upload-list__item-name">{{ fileName }}</div>
|
||||
</template>
|
||||
<el-button
|
||||
v-if="hasAuth('professional_salary_import')"
|
||||
size="small"
|
||||
type="primary">选择文件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button type="primary" @click="submitUpload" :loading="btnLoading">导入</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="visible" title="税金导入" width="600px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
type="month"
|
||||
format="YYYY-M"
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-upload
|
||||
v-if="showUpload"
|
||||
:headers="headers"
|
||||
class="upload-demo"
|
||||
:action="url"
|
||||
:limit="1"
|
||||
:with-credentials="true"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<template #tip>
|
||||
<div class="el-upload-list__item-name">{{ fileName }}</div>
|
||||
</template>
|
||||
<el-button v-if="hasAuth('professional_salary_import')" size="small" type="primary">选择文件 </el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button type="primary" @click="submitUpload" :loading="btnLoading">导入</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useAuth } from '/@/hooks/auth'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import request from '/@/utils/request'
|
||||
import { ref, computed } from 'vue';
|
||||
import { useAuth } from '/@/hooks/auth';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import request from '/@/utils/request';
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'refreshData'): void
|
||||
}>()
|
||||
(e: 'refreshData'): void;
|
||||
}>();
|
||||
|
||||
// 无权限即无节点
|
||||
const { hasAuth } = useAuth()
|
||||
const { hasAuth } = useAuth();
|
||||
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
const message = useMessage();
|
||||
|
||||
// 对话框显示状态
|
||||
const visible = ref(false)
|
||||
const visible = ref(false);
|
||||
|
||||
// 表单数据
|
||||
const chooseDate = ref('')
|
||||
const url = ref('')
|
||||
const showUpload = ref(false)
|
||||
const fileList = ref<any[]>([])
|
||||
const btnLoading = ref(false)
|
||||
const fileName = ref('')
|
||||
const files = ref<File | null>(null)
|
||||
const chooseDate = ref('');
|
||||
const url = ref('');
|
||||
const showUpload = ref(false);
|
||||
const fileList = ref<any[]>([]);
|
||||
const btnLoading = ref(false);
|
||||
const fileName = ref('');
|
||||
const files = ref<File | null>(null);
|
||||
|
||||
// 请求头
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
return {
|
||||
Authorization: 'Bearer ' + Session.getToken(),
|
||||
};
|
||||
});
|
||||
|
||||
// 日期改变
|
||||
const handleChange = () => {
|
||||
if (chooseDate.value) {
|
||||
showUpload.value = true
|
||||
url.value = `/professional/file/importTaxSalary?chooseDate=${chooseDate.value}`
|
||||
} else {
|
||||
showUpload.value = false
|
||||
}
|
||||
}
|
||||
if (chooseDate.value) {
|
||||
showUpload.value = true;
|
||||
url.value = `/professional/file/importTaxSalary?chooseDate=${chooseDate.value}`;
|
||||
} else {
|
||||
showUpload.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
const init = () => {
|
||||
fileList.value = []
|
||||
files.value = null
|
||||
fileName.value = ''
|
||||
chooseDate.value = ''
|
||||
showUpload.value = false
|
||||
visible.value = true
|
||||
}
|
||||
fileList.value = [];
|
||||
files.value = null;
|
||||
fileName.value = '';
|
||||
chooseDate.value = '';
|
||||
showUpload.value = false;
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 上传前验证
|
||||
const beforeUpload = (file: File) => {
|
||||
files.value = file
|
||||
const fileLast = file.name.split('.')
|
||||
const extension = fileLast[fileLast.length - 1] === 'xls'
|
||||
const extension2 = fileLast[fileLast.length - 1] === 'xlsx'
|
||||
const isLt2M = file.size / 1024 / 1024 < 20
|
||||
|
||||
if (!extension && !extension2) {
|
||||
message.warning('上传模板只能是 xls、xlsx格式!')
|
||||
return false
|
||||
}
|
||||
if (!isLt2M) {
|
||||
message.warning('上传模板大小不能超过 20MB!')
|
||||
return false
|
||||
}
|
||||
fileName.value = file.name
|
||||
return false // 返回false不会自动上传
|
||||
}
|
||||
files.value = file;
|
||||
const fileLast = file.name.split('.');
|
||||
const extension = fileLast[fileLast.length - 1] === 'xls';
|
||||
const extension2 = fileLast[fileLast.length - 1] === 'xlsx';
|
||||
const isLt2M = file.size / 1024 / 1024 < 20;
|
||||
|
||||
if (!extension && !extension2) {
|
||||
message.warning('上传模板只能是 xls、xlsx格式!');
|
||||
return false;
|
||||
}
|
||||
if (!isLt2M) {
|
||||
message.warning('上传模板大小不能超过 20MB!');
|
||||
return false;
|
||||
}
|
||||
fileName.value = file.name;
|
||||
return false; // 返回false不会自动上传
|
||||
};
|
||||
|
||||
// 导入提交
|
||||
const submitUpload = async () => {
|
||||
btnLoading.value = true
|
||||
if (fileName.value === "") {
|
||||
message.warning('请选择要上传的文件!')
|
||||
btnLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (!files.value) {
|
||||
message.warning('请选择要上传的文件!')
|
||||
btnLoading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const fileFormData = new FormData()
|
||||
fileFormData.append('file', files.value, fileName.value)
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: url.value,
|
||||
method: 'post',
|
||||
data: fileFormData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
|
||||
if (res.data.data && res.data.data.code == 1) {
|
||||
message.error(`导入失败,${res.data.data.title}: ${res.data.data.msg}`)
|
||||
} else {
|
||||
message.success("导入成功")
|
||||
visible.value = false
|
||||
emit('refreshData')
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '导入失败')
|
||||
} finally {
|
||||
btnLoading.value = false
|
||||
}
|
||||
}
|
||||
btnLoading.value = true;
|
||||
if (fileName.value === '') {
|
||||
message.warning('请选择要上传的文件!');
|
||||
btnLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!files.value) {
|
||||
message.warning('请选择要上传的文件!');
|
||||
btnLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const fileFormData = new FormData();
|
||||
fileFormData.append('file', files.value, fileName.value);
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: url.value,
|
||||
method: 'post',
|
||||
data: fileFormData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
|
||||
if (res.data.data && res.data.data.code == 1) {
|
||||
message.error(`导入失败,${res.data.data.title}: ${res.data.data.msg}`);
|
||||
} else {
|
||||
message.success('导入成功');
|
||||
visible.value = false;
|
||||
emit('refreshData');
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '导入失败');
|
||||
} finally {
|
||||
btnLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
init,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,364 +1,295 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<search-form
|
||||
v-show="showSearch"
|
||||
:model="search"
|
||||
ref="searchFormRef"
|
||||
@keyup-enter="handleFilter"
|
||||
>
|
||||
<template #default="{ visible }">
|
||||
<template v-if="visible">
|
||||
<el-form-item label="工号" prop="teacherNo">
|
||||
<el-input
|
||||
v-model="search.teacherNo"
|
||||
placeholder="请输入工号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<search-form v-show="showSearch" :model="search" ref="searchFormRef" @keyup-enter="handleFilter">
|
||||
<template #default="{ visible }">
|
||||
<template v-if="visible">
|
||||
<el-form-item label="工号" prop="teacherNo">
|
||||
<el-input v-model="search.teacherNo" placeholder="请输入工号" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input
|
||||
v-model="search.realName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input v-model="search.realName" placeholder="请输入姓名" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="身份证号" prop="idCard">
|
||||
<el-input
|
||||
v-model="search.idCard"
|
||||
placeholder="请输入身份证号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证号" prop="idCard">
|
||||
<el-input v-model="search.idCard" placeholder="请输入身份证号" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="年份" prop="nf">
|
||||
<el-date-picker
|
||||
v-model="search.nf"
|
||||
type="year"
|
||||
format="YYYY"
|
||||
value-format="YYYY"
|
||||
placeholder="请选择年份"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="年份" prop="nf">
|
||||
<el-date-picker v-model="search.nf" type="year" format="YYYY" value-format="YYYY" placeholder="请选择年份" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="月份" prop="yf">
|
||||
<el-date-picker
|
||||
v-model="search.yf"
|
||||
type="month"
|
||||
format="M"
|
||||
value-format="M"
|
||||
placeholder="请选择月份"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="月份" prop="yf">
|
||||
<el-date-picker v-model="search.yf" type="month" format="M" value-format="M" placeholder="请选择月份" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="岗位级别" prop="stationTypeId">
|
||||
<el-select
|
||||
v-model="search.stationTypeId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择岗位级别"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in stationLevelList"
|
||||
:key="item.id"
|
||||
:label="item.levelName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
<el-form-item label="岗位级别" prop="stationTypeId">
|
||||
<el-select v-model="search.stationTypeId" filterable clearable placeholder="请选择岗位级别">
|
||||
<el-option v-for="item in stationLevelList" :key="item.id" :label="item.levelName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- 查询和重置按钮 -->
|
||||
<template #actions>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleFilter" icon="Search">查询</el-button>
|
||||
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</search-form>
|
||||
<!-- 查询和重置按钮 -->
|
||||
<template #actions>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleFilter" icon="Search">查询</el-button>
|
||||
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</search-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row>
|
||||
<div class="mb15">
|
||||
<el-button
|
||||
v-if="hasAuth('professional_salary_import')"
|
||||
type="primary"
|
||||
plain
|
||||
icon="UploadFilled"
|
||||
@click="handleImportBaseSalary">工资条导入
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasAuth('professional_seach_auth')"
|
||||
icon="View"
|
||||
class="ml10"
|
||||
@click="canSearch(1)">设置可查询
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasAuth('professional_seach_auth')"
|
||||
icon="Hide"
|
||||
class="ml10"
|
||||
@click="canSearch(0)">设置不可查询
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasAuth('professional_professionalsalaries_del')"
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
class="ml10"
|
||||
@click="delbatch">批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
<!-- 操作按钮 -->
|
||||
<el-row>
|
||||
<div class="mb15">
|
||||
<el-button v-if="hasAuth('professional_salary_import')" type="primary" plain icon="UploadFilled" @click="handleImportBaseSalary"
|
||||
>工资条导入
|
||||
</el-button>
|
||||
<el-button v-if="hasAuth('professional_seach_auth')" icon="View" class="ml10" @click="canSearch(1)">设置可查询 </el-button>
|
||||
<el-button v-if="hasAuth('professional_seach_auth')" icon="Hide" class="ml10" @click="canSearch(0)">设置不可查询 </el-button>
|
||||
<el-button v-if="hasAuth('professional_professionalsalaries_del')" type="danger" plain icon="Delete" class="ml10" @click="delbatch"
|
||||
>批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
row-key="id"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
class="data-table"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
row-key="id"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
class="data-table"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
|
||||
<el-table-column label="姓名/工号" min-width="150" align="center">
|
||||
<template #default="scope">
|
||||
<TeacherNameNo :name="scope.row.realName" :no="scope.row.teacherNo" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="postSalary" label="岗位工资" min-width="120" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="nf" label="年份" width="100" align="center" />
|
||||
|
||||
<el-table-column prop="yf" label="月份" width="100" align="center" />
|
||||
|
||||
<el-table-column prop="idCard" label="身份证号" min-width="180" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="shouldPay" label="应发工资" min-width="120" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="realWage" label="实发工资" width="120" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="normalView" label="职工查看" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.normalView === '1' ? 'success' : 'info'">
|
||||
{{ scope.row.normalView === '1' ? '可查询' : '不可查询' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" min-width="150" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="document"
|
||||
link
|
||||
type="primary"
|
||||
@click="handleEdit(scope.row)">查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination
|
||||
v-bind="state.pagination"
|
||||
@current-change="currentChangeHandle"
|
||||
@size-change="sizeChangeHandle"
|
||||
/>
|
||||
<el-table-column label="姓名/工号" min-width="150" align="center">
|
||||
<template #default="scope">
|
||||
<TeacherNameNo :name="scope.row.realName" :no="scope.row.teacherNo" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 子组件 -->
|
||||
<salary-info ref="salaryInfoRef" />
|
||||
<import-base-salary ref="importBaseSalaryRef" @refreshData="handleFilter" />
|
||||
<export-base-salary ref="exportBaseSalaryRef" />
|
||||
</div>
|
||||
</div>
|
||||
<el-table-column prop="postSalary" label="岗位工资" min-width="120" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="nf" label="年份" width="100" align="center" />
|
||||
|
||||
<el-table-column prop="yf" label="月份" width="100" align="center" />
|
||||
|
||||
<el-table-column prop="idCard" label="身份证号" min-width="180" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="shouldPay" label="应发工资" min-width="120" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="realWage" label="实发工资" width="120" align="center" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="normalView" label="职工查看" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.normalView === '1' ? 'success' : 'info'">
|
||||
{{ scope.row.normalView === '1' ? '可查询' : '不可查询' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" min-width="150" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button icon="document" link type="primary" @click="handleEdit(scope.row)">查看 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination v-bind="state.pagination" @current-change="currentChangeHandle" @size-change="sizeChangeHandle" />
|
||||
|
||||
<!-- 子组件 -->
|
||||
<salary-info ref="salaryInfoRef" />
|
||||
<import-base-salary ref="importBaseSalaryRef" @refreshData="handleFilter" />
|
||||
<export-base-salary ref="exportBaseSalaryRef" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table'
|
||||
import { useAuth } from '/@/hooks/auth'
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||
import { fetchList, delBatch, setCanSearch } from '/@/api/professional/salaries/teacherpayslip'
|
||||
import { checkAuth } from '/@/api/professional/salaries/teachersalary'
|
||||
import { getStationLevelList } from '/@/api/professional/professionalstationlevelconfig'
|
||||
const SalaryInfo = defineAsyncComponent(() => import('./salaryInfo.vue'))
|
||||
const ImportBaseSalary = defineAsyncComponent(() => import('./importBaseSalary.vue'))
|
||||
const ExportBaseSalary = defineAsyncComponent(() => import('./exportBaseSalary.vue'))
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table';
|
||||
import { useAuth } from '/@/hooks/auth';
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message';
|
||||
import { fetchList, delBatch, setCanSearch } from '/@/api/professional/salaries/teacherpayslip';
|
||||
import { checkAuth } from '/@/api/professional/salaries/teachersalary';
|
||||
import { getStationLevelList } from '/@/api/professional/professionalstationlevelconfig';
|
||||
const SalaryInfo = defineAsyncComponent(() => import('./salaryInfo.vue'));
|
||||
const ImportBaseSalary = defineAsyncComponent(() => import('./importBaseSalary.vue'));
|
||||
const ExportBaseSalary = defineAsyncComponent(() => import('./exportBaseSalary.vue'));
|
||||
|
||||
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
|
||||
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'));
|
||||
|
||||
// 无权限即无节点
|
||||
const { hasAuth } = useAuth()
|
||||
const { hasAuth } = useAuth();
|
||||
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
const message = useMessage();
|
||||
const messageBox = useMessageBox();
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const salaryInfoRef = ref()
|
||||
const importBaseSalaryRef = ref()
|
||||
const exportBaseSalaryRef = ref()
|
||||
const tableRef = ref();
|
||||
const searchFormRef = ref();
|
||||
const salaryInfoRef = ref();
|
||||
const importBaseSalaryRef = ref();
|
||||
const exportBaseSalaryRef = ref();
|
||||
|
||||
// 搜索表单显示状态
|
||||
const showSearch = ref(true)
|
||||
const showSearch = ref(true);
|
||||
|
||||
// 岗位类别列表
|
||||
const stationLevelList = ref<any[]>([])
|
||||
const stationLevelList = ref<any[]>([]);
|
||||
|
||||
// 选中的行
|
||||
const selectList = ref<any[]>([])
|
||||
const selectList = ref<any[]>([]);
|
||||
|
||||
// 搜索表单数据
|
||||
const search = reactive({
|
||||
teacherNo: '',
|
||||
realName: '',
|
||||
idCard: '',
|
||||
nf: '',
|
||||
yf: '',
|
||||
stationTypeId: '',
|
||||
canSearch: 0,
|
||||
selectList:[]
|
||||
})
|
||||
teacherNo: '',
|
||||
realName: '',
|
||||
idCard: '',
|
||||
nf: '',
|
||||
yf: '',
|
||||
stationTypeId: '',
|
||||
canSearch: 0,
|
||||
selectList: [],
|
||||
});
|
||||
|
||||
// 配置 useTable
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
pageList: async (params: any) => {
|
||||
const response = await fetchList(params)
|
||||
return {
|
||||
data: {
|
||||
records: response.data.records || [],
|
||||
total: response.data.total || 0
|
||||
}
|
||||
}
|
||||
},
|
||||
queryForm: search
|
||||
})
|
||||
pageList: async (params: any) => {
|
||||
const response = await fetchList(params);
|
||||
return {
|
||||
data: {
|
||||
records: response.data.records || [],
|
||||
total: response.data.total || 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
queryForm: search,
|
||||
});
|
||||
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state)
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state);
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
init();
|
||||
});
|
||||
|
||||
// 初始化数据
|
||||
const init = async () => {
|
||||
try {
|
||||
const [stationRes, authRes] = await Promise.all([
|
||||
getStationLevelList(),
|
||||
checkAuth()
|
||||
])
|
||||
|
||||
stationLevelList.value = stationRes.data || []
|
||||
|
||||
// 根据权限设置表格选项(如果需要)
|
||||
// if (authRes.data.data === false) {
|
||||
// // 设置普通表格选项
|
||||
// }
|
||||
} catch (error) {
|
||||
// 初始化失败
|
||||
}
|
||||
}
|
||||
try {
|
||||
const [stationRes, authRes] = await Promise.all([getStationLevelList(), checkAuth()]);
|
||||
|
||||
stationLevelList.value = stationRes.data || [];
|
||||
|
||||
// 根据权限设置表格选项(如果需要)
|
||||
// if (authRes.data.data === false) {
|
||||
// // 设置普通表格选项
|
||||
// }
|
||||
} catch (error) {
|
||||
// 初始化失败
|
||||
}
|
||||
};
|
||||
|
||||
// 查询
|
||||
const handleFilter = () => {
|
||||
getDataList() // 查询后跳转到第一页
|
||||
}
|
||||
getDataList(); // 查询后跳转到第一页
|
||||
};
|
||||
|
||||
// 重置
|
||||
const resetQuery = () => {
|
||||
searchFormRef.value?.formRef?.resetFields()
|
||||
Object.assign(search, {
|
||||
teacherNo: '',
|
||||
realName: '',
|
||||
idCard: '',
|
||||
nf: '',
|
||||
yf: '',
|
||||
stationTypeId: ''
|
||||
})
|
||||
handleFilter()
|
||||
}
|
||||
searchFormRef.value?.formRef?.resetFields();
|
||||
Object.assign(search, {
|
||||
teacherNo: '',
|
||||
realName: '',
|
||||
idCard: '',
|
||||
nf: '',
|
||||
yf: '',
|
||||
stationTypeId: '',
|
||||
});
|
||||
handleFilter();
|
||||
};
|
||||
|
||||
// 选择变化
|
||||
const selectionChange = (selection: any[]) => {
|
||||
selectList.value = selection
|
||||
}
|
||||
selectList.value = selection;
|
||||
};
|
||||
|
||||
// 查看
|
||||
const handleEdit = (row: any) => {
|
||||
salaryInfoRef.value?.init(row)
|
||||
}
|
||||
salaryInfoRef.value?.init(row);
|
||||
};
|
||||
|
||||
// 导入工资条
|
||||
const handleImportBaseSalary = () => {
|
||||
importBaseSalaryRef.value?.init()
|
||||
}
|
||||
importBaseSalaryRef.value?.init();
|
||||
};
|
||||
|
||||
// 批量删除
|
||||
const delbatch = () => {
|
||||
if (selectList.value.length === 0) {
|
||||
message.warning("请至少选择一名人员")
|
||||
return
|
||||
}
|
||||
|
||||
messageBox.confirm(`确认删除当前${selectList.value.length}条记录`).then(async () => {
|
||||
try {
|
||||
const data = { selectList: selectList.value }
|
||||
const response = await delBatch(data)
|
||||
|
||||
if (response.data.code == -1) {
|
||||
message.error(response.data.data)
|
||||
} else {
|
||||
message.success("删除成功")
|
||||
getDataList(false) // 删除后保持当前页
|
||||
}
|
||||
} catch (error: any) {
|
||||
// 错误处理已在数据请求层统一处理,此处不需要提示
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
})
|
||||
}
|
||||
if (selectList.value.length === 0) {
|
||||
message.warning('请至少选择一名人员');
|
||||
return;
|
||||
}
|
||||
|
||||
messageBox
|
||||
.confirm(`确认删除当前${selectList.value.length}条记录`)
|
||||
.then(async () => {
|
||||
try {
|
||||
const data = { selectList: selectList.value };
|
||||
const response = await delBatch(data);
|
||||
|
||||
if (response.data.code == -1) {
|
||||
message.error(response.data.data);
|
||||
} else {
|
||||
message.success('删除成功');
|
||||
getDataList(false); // 删除后保持当前页
|
||||
}
|
||||
} catch (error: any) {
|
||||
// 错误处理已在数据请求层统一处理,此处不需要提示
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// 用户取消
|
||||
});
|
||||
};
|
||||
|
||||
// 设置可查询/不可查询
|
||||
const canSearch = (val: number) => {
|
||||
search.canSearch = val;
|
||||
search.selectList = selectList.value;
|
||||
|
||||
|
||||
search.canSearch=val
|
||||
search.selectList=selectList.value
|
||||
|
||||
messageBox.confirm('确认设置?').then(async () => {
|
||||
try {
|
||||
await setCanSearch(search)
|
||||
message.success("设置成功")
|
||||
getDataList(false) // 设置后保持当前页
|
||||
} catch (error: any) {
|
||||
// 错误处理已在数据请求层统一处理,此处不需要提示
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
})
|
||||
}
|
||||
messageBox
|
||||
.confirm('确认设置?')
|
||||
.then(async () => {
|
||||
try {
|
||||
await setCanSearch(search);
|
||||
message.success('设置成功');
|
||||
getDataList(false); // 设置后保持当前页
|
||||
} catch (error: any) {
|
||||
// 错误处理已在数据请求层统一处理,此处不需要提示
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// 用户取消
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.data-table {
|
||||
width: 100% !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,571 +1,528 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
width="95%"
|
||||
v-loading="baseLoading"
|
||||
top="2vh"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
class="salary-info-dialog"
|
||||
>
|
||||
<div class="salary-info-container">
|
||||
<!--基本信息-->
|
||||
<div class="base-info-section">
|
||||
<div class="base-info-content">
|
||||
<div class="info-group">
|
||||
<div class="info-item">
|
||||
<span class="info-label">姓名:</span>
|
||||
<el-tag v-if="salaryData.baseInfo[0]?.realName">{{ salaryData.baseInfo[0].realName }}</el-tag>
|
||||
<span v-else class="info-value">-</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">身份证号:</span>
|
||||
<el-tag v-if="salaryData.baseInfo[0]?.idCard">{{ salaryData.baseInfo[0].idCard }}</el-tag>
|
||||
<span v-else class="info-value">-</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-form :model="nowUser" :inline="true" class="search-form">
|
||||
<el-form-item label="年份">
|
||||
<el-date-picker
|
||||
v-model="nowUser.nf"
|
||||
type="year"
|
||||
format="YYYY"
|
||||
value-format="YYYY"
|
||||
placeholder="选择年"
|
||||
style="width: 150px">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="月份">
|
||||
<el-date-picker
|
||||
v-model="nowUser.yff"
|
||||
type="month"
|
||||
format="M"
|
||||
value-format="M"
|
||||
placeholder="选择月"
|
||||
style="width: 150px">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="searchUserInfo" type="primary" icon="Search">
|
||||
查询
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
width="95%"
|
||||
v-loading="baseLoading"
|
||||
top="2vh"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
class="salary-info-dialog"
|
||||
>
|
||||
<div class="salary-info-container">
|
||||
<!--基本信息-->
|
||||
<div class="base-info-section">
|
||||
<div class="base-info-content">
|
||||
<div class="info-group">
|
||||
<div class="info-item">
|
||||
<span class="info-label">姓名:</span>
|
||||
<el-tag v-if="salaryData.baseInfo[0]?.realName">{{ salaryData.baseInfo[0].realName }}</el-tag>
|
||||
<span v-else class="info-value">-</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">身份证号:</span>
|
||||
<el-tag v-if="salaryData.baseInfo[0]?.idCard">{{ salaryData.baseInfo[0].idCard }}</el-tag>
|
||||
<span v-else class="info-value">-</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-form :model="nowUser" :inline="true" class="search-form">
|
||||
<el-form-item label="年份">
|
||||
<el-date-picker v-model="nowUser.nf" type="year" format="YYYY" value-format="YYYY" placeholder="选择年" style="width: 150px">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="月份">
|
||||
<el-date-picker v-model="nowUser.yff" type="month" format="M" value-format="M" placeholder="选择月" style="width: 150px">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="searchUserInfo" type="primary" icon="Search"> 查询 </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card shadow="hover" class="info-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<el-icon><Money /></el-icon>
|
||||
<span>工资明细</span>
|
||||
</div>
|
||||
</template>
|
||||
<!--应发部分-->
|
||||
<div class="section-title">
|
||||
<el-icon><TrendCharts /></el-icon>
|
||||
<span>应发部分</span>
|
||||
</div>
|
||||
<el-table
|
||||
:data="salaryData.baseInfo"
|
||||
size="small"
|
||||
border
|
||||
class="salary-table"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="应发部分">
|
||||
<el-table-column prop="baseSalary" label="基础专项绩效" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="postSalary" label="岗位工资" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="payWage" label="薪级工资" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="见习期工资" prop="studentPay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="liveAllowance" label="生活补贴" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="postAllowance" label="岗位津贴" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="住房(租金)补贴" prop="houseSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="新职工住房补贴" prop="newHouseSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="回民补贴" prop="huiSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="养老保险补贴" prop="oldSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="教龄津贴" prop="ageAllowance" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特教补贴" prop="specialSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特级教师津贴" prop="teacherAllowance" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特岗津贴(一)" prop="sPostAllowance1" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特岗津贴(二)" prop="sPostAllowance2" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="其他" prop="other" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="奖励性绩效工资" prop="meritPay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="乡镇工作补贴" prop="villageSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="临时性补贴" prop="temporarySubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="上下班交通补贴" prop="trafficSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="保留津贴" prop="keepAllowance" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="补发工资" prop="retroactivePay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="应休未休假补贴" prop="vacationMoney" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="应发工资" prop="shouldPay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="基础专项绩效" prop="baseSalary" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="基础工资应税收入" prop="shouldTaxMoney" min-width="60" align="center"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tag">
|
||||
<el-tag type="danger" size="small">基础工资应税收入= 岗位工资 +薪级工资+见习期工资+生活补贴+岗位津贴+教龄津贴+特教补贴+特级教师津贴+特岗津贴(1)+特岗津贴(2)+奖励绩效性工资+乡镇工作补贴+临时补贴+保留津贴+应休未休假-个人补缴-其他扣款-医疗救助金</el-tag>
|
||||
</div>
|
||||
|
||||
<!--应扣部分-->
|
||||
<div class="section-title">
|
||||
<el-icon><Remove /></el-icon>
|
||||
<span>应扣部分</span>
|
||||
</div>
|
||||
<el-table
|
||||
size="small"
|
||||
border
|
||||
:data="salaryData.baseInfo"
|
||||
class="salary-table"
|
||||
style="width: 100%">
|
||||
<el-table-column label="应扣部分">
|
||||
<el-table-column label="住房公积金" min-width="90" prop="houseFund"></el-table-column>
|
||||
<el-table-column label="医疗保险金" min-width="90" prop="medicalInsurance"></el-table-column>
|
||||
<el-table-column label="失业保险金" min-width="90" prop="unemployInsurance"></el-table-column>
|
||||
<el-table-column label="养老保险金" min-width="90" prop="endowInsurance"></el-table-column>
|
||||
<el-table-column label="工会费" min-width="60" prop="unionFee"></el-table-column>
|
||||
<el-table-column label="儿童统筹" min-width="90" prop="childrenWhole"></el-table-column>
|
||||
<el-table-column label="个人所得税" width="90" prop="personalTax"></el-table-column>
|
||||
<el-table-column label="其他扣款" min-width="90" prop="otherDeduction"></el-table-column>
|
||||
<el-table-column label="病事假扣款" min-width="90" prop="sickDeduction"></el-table-column>
|
||||
<el-table-column label="医疗救助基金" min-width="90" prop="medicalFund"></el-table-column>
|
||||
<el-table-column label="工伤保险" min-width="90" prop="inductrialInjury"></el-table-column>
|
||||
<el-table-column label="个人补缴" min-width="90" prop="personalPay"></el-table-column>
|
||||
<el-table-column label="应扣合计" min-width="90" prop="withhold"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tag">
|
||||
<el-tag size="small">个人所得税 = 个税计算数据中的《 累计应补(退)税额 》</el-tag>
|
||||
</div>
|
||||
<el-card shadow="hover" class="info-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<el-icon><Money /></el-icon>
|
||||
<span>工资明细</span>
|
||||
</div>
|
||||
</template>
|
||||
<!--应发部分-->
|
||||
<div class="section-title">
|
||||
<el-icon><TrendCharts /></el-icon>
|
||||
<span>应发部分</span>
|
||||
</div>
|
||||
<el-table :data="salaryData.baseInfo" size="small" border class="salary-table" style="width: 100%">
|
||||
<el-table-column label="应发部分">
|
||||
<el-table-column prop="baseSalary" label="基础专项绩效" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="postSalary" label="岗位工资" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="payWage" label="薪级工资" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="见习期工资" prop="studentPay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="liveAllowance" label="生活补贴" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="postAllowance" label="岗位津贴" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="住房(租金)补贴" prop="houseSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="新职工住房补贴" prop="newHouseSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="回民补贴" prop="huiSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="养老保险补贴" prop="oldSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="教龄津贴" prop="ageAllowance" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特教补贴" prop="specialSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特级教师津贴" prop="teacherAllowance" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特岗津贴(一)" prop="sPostAllowance1" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="特岗津贴(二)" prop="sPostAllowance2" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="其他" prop="other" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="奖励性绩效工资" prop="meritPay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="乡镇工作补贴" prop="villageSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="临时性补贴" prop="temporarySubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="上下班交通补贴" prop="trafficSubsidies" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="保留津贴" prop="keepAllowance" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="补发工资" prop="retroactivePay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="应休未休假补贴" prop="vacationMoney" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="应发工资" prop="shouldPay" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="基础专项绩效" prop="baseSalary" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="基础工资应税收入" prop="shouldTaxMoney" min-width="60" align="center"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tag">
|
||||
<el-tag type="danger" size="small"
|
||||
>基础工资应税收入= 岗位工资
|
||||
+薪级工资+见习期工资+生活补贴+岗位津贴+教龄津贴+特教补贴+特级教师津贴+特岗津贴(1)+特岗津贴(2)+奖励绩效性工资+乡镇工作补贴+临时补贴+保留津贴+应休未休假-个人补缴-其他扣款-医疗救助金</el-tag
|
||||
>
|
||||
</div>
|
||||
|
||||
<!--劳务费-->
|
||||
<div v-if="showAllContent" class="section-title">
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>造单收入清单</span>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="showAllContent"
|
||||
size="small"
|
||||
border
|
||||
:data="allProjectData"
|
||||
class="salary-table"
|
||||
style="width: 100%">
|
||||
<el-table-column label="造单收入清单">
|
||||
<el-table-column label="造单部门" prop="deptName"></el-table-column>
|
||||
<el-table-column label="造单人" prop="createName"></el-table-column>
|
||||
<el-table-column label="项目编号" prop="projectNo"></el-table-column>
|
||||
<el-table-column label="项目名" prop="title"></el-table-column>
|
||||
<el-table-column label="金额" prop="realMoney"></el-table-column>
|
||||
<el-table-column label="付讫时间" prop="payTime"></el-table-column>
|
||||
<el-table-column label="免税或暂不交税" prop="freeTax">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.freeTax=='1'">√</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--应扣部分-->
|
||||
<div class="section-title">
|
||||
<el-icon><Remove /></el-icon>
|
||||
<span>应扣部分</span>
|
||||
</div>
|
||||
<el-table size="small" border :data="salaryData.baseInfo" class="salary-table" style="width: 100%">
|
||||
<el-table-column label="应扣部分">
|
||||
<el-table-column label="住房公积金" min-width="90" prop="houseFund"></el-table-column>
|
||||
<el-table-column label="医疗保险金" min-width="90" prop="medicalInsurance"></el-table-column>
|
||||
<el-table-column label="失业保险金" min-width="90" prop="unemployInsurance"></el-table-column>
|
||||
<el-table-column label="养老保险金" min-width="90" prop="endowInsurance"></el-table-column>
|
||||
<el-table-column label="工会费" min-width="60" prop="unionFee"></el-table-column>
|
||||
<el-table-column label="儿童统筹" min-width="90" prop="childrenWhole"></el-table-column>
|
||||
<el-table-column label="个人所得税" width="90" prop="personalTax"></el-table-column>
|
||||
<el-table-column label="其他扣款" min-width="90" prop="otherDeduction"></el-table-column>
|
||||
<el-table-column label="病事假扣款" min-width="90" prop="sickDeduction"></el-table-column>
|
||||
<el-table-column label="医疗救助基金" min-width="90" prop="medicalFund"></el-table-column>
|
||||
<el-table-column label="工伤保险" min-width="90" prop="inductrialInjury"></el-table-column>
|
||||
<el-table-column label="个人补缴" min-width="90" prop="personalPay"></el-table-column>
|
||||
<el-table-column label="应扣合计" min-width="90" prop="withhold"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tag">
|
||||
<el-tag size="small">个人所得税 = 个税计算数据中的《 累计应补(退)税额 》</el-tag>
|
||||
</div>
|
||||
|
||||
<!--专项扣除-->
|
||||
<div v-if="showAllContent" class="section-title">
|
||||
<el-icon><DataAnalysis /></el-icon>
|
||||
<span>个税计算数据</span>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="showAllContent"
|
||||
size="small"
|
||||
border
|
||||
:data="salaryExtendData"
|
||||
class="salary-table"
|
||||
style="width: 100%">
|
||||
<el-table-column label="个税计算数据">
|
||||
<el-table-column prop="currentIncome" label="应税收入" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalIncome" label="累计收入额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalDeduction" label="累计减除费用" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalSpecialDecution" label="累计专项扣除" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="累计专项扣除附加" align="center">
|
||||
<el-table-column prop="totalChildEdu" label="累计子女教育" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalConEdu" label="累计继续教育" min-width="60" align="center"> </el-table-column>
|
||||
<el-table-column prop="totalHouseInterest" label="累计住房贷款利息" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalHouse" label="累计住房租金" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalSupportOld" label="累计赡养老人" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalBabyMoney" label="累计婴幼儿照护费用" min-width="60" align="center"></el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column prop="totalTaxMoney" label="累计应纳税所得额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="taxRate" label="税率" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="quickDecution" label="速算扣除数" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalRealTaxPay" label="累计应扣缴税额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalPrePayTax" label="累计已预缴税额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalRetrieveTax" label="累计应补(退)税额" min-width="60" align="center"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="showAllContent" class="formula-tag">
|
||||
<el-tag type="warning" size="small">应税收入= 基础工资应税收入+造单收入</el-tag>
|
||||
<el-tag type="success" size="small" class="ml10">累计专项扣除=当年累计个人承担的住房公积金+医疗保险金+失业保险金+养老保险金</el-tag>
|
||||
</div>
|
||||
<!--劳务费-->
|
||||
<div v-if="showAllContent" class="section-title">
|
||||
<el-icon><Document /></el-icon>
|
||||
<span>造单收入清单</span>
|
||||
</div>
|
||||
<el-table v-if="showAllContent" size="small" border :data="allProjectData" class="salary-table" style="width: 100%">
|
||||
<el-table-column label="造单收入清单">
|
||||
<el-table-column label="造单部门" prop="deptName"></el-table-column>
|
||||
<el-table-column label="造单人" prop="createName"></el-table-column>
|
||||
<el-table-column label="项目编号" prop="projectNo"></el-table-column>
|
||||
<el-table-column label="项目名" prop="title"></el-table-column>
|
||||
<el-table-column label="金额" prop="realMoney"></el-table-column>
|
||||
<el-table-column label="付讫时间" prop="payTime"></el-table-column>
|
||||
<el-table-column label="免税或暂不交税" prop="freeTax">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.freeTax == '1'">√</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!--实发合计-->
|
||||
<div class="section-title">
|
||||
<el-icon><Wallet /></el-icon>
|
||||
<span>实发合计</span>
|
||||
</div>
|
||||
<el-table
|
||||
size="small"
|
||||
border
|
||||
:data="[staticsData]"
|
||||
class="salary-table summary-table"
|
||||
empty-text=" "
|
||||
style="width: 100%">
|
||||
<el-table-column label="小计">
|
||||
<el-table-column label="应发工资" prop="shouldPay"></el-table-column>
|
||||
<el-table-column label="应扣合计" prop="shouldDedu"></el-table-column>
|
||||
<el-table-column label="实发工资" prop="realWage"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tag">
|
||||
<el-tag type="primary" size="small">实发工资= 应发工资-应扣合计</el-tag>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--专项扣除-->
|
||||
<div v-if="showAllContent" class="section-title">
|
||||
<el-icon><DataAnalysis /></el-icon>
|
||||
<span>个税计算数据</span>
|
||||
</div>
|
||||
<el-table v-if="showAllContent" size="small" border :data="salaryExtendData" class="salary-table" style="width: 100%">
|
||||
<el-table-column label="个税计算数据">
|
||||
<el-table-column prop="currentIncome" label="应税收入" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalIncome" label="累计收入额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalDeduction" label="累计减除费用" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalSpecialDecution" label="累计专项扣除" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column label="累计专项扣除附加" align="center">
|
||||
<el-table-column prop="totalChildEdu" label="累计子女教育" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalConEdu" label="累计继续教育" min-width="60" align="center"> </el-table-column>
|
||||
<el-table-column prop="totalHouseInterest" label="累计住房贷款利息" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalHouse" label="累计住房租金" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalSupportOld" label="累计赡养老人" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalBabyMoney" label="累计婴幼儿照护费用" min-width="60" align="center"></el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column prop="totalTaxMoney" label="累计应纳税所得额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="taxRate" label="税率" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="quickDecution" label="速算扣除数" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalRealTaxPay" label="累计应扣缴税额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalPrePayTax" label="累计已预缴税额" min-width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="totalRetrieveTax" label="累计应补(退)税额" min-width="60" align="center"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="showAllContent" class="formula-tag">
|
||||
<el-tag type="warning" size="small">应税收入= 基础工资应税收入+造单收入</el-tag>
|
||||
<el-tag type="success" size="small" class="ml10">累计专项扣除=当年累计个人承担的住房公积金+医疗保险金+失业保险金+养老保险金</el-tag>
|
||||
</div>
|
||||
|
||||
<!--实发合计-->
|
||||
<div class="section-title">
|
||||
<el-icon><Wallet /></el-icon>
|
||||
<span>实发合计</span>
|
||||
</div>
|
||||
<el-table size="small" border :data="[staticsData]" class="salary-table summary-table" empty-text=" " style="width: 100%">
|
||||
<el-table-column label="小计">
|
||||
<el-table-column label="应发工资" prop="shouldPay"></el-table-column>
|
||||
<el-table-column label="应扣合计" prop="shouldDedu"></el-table-column>
|
||||
<el-table-column label="实发工资" prop="realWage"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="formula-tag">
|
||||
<el-tag type="primary" size="small">实发工资= 应发工资-应扣合计</el-tag>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from 'vue'
|
||||
import { Money, TrendCharts, Remove, Document, DataAnalysis, Wallet, Search } from '@element-plus/icons-vue'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { queryUserInfo, queryExtendSalaryInfo } from '/@/api/professional/salaries/teacherpayslip'
|
||||
import { checkAuth } from '/@/api/professional/salaries/teachersalary'
|
||||
import { ref, reactive, nextTick } from 'vue';
|
||||
import { Money, TrendCharts, Remove, Document, DataAnalysis, Wallet, Search } from '@element-plus/icons-vue';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { queryUserInfo, queryExtendSalaryInfo } from '/@/api/professional/salaries/teacherpayslip';
|
||||
import { checkAuth } from '/@/api/professional/salaries/teachersalary';
|
||||
|
||||
const message = useMessage()
|
||||
const message = useMessage();
|
||||
|
||||
// 对话框显示状态
|
||||
const visible = ref(false)
|
||||
const visible = ref(false);
|
||||
|
||||
// 数据
|
||||
const salaryData = reactive({
|
||||
baseInfo: [] as any[]
|
||||
})
|
||||
baseInfo: [] as any[],
|
||||
});
|
||||
|
||||
const nowUser = ref<any>({})
|
||||
const baseLoading = ref(false)
|
||||
const salaryExtendData = ref<any[]>([])
|
||||
const allProjectData = ref<any[]>([])
|
||||
const nowUser = ref<any>({});
|
||||
const baseLoading = ref(false);
|
||||
const salaryExtendData = ref<any[]>([]);
|
||||
const allProjectData = ref<any[]>([]);
|
||||
const staticsData = reactive({
|
||||
shouldPay: 0,
|
||||
shouldDedu: 0,
|
||||
realWage: 0,
|
||||
orderMoney: 0,
|
||||
personTax: 0
|
||||
})
|
||||
const showAllContent = ref(false)
|
||||
shouldPay: 0,
|
||||
shouldDedu: 0,
|
||||
realWage: 0,
|
||||
orderMoney: 0,
|
||||
personTax: 0,
|
||||
});
|
||||
const showAllContent = ref(false);
|
||||
|
||||
// 检查权限
|
||||
const checkAuthMethod = async () => {
|
||||
try {
|
||||
const res = await checkAuth()
|
||||
showAllContent.value = res.data
|
||||
} catch (error) {
|
||||
// 检查权限失败
|
||||
}
|
||||
}
|
||||
try {
|
||||
const res = await checkAuth();
|
||||
showAllContent.value = res.data;
|
||||
} catch (error) {
|
||||
// 检查权限失败
|
||||
}
|
||||
};
|
||||
|
||||
// 构建用户信息
|
||||
const makeUserInfo = (data: any) => {
|
||||
const row = JSON.parse(JSON.stringify(data))
|
||||
salaryData.baseInfo = []
|
||||
row.realName = (row.realName == "" || row.realName == null ? row.userName : row.realName)
|
||||
salaryData.baseInfo.push(row)
|
||||
const row = JSON.parse(JSON.stringify(data));
|
||||
salaryData.baseInfo = [];
|
||||
row.realName = row.realName == '' || row.realName == null ? row.userName : row.realName;
|
||||
salaryData.baseInfo.push(row);
|
||||
|
||||
staticsData.shouldPay = row.shouldPay || 0
|
||||
staticsData.shouldDedu = row.withhold || 0
|
||||
staticsData.realWage = row.realWage || 0
|
||||
staticsData.personTax = (row.personalTax as number) || 0
|
||||
}
|
||||
staticsData.shouldPay = row.shouldPay || 0;
|
||||
staticsData.shouldDedu = row.withhold || 0;
|
||||
staticsData.realWage = row.realWage || 0;
|
||||
staticsData.personTax = (row.personalTax as number) || 0;
|
||||
};
|
||||
|
||||
// 查询扩展薪资信息
|
||||
const queryExtendSalaryInfoMethod = async (row: any) => {
|
||||
salaryExtendData.value = []
|
||||
const params = { nf: row.nf, yf: row.yf, teacherNo: row.teacherNo }
|
||||
try {
|
||||
const res = await queryExtendSalaryInfo(params)
|
||||
salaryExtendData.value.push(res.data.salaryTax)
|
||||
allProjectData.value = res.data.allProject
|
||||
staticsData.orderMoney = res.data.totalMoney
|
||||
} catch (error) {
|
||||
// 查询失败
|
||||
}
|
||||
}
|
||||
salaryExtendData.value = [];
|
||||
const params = { nf: row.nf, yf: row.yf, teacherNo: row.teacherNo };
|
||||
try {
|
||||
const res = await queryExtendSalaryInfo(params);
|
||||
salaryExtendData.value.push(res.data.salaryTax);
|
||||
allProjectData.value = res.data.allProject;
|
||||
staticsData.orderMoney = res.data.totalMoney;
|
||||
} catch (error) {
|
||||
// 查询失败
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索用户信息
|
||||
const searchUserInfo = async () => {
|
||||
if (!nowUser.value.idCard) {
|
||||
message.warning('请输入身份证号')
|
||||
return
|
||||
}
|
||||
if (!nowUser.value.nf) {
|
||||
message.warning('请选择年份')
|
||||
return
|
||||
}
|
||||
if (!nowUser.value.yff) {
|
||||
message.warning('请选择月份')
|
||||
return
|
||||
}
|
||||
if (!nowUser.value.idCard) {
|
||||
message.warning('请输入身份证号');
|
||||
return;
|
||||
}
|
||||
if (!nowUser.value.nf) {
|
||||
message.warning('请选择年份');
|
||||
return;
|
||||
}
|
||||
if (!nowUser.value.yff) {
|
||||
message.warning('请选择月份');
|
||||
return;
|
||||
}
|
||||
|
||||
baseLoading.value = true
|
||||
const data = { idCard: nowUser.value.idCard, nf: nowUser.value.nf, yf: nowUser.value.yff }
|
||||
try {
|
||||
const response = await queryUserInfo(data)
|
||||
if (response.data.data == null) {
|
||||
message.info('未查询到该时间段的数据')
|
||||
salaryData.baseInfo = []
|
||||
const obj: any = {}
|
||||
obj.realName = nowUser.value.realName
|
||||
obj.idCard = nowUser.value.idCard
|
||||
salaryData.baseInfo.push(obj)
|
||||
baseLoading.value = true;
|
||||
const data = { idCard: nowUser.value.idCard, nf: nowUser.value.nf, yf: nowUser.value.yff };
|
||||
try {
|
||||
const response = await queryUserInfo(data);
|
||||
if (response.data.data == null) {
|
||||
message.info('未查询到该时间段的数据');
|
||||
salaryData.baseInfo = [];
|
||||
const obj: any = {};
|
||||
obj.realName = nowUser.value.realName;
|
||||
obj.idCard = nowUser.value.idCard;
|
||||
salaryData.baseInfo.push(obj);
|
||||
|
||||
salaryExtendData.value = []
|
||||
Object.assign(staticsData, {
|
||||
shouldPay: 0,
|
||||
shouldDedu: 0,
|
||||
realWage: 0,
|
||||
orderMoney: 0,
|
||||
personTax: 0
|
||||
})
|
||||
} else {
|
||||
const resData = response.data.data
|
||||
resData.realName = nowUser.value.realName
|
||||
resData.nf = nowUser.value.nf
|
||||
resData.yf = nowUser.value.yff
|
||||
resData.teacherNo = nowUser.value.teacherNo
|
||||
makeUserInfo(resData)
|
||||
await queryExtendSalaryInfoMethod(resData)
|
||||
message.success('查询成功')
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '查询失败')
|
||||
} finally {
|
||||
baseLoading.value = false
|
||||
}
|
||||
}
|
||||
salaryExtendData.value = [];
|
||||
Object.assign(staticsData, {
|
||||
shouldPay: 0,
|
||||
shouldDedu: 0,
|
||||
realWage: 0,
|
||||
orderMoney: 0,
|
||||
personTax: 0,
|
||||
});
|
||||
} else {
|
||||
const resData = response.data.data;
|
||||
resData.realName = nowUser.value.realName;
|
||||
resData.nf = nowUser.value.nf;
|
||||
resData.yf = nowUser.value.yff;
|
||||
resData.teacherNo = nowUser.value.teacherNo;
|
||||
makeUserInfo(resData);
|
||||
await queryExtendSalaryInfoMethod(resData);
|
||||
message.success('查询成功');
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '查询失败');
|
||||
} finally {
|
||||
baseLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
const init = (row: any) => {
|
||||
visible.value = true
|
||||
nextTick(() => {
|
||||
checkAuthMethod()
|
||||
nowUser.value = JSON.parse(JSON.stringify(row))
|
||||
nowUser.value.yff = row.yf
|
||||
makeUserInfo(row)
|
||||
queryExtendSalaryInfoMethod(row)
|
||||
})
|
||||
}
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
checkAuthMethod();
|
||||
nowUser.value = JSON.parse(JSON.stringify(row));
|
||||
nowUser.value.yff = row.yf;
|
||||
makeUserInfo(row);
|
||||
queryExtendSalaryInfoMethod(row);
|
||||
});
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
init,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.salary-info-dialog {
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 10px !important;
|
||||
max-height: calc(100vh - 120px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 10px !important;
|
||||
max-height: calc(100vh - 120px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.salary-info-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
|
||||
.el-icon {
|
||||
font-size: 18px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon {
|
||||
font-size: 18px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.section-header-inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-right: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-right: 16px;
|
||||
|
||||
.el-icon {
|
||||
font-size: 16px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon {
|
||||
font-size: 16px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.info-card {
|
||||
:deep(.el-card__header) {
|
||||
padding: 16px 20px;
|
||||
background: #f5f7fa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
:deep(.el-card__header) {
|
||||
padding: 16px 20px;
|
||||
background: #f5f7fa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
:deep(.el-card__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.base-info-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.info-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
// align-items: center;
|
||||
gap: 6px;
|
||||
display: flex;
|
||||
// align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
.info-label {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
}
|
||||
.info-label {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #303133;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.info-value {
|
||||
color: #303133;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin-left: auto;
|
||||
margin-bottom: 0;
|
||||
|
||||
|
||||
|
||||
margin-left: auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 24px 0 12px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #e4e7ed;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 24px 0 12px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #e4e7ed;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
|
||||
.el-icon {
|
||||
font-size: 16px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon {
|
||||
font-size: 16px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.salary-table {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
:deep(.el-table__header) {
|
||||
th {
|
||||
background: #f5f7fa;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
:deep(.el-table__header) {
|
||||
th {
|
||||
background: #f5f7fa;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
td {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
:deep(.el-table__body) {
|
||||
td {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__cell) {
|
||||
padding: 8px 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
:deep(.el-table__cell) {
|
||||
padding: 8px 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.summary-table {
|
||||
:deep(.el-table__body) {
|
||||
td {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
:deep(.el-table__body) {
|
||||
td {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.formula-tag {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.6;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.6;
|
||||
|
||||
.el-tag {
|
||||
margin-right: 8px;
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
.el-tag {
|
||||
margin-right: 8px;
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式优化
|
||||
@media (max-width: 1400px) {
|
||||
.salary-info-dialog {
|
||||
:deep(.el-dialog) {
|
||||
width: 98% !important;
|
||||
}
|
||||
}
|
||||
.salary-info-dialog {
|
||||
:deep(.el-dialog) {
|
||||
width: 98% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条优化
|
||||
.salary-info-dialog {
|
||||
:deep(.el-dialog__body) {
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
:deep(.el-dialog__body) {
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 4px;
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background: #a8a8a8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user