Files
ss-oa-manage-web/src/views/Home/Salary/index.vue
2025-02-17 14:12:34 +08:00

482 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<el-form :model="searchForm" ref="searchFormRef" inline @submit.prevent>
<el-form-item>
<el-input
v-model="searchForm.name"
placeholder="员工姓名"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item>
<el-date-picker
v-model="searchForm.period"
type="month"
format="YYYY-MM"
value-format="YYYY-MM"
placeholder="年月"
style="width: 100%"
@change="handleSearch"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleSearch" v-hasPermi="['home:salary:search']">查询</el-button>
<el-button type="primary" plain @click="craeteSalary" v-hasPermi="['home:salary:create']"
>生成工资条</el-button
>
<el-button type="primary" @click="importHistorySalary" v-hasPermi="['home:salary:history']"
>导入历史工资条</el-button
>
</el-form-item>
</el-form>
<el-table
v-loading="loading"
:data="tableList"
border
stripe
:default-expand-all="false"
row-key="id"
:tree-props="{ children: 'userSalaryGrantRespVOList', hasChildren: 'hasChildren' }"
:span-method="spanMethod"
>
<el-table-column label="姓名" min-width="90px" fixed="left">
<template #default="{ row }">
<span v-if="row.userSalaryGrantRespVOList && row.userSalaryGrantRespVOList.length">
<span>{{ row.period }}</span>
<span class="ml-20px">应发工资人数{{ row.grantNum }}</span>
<span class="ml-20px">应发工资¥{{ row.allGrantSalaryTotal }}</span>
</span>
<span v-else>
{{ row.name }}
</span>
</template>
</el-table-column>
<el-table-column prop="period" label="年月" min-width="90px" />
<el-table-column prop="dept" label="部门" min-width="90px" />
<el-table-column prop="post" label="职位" min-width="90px" />
<el-table-column label="应发工资" align="center">
<el-table-column label="无责底薪" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.baseSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.baseSalary }}</span>
</template>
</el-table-column>
<el-table-column label="标准绩效" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.meritsSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.meritsSalary }}</span>
</template>
</el-table-column>
<el-table-column label="绩效实发" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.reallyMeritsSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.reallyMeritsSalary }}</span>
</template>
</el-table-column>
<el-table-column label="补贴" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.allowanceSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.allowanceSalary }}</span>
</template>
</el-table-column>
<el-table-column label="提成" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.percentageSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.percentageSalary }}</span>
</template>
</el-table-column>
<el-table-column label="奖金" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.rewardSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.rewardSalary }}</span>
</template>
</el-table-column>
<el-table-column label="满勤" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.fullWorkSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.fullWorkSalary }}</span>
</template>
</el-table-column>
<el-table-column label="其他" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.extraSalary"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.extraSalary }}</span>
</template>
</el-table-column>
<el-table-column label="小计" prop="salaryTotal" min-width="90px" />
</el-table-column>
<el-table-column label="应扣工资" align="center">
<el-table-column label="请假" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.leaveDayDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.leaveDayDeduct }}</span>
</template>
</el-table-column>
<el-table-column min-width="90px">
<template #header>
<Tooltip message="月中入职,入职前无需考勤天数" titel="缺勤" />
</template>
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.absenceDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.absenceDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="旷工" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.skipWorkDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.skipWorkDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="违纪" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.breachDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.breachDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="公积金" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.accumulationFundDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.accumulationFundDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="社保" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.socialDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.socialDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="所得税" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.taxDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.taxDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="其他" min-width="90px">
<template #default="{ row }">
<el-input-number
v-if="row.edit"
v-model="row.extraDeduct"
:min="0"
:controls="false"
size="small"
style="width: 65px"
/>
<span v-else> {{ row.extraDeduct }}</span>
</template>
</el-table-column>
<el-table-column label="小计" prop="deductTotal" min-width="90px" />
</el-table-column>
<el-table-column label="实发工资" prop="gantSalary" fixed="right" width="90" />
<el-table-column label="操作" fixed="right" width="200">
<template #default="{ row }">
<el-button
type="primary"
style="padding: 0"
v-if="row.edit === '0'"
text
v-hasPermi="['home:salary:update']"
@click="handleEdit(row)"
>
修改
</el-button>
<el-button
type="primary"
v-else-if="row.edit === '1'"
text
style="padding: 0"
v-hasPermi="['home:salary:update']"
@click="handleSave(row)"
>
保存
</el-button>
<el-button
type="danger"
v-if="row.id"
:disabled="row.status == 1"
style="padding: 0"
text
v-hasPermi="['home:salary:sealup']"
@click="handleSealup(row)"
>
<span v-if="row.status == 0">封存</span>
<span v-else-if="row.status == 1">已封存</span>
</el-button>
<el-button type="primary" v-if="row.grantId" text @click="handleDetail(row)">
提成明细
</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:total="total"
v-model:page="searchForm.pageNo"
v-model:limit="searchForm.pageSize"
@pagination="getList"
/>
<DialogCreateSalary ref="createSalaryRef" @success="getList" />
<DialogSalaryImport ref="importSalaryRef" @success="getList" />
</div>
</template>
<script setup name="SalarySlip">
import DialogCreateSalary from './Comp/DialogCreateSalary.vue'
import DialogSalaryImport from './Comp/DialogSalaryImport.vue'
import { removeNullField } from '@/utils'
import * as SalaryApi from '@/api/home/salary.js'
import { ElLoading } from 'element-plus'
const message = useMessage() // 消息弹窗
const searchForm = ref({
name: undefined,
period: undefined,
pageNo: 1,
pageSize: 20
})
onMounted(() => {
handleSearch()
})
function handleSearch() {
searchForm.value.pageNo = 1
getList()
}
const loading = ref(false)
const tableList = ref([])
const total = ref(0)
async function getList() {
loading.value = true
try {
let params = {
...searchForm.value
}
if (params.period) {
params = {
...params,
year: new Date(params.period).getFullYear(),
month: new Date(params.period).getMonth() + 1
}
}
const data = await SalaryApi.getSalaryPage(removeNullField(params))
if (searchForm.value.name) {
tableList.value = data.list.reduce((pre, cur) => {
return pre.concat(cur.userSalaryGrantRespVOList)
}, [])
} else {
tableList.value = data.list.map((it, index) => ({
...it,
userSalaryGrantRespVOList: it.userSalaryGrantRespVOList.sort((pre, cur) =>
pre.name.localeCompare(cur.name)
),
id: index + 1,
edit: it.status == 1 ? '2' : '0'
}))
}
total.value = data.total
} catch (err) {
console.log(err)
} finally {
loading.value = false
}
}
const createSalaryRef = ref()
function craeteSalary() {
createSalaryRef.value.open()
}
const importSalaryRef = ref()
function importHistorySalary() {
importSalaryRef.value.open()
}
function spanMethod({ row, columnIndex }) {
if (row.userSalaryGrantRespVOList && row.userSalaryGrantRespVOList.length > 0) {
if (columnIndex === 0) {
return [1, 23]
} else if (columnIndex == 23 && row.id) {
return [1, 1]
} else {
return [0, 0]
}
}
}
function handleEdit(row) {
row.edit = '1'
row.userSalaryGrantRespVOList.forEach((it) => (it.edit = true))
}
const globalLoading = ref({})
async function handleSave(row) {
try {
row.edit = '0'
row.userSalaryGrantRespVOList.forEach((it) => (it.edit = false))
globalLoading.value = ElLoading.service({
lock: true,
text: `工资条数据保存中,请稍后...`,
background: 'rgba(0, 0, 0, 0.7)'
})
await SalaryApi.updateSalarySlip(row.userSalaryGrantRespVOList)
globalLoading.value.close()
message.success('保存成功!')
getList()
} catch {
globalLoading.value.close()
}
}
async function handleSealup(row) {
try {
// 二次确认
await message.confirm('确认要封存"' + row.period + '"工资条吗?')
// 发起修改状态
await SalaryApi.sealupSalarySlip({
grantIdList: row.userSalaryGrantRespVOList.map((it) => it.grantId),
period: row.period
})
message.success('封存成功!')
// 刷新列表
await getList()
} catch (err) {
console.log(err)
}
}
async function handleDetail(row) {
try {
const data = await SalaryApi.getCommissionDetail({ id: row.grantId })
if (data) {
message.alert(data)
} else {
message.info('该员工未配置提成方案!')
}
} catch (error) {
message.error(error)
console.log(error)
}
}
</script>
<style lang="scss" scoped>
:deep(.el-table__indent) {
display: none;
}
:deep(.el-table__placeholder) {
display: none;
}
</style>