ren
This commit is contained in:
122
src/views/professional/teacherpayslip/exportBaseSalary.vue
Normal file
122
src/views/professional/teacherpayslip/exportBaseSalary.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="薪资导出" width="500px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="120px">
|
||||
<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 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>
|
||||
<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'
|
||||
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
|
||||
// 对话框显示状态
|
||||
const visible = ref(false)
|
||||
|
||||
// 表单数据
|
||||
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
|
||||
}
|
||||
|
||||
// 日期改变
|
||||
const handleChange = () => {
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 导出薪资数据
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
183
src/views/professional/teacherpayslip/importBaseSalary.vue
Normal file
183
src/views/professional/teacherpayslip/importBaseSalary.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<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
|
||||
size="small"
|
||||
v-if="permissions.professional_salary_import"
|
||||
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 { storeToRefs } from 'pinia'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import request from '/@/utils/request'
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'refreshData'): void
|
||||
}>()
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
const { userInfos } = storeToRefs(userInfoStore)
|
||||
|
||||
// 创建权限对象
|
||||
const permissions = computed(() => {
|
||||
const perms: Record<string, boolean> = {}
|
||||
userInfos.value.authBtnList.forEach((perm: string) => {
|
||||
perms[perm] = true
|
||||
})
|
||||
return perms
|
||||
})
|
||||
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
|
||||
// 对话框显示状态
|
||||
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 headers = computed(() => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
const init = () => {
|
||||
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不会自动上传
|
||||
}
|
||||
|
||||
// 导入提交
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
183
src/views/professional/teacherpayslip/importTaxSalary.vue
Normal file
183
src/views/professional/teacherpayslip/importTaxSalary.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<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
|
||||
size="small"
|
||||
v-if="permissions.professional_salary_import"
|
||||
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 { storeToRefs } from 'pinia'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import request from '/@/utils/request'
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'refreshData'): void
|
||||
}>()
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
const { userInfos } = storeToRefs(userInfoStore)
|
||||
|
||||
// 创建权限对象
|
||||
const permissions = computed(() => {
|
||||
const perms: Record<string, boolean> = {}
|
||||
userInfos.value.authBtnList.forEach((perm: string) => {
|
||||
perms[perm] = true
|
||||
})
|
||||
return perms
|
||||
})
|
||||
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
|
||||
// 对话框显示状态
|
||||
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 headers = computed(() => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
const init = () => {
|
||||
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不会自动上传
|
||||
}
|
||||
|
||||
// 导入提交
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
359
src/views/professional/teacherpayslip/index.vue
Executable file
359
src/views/professional/teacherpayslip/index.vue
Executable file
@@ -0,0 +1,359 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 操作按钮 -->
|
||||
<el-row>
|
||||
<div class="mb15" style="width: 100%;">
|
||||
<el-button
|
||||
size="small"
|
||||
v-if="permissions.professional_salary_import"
|
||||
type="primary"
|
||||
@click="handleImportBaseSalary">工资条导入
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
v-if="permissions.professional_seach_auth"
|
||||
@click="canSearch(1)">设置可查询
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
v-if="permissions.professional_seach_auth"
|
||||
@click="canSearch(0)">设置不可查询
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
v-if="permissions.professional_professionalsalaries_del"
|
||||
@click="delbatch">批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<!-- 搜索表单 -->
|
||||
<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
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input
|
||||
v-model="search.realName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="身份证号" prop="idCard">
|
||||
<el-input
|
||||
v-model="search.idCard"
|
||||
placeholder="请输入身份证号"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</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
|
||||
style="width: 200px"
|
||||
/>
|
||||
</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
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="岗位类别" prop="stationTypeId">
|
||||
<el-select
|
||||
v-model="search.stationTypeId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择岗位类别"
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in stationLevelList"
|
||||
:key="item.id"
|
||||
:label="item.levelName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</search-form>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
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-column prop="numId" label="编号" width="100" align="center" show-overflow-tooltip />
|
||||
|
||||
<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>
|
||||
|
||||
<!-- 分页 -->
|
||||
<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, computed, onMounted } from 'vue'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table'
|
||||
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'
|
||||
import SalaryInfo from './salaryInfo.vue'
|
||||
import ImportBaseSalary from './importBaseSalary.vue'
|
||||
import ExportBaseSalary from './exportBaseSalary.vue'
|
||||
|
||||
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
const { userInfos } = storeToRefs(userInfoStore)
|
||||
|
||||
// 创建权限对象
|
||||
const permissions = computed(() => {
|
||||
const perms: Record<string, boolean> = {}
|
||||
userInfos.value.authBtnList.forEach((perm: string) => {
|
||||
perms[perm] = true
|
||||
})
|
||||
return perms
|
||||
})
|
||||
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const salaryInfoRef = ref()
|
||||
const importBaseSalaryRef = ref()
|
||||
const exportBaseSalaryRef = ref()
|
||||
|
||||
// 搜索表单显示状态
|
||||
const showSearch = ref(true)
|
||||
|
||||
// 岗位类别列表
|
||||
const stationLevelList = ref<any[]>([])
|
||||
|
||||
// 选中的行
|
||||
const selectList = ref<any[]>([])
|
||||
|
||||
// 搜索表单数据
|
||||
const search = reactive({
|
||||
teacherNo: '',
|
||||
realName: '',
|
||||
idCard: '',
|
||||
nf: '',
|
||||
yf: '',
|
||||
stationTypeId: ''
|
||||
})
|
||||
|
||||
// 配置 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
|
||||
})
|
||||
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state)
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
// 初始化数据
|
||||
const init = async () => {
|
||||
try {
|
||||
const [stationRes, authRes] = await Promise.all([
|
||||
getStationLevelList(),
|
||||
checkAuth()
|
||||
])
|
||||
|
||||
stationLevelList.value = stationRes.data || []
|
||||
|
||||
// 根据权限设置表格选项(如果需要)
|
||||
// if (authRes.data.data === false) {
|
||||
// // 设置普通表格选项
|
||||
// }
|
||||
} catch (error) {
|
||||
// 初始化失败
|
||||
}
|
||||
}
|
||||
|
||||
// 查询
|
||||
const handleFilter = () => {
|
||||
getDataList() // 查询后跳转到第一页
|
||||
}
|
||||
|
||||
// 选择变化
|
||||
const selectionChange = (selection: any[]) => {
|
||||
selectList.value = selection
|
||||
}
|
||||
|
||||
// 查看
|
||||
const handleEdit = (row: any) => {
|
||||
salaryInfoRef.value?.init(row)
|
||||
}
|
||||
|
||||
// 导入工资条
|
||||
const handleImportBaseSalary = () => {
|
||||
importBaseSalaryRef.value?.init()
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
const delbatch = () => {
|
||||
if (selectList.value.length === 0) {
|
||||
message.info("请至少选择一名人员")
|
||||
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.info("删除成功")
|
||||
getDataList(false) // 删除后保持当前页
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '删除失败')
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
})
|
||||
}
|
||||
|
||||
// 设置可查询/不可查询
|
||||
const canSearch = (val: number) => {
|
||||
if (selectList.value.length === 0) {
|
||||
message.info("请至少选择一名人员")
|
||||
return
|
||||
}
|
||||
|
||||
const params = {
|
||||
canSearch: val,
|
||||
selectList: selectList.value
|
||||
}
|
||||
|
||||
messageBox.confirm('确认设置?').then(async () => {
|
||||
try {
|
||||
await setCanSearch(params)
|
||||
message.success("设置成功")
|
||||
getDataList(false) // 设置后保持当前页
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '设置失败')
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.data-table {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
323
src/views/professional/teacherpayslip/salaryInfo.vue
Normal file
323
src/views/professional/teacherpayslip/salaryInfo.vue
Normal file
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" width="100%" v-loading="baseLoading" top="0" :close-on-click-modal="false" destroy-on-close>
|
||||
<!--基本信息-->
|
||||
<el-card shadow="hover">
|
||||
<el-row :span="24">
|
||||
<el-col>
|
||||
<el-table
|
||||
:data="salaryData.baseInfo"
|
||||
style="width: 100%">
|
||||
<el-table-column
|
||||
prop="realName"
|
||||
label="姓名"
|
||||
width="80">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="idCard"
|
||||
label="身份证号"
|
||||
width="200">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="年份"
|
||||
width="300">
|
||||
<template #default>
|
||||
<el-date-picker
|
||||
v-model="nowUser.nf"
|
||||
type="year"
|
||||
format="YYYY"
|
||||
value-format="YYYY"
|
||||
style="width: 200px"
|
||||
placeholder="选择年">
|
||||
</el-date-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="月份"
|
||||
width="300">
|
||||
<template #default>
|
||||
<el-date-picker
|
||||
v-model="nowUser.yff"
|
||||
type="month"
|
||||
format="M"
|
||||
value-format="M"
|
||||
style="width: 200px"
|
||||
placeholder="选择月">
|
||||
</el-date-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="200">
|
||||
<template #default>
|
||||
<el-button @click="searchUserInfo" type="primary" size="small">搜索</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover">
|
||||
<!--应发部分-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-table
|
||||
:data="salaryData.baseInfo"
|
||||
size="small"
|
||||
border
|
||||
>
|
||||
<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>
|
||||
<el-tag type="danger">基础工资应税收入= 岗位工资 +薪级工资+见习期工资+生活补贴+岗位津贴+教龄津贴+特教补贴+特级教师津贴+特岗津贴(1)+特岗津贴(2)+奖励绩效性工资+乡镇工作补贴+临时补贴+保留津贴+应休未休假-个人补缴-其他扣款-医疗救助金 </el-tag>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--应扣部分-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-table
|
||||
size="small"
|
||||
border
|
||||
:data="salaryData.baseInfo"
|
||||
style="width: 100%">
|
||||
<el-table-column label="应扣部分">
|
||||
<el-table-column label="住房公积金" width="90" prop="houseFund"></el-table-column>
|
||||
<el-table-column label="医疗保险金" width="90" prop="medicalInsurance"></el-table-column>
|
||||
<el-table-column label="失业保险金" width="90" prop="unemployInsurance"></el-table-column>
|
||||
<el-table-column label="养老保险金" width="90" prop="endowInsurance"></el-table-column>
|
||||
<el-table-column label="工会费" width="60" prop="unionFee"></el-table-column>
|
||||
<el-table-column label="儿童统筹" width="90" prop="childrenWhole"></el-table-column>
|
||||
<el-table-column label="个人所得税" width="90" prop="personalTax"></el-table-column>
|
||||
<el-table-column label="其他扣款" width="90" prop="otherDeduction"></el-table-column>
|
||||
<el-table-column label="病事假扣款" width="90" prop="sickDeduction"></el-table-column>
|
||||
<el-table-column label="医疗救助基金" width="90" prop="medicalFund"></el-table-column>
|
||||
<el-table-column label="工伤保险" width="90" prop="inductrialInjury"></el-table-column>
|
||||
<el-table-column label="个人补缴" width="90" prop="personalPay"></el-table-column>
|
||||
<el-table-column label="应扣合计" width="90" prop="withhold"></el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-tag>个人所得税 = 个税计算数据中的《 累计应补(退)税额 》</el-tag>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--劳务费-->
|
||||
<el-row v-if="showAllContent">
|
||||
<el-col :span="24">
|
||||
<el-table size="small" border :data="allProjectData">
|
||||
<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>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--专项扣除-->
|
||||
<el-row v-if="showAllContent">
|
||||
<el-col :span="24">
|
||||
<el-table
|
||||
size="small"
|
||||
border
|
||||
:data="salaryExtendData"
|
||||
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>
|
||||
<el-tag type="warning">应税收入= 基础工资应税收入+造单收入 </el-tag>
|
||||
<el-tag type="success">累计专项扣除=当年累计个人承担的住房公积金+医疗保险金+失业保险金+养老保险金 </el-tag>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--实发合计-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-table
|
||||
size="small"
|
||||
border
|
||||
:data="[staticsData]"
|
||||
empty-text=" ">
|
||||
<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>
|
||||
<el-tag type="primary">实发工资= 应发工资-应扣合计 </el-tag>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick } from 'vue'
|
||||
import { queryUserInfo, queryExtendSalaryInfo } from '/@/api/professional/salaries/teacherpayslip'
|
||||
import { checkAuth } from '/@/api/professional/salaries/teachersalary'
|
||||
|
||||
// 对话框显示状态
|
||||
const visible = ref(false)
|
||||
|
||||
// 数据
|
||||
const salaryData = reactive({
|
||||
baseInfo: [] as 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)
|
||||
|
||||
// 检查权限
|
||||
const checkAuthMethod = async () => {
|
||||
try {
|
||||
const res = await checkAuth()
|
||||
showAllContent.value = res.data.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)
|
||||
|
||||
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.data.salaryTax)
|
||||
allProjectData.value = res.data.data.allProject
|
||||
staticsData.orderMoney = res.data.data.totalMoney
|
||||
} catch (error) {
|
||||
// 查询失败
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索用户信息
|
||||
const searchUserInfo = async () => {
|
||||
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) {
|
||||
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
|
||||
makeUserInfo(resData)
|
||||
await queryExtendSalaryInfoMethod(resData)
|
||||
}
|
||||
} catch (error) {
|
||||
// 查询失败
|
||||
} 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)
|
||||
})
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user