dev-cl
qsh 2 months ago
parent 8142e05543
commit 9dada27bd0
  1. 18
      src/api/home/salary.js
  2. 2
      src/config/axios/service.ts
  3. 23
      src/utils/download.ts
  4. 14
      src/views/Home/Salary/Comp/DialogCreateSalary.vue
  5. 99
      src/views/Home/Salary/Comp/DialogSalaryImport.vue
  6. 56
      src/views/Home/Salary/index.vue

@ -2,7 +2,7 @@ import request from '@/config/axios'
// 查询工资条 // 查询工资条
export const getSalaryPage = async (params) => { export const getSalaryPage = async (params) => {
return await request.get({ url: '/admin-api/oa/user-salary-grant/page', params }) return await request.get({ url: '/admin-api/oa/user-salary-grant/periodPage', params })
} }
// 生成工资条 // 生成工资条
@ -15,8 +15,8 @@ export const createSalarySlip = async (data) => {
} }
// 导入工资条 // 导入工资条
export const importSalarySlip = async (params) => { export const importSalarySlip = async (data) => {
return await request.get({ url: '/admin-api/oa/user-salary-grant/import', params }) return await request.post({ url: '/admin-api/oa/user-salary-grant/import', data })
} }
// 修改工资条 // 修改工资条
@ -31,15 +31,21 @@ export const sealupSalarySlip = async (data) => {
// 获取考勤模板链接 // 获取考勤模板链接
export const getLinkAttendance = async () => { export const getLinkAttendance = async () => {
return await request.get({ url: '/admin-api/oa/user-attendance/get-import-template' }) return await request.download({
url: '/admin-api/oa/user-attendance/get-import-template'
})
} }
// 获取奖金模板 // 获取奖金模板
export const getLinkReward = async () => { export const getLinkReward = async () => {
return await request.get({ url: '/admin-api/oa/user-salary-grant/get-import-template' }) return await request.download({
url: '/admin-api/oa/user-salary-grant/get-import-template'
})
} }
// 获取历史工资条模板 // 获取历史工资条模板
export const getLinkHistorySalary = async () => { export const getLinkHistorySalary = async () => {
return await request.get({ url: '/admin-api/oa/user-salary-grant/get-import-template/history' }) return await request.download({
url: '/admin-api/oa/user-salary-grant/get-import-template/history'
})
} }

@ -79,7 +79,7 @@ service.interceptors.request.use(
config.data = qs.stringify(data) config.data = qs.stringify(data)
} }
// get参数编码 // get参数编码
if (config.method?.toUpperCase() === 'GET' && params) { if (config.method?.toUpperCase() === 'GET' && Object.keys(params).length > 0) {
config.params = {} config.params = {}
const paramsStr = qs.stringify(params, { allowDots: true }) const paramsStr = qs.stringify(params, { allowDots: true })
if (paramsStr) { if (paramsStr) {

@ -1,6 +1,7 @@
const download0 = (data: Blob, fileName: string, mineType: string) => { const download0 = (data: Blob, fileName: string, mineType: string) => {
// 创建 blob // 创建 blob
const blob = new Blob([data], { type: mineType }) const blob = new Blob([data], { type: mineType })
// 创建 href 超链接,点击进行下载 // 创建 href 超链接,点击进行下载
window.URL = window.URL || window.webkitURL window.URL = window.URL || window.webkitURL
const href = URL.createObjectURL(blob) const href = URL.createObjectURL(blob)
@ -15,7 +16,11 @@ const download0 = (data: Blob, fileName: string, mineType: string) => {
const download = { const download = {
// 下载 Excel 方法 // 下载 Excel 方法
excel: (data: Blob, fileName: string) => { excel: (data: Blob, fileName: string) => {
download0(data, fileName, 'application/vnd.ms-excel') download0(
data,
fileName,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8'
)
}, },
// 下载 Word 方法 // 下载 Word 方法
word: (data: Blob, fileName: string) => { word: (data: Blob, fileName: string) => {
@ -36,19 +41,3 @@ const download = {
} }
export default download export default download
export function downloadFile(url: string, fileName: string) {
const link = document.createElement('a')
// 这里是将url转成blob地址,
fetch(url)
.then((res) => res.blob())
.then((blob) => {
// 将链接地址字符内容转变成blob地址
link.href = URL.createObjectURL(blob)
link.download = fileName
document.body.appendChild(link)
link.click()
URL.revokeObjectURL(link.href) //清除引用
document.body.removeChild(link)
})
}

@ -16,7 +16,7 @@
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12" :offset="0"> <el-col :span="12" :offset="0">
<el-form-item label="导入奖金"> <el-form-item label="导入工资">
<div> <div>
<el-upload <el-upload
ref="rewardFile" ref="rewardFile"
@ -70,7 +70,7 @@
<script setup name="DialogCreateSalary"> <script setup name="DialogCreateSalary">
import * as SalaryApi from '@/api/home/salary.js' import * as SalaryApi from '@/api/home/salary.js'
import { downloadFile } from '@/utils/download' import download from '@/utils/download'
const message = useMessage() // const message = useMessage() //
const dialogVisible = ref(false) const dialogVisible = ref(false)
@ -104,13 +104,10 @@ async function handleSave() {
if (!formRef.value) return if (!formRef.value) return
const valid = await formRef.value.validate() const valid = await formRef.value.validate()
if (!valid) return if (!valid) return
if (!fd.value.get('attendanceFile')) {
message.info('请导入考勤表!')
return
}
// //
formLoading.value = true formLoading.value = true
try { try {
fd.value.delete('period')
fd.value.append('period', formData.value.period) fd.value.append('period', formData.value.period)
await SalaryApi.createSalarySlip(fd.value) await SalaryApi.createSalarySlip(fd.value)
message.success('生成成功') message.success('生成成功')
@ -126,10 +123,11 @@ async function downloadTemplateFile(type) {
let data let data
if (type == 1) { if (type == 1) {
data = await SalaryApi.getLinkReward() data = await SalaryApi.getLinkReward()
downloadFile(data, '奖金模板.xls') console.log(data)
download.excel(data, '奖金模板.xls')
} else if (type == 2) { } else if (type == 2) {
data = await SalaryApi.getLinkAttendance() data = await SalaryApi.getLinkAttendance()
downloadFile(data, '考勤模板.xls') download.excel(data, '考勤模板.xls')
} }
} }

@ -1,6 +1,6 @@
<template> <template>
<Dialog v-model="dialogVisible" title="导入历史工资条" style="width: 600px"> <Dialog v-model="dialogVisible" title="导入历史工资条" style="width: 500px">
<el-form :model="formData" ref="formRef" :rules="rules" label-width="80px"> <el-form :model="formData" ref="formRef" :rules="rules" label-width="auto">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="24" :offset="0"> <el-col :span="24" :offset="0">
<el-form-item label="年月" prop="period"> <el-form-item label="年月" prop="period">
@ -16,22 +16,24 @@
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="24" :offset="0"> <el-col :span="24" :offset="0">
<el-form-item label="导入工资条"> <el-form-item label="工资文件">
<UploadFile <div>
v-model="formData.rewardSalaryFile" <el-upload
:limit="1" ref="salaryFile"
:fileType="['xls', 'xlsx']" action="#"
accept=".xls,.xlsx" :limit="1"
:isShowTip="false" accept=".xls,.xlsx"
> :before-upload="fileBeforeUpload"
<template #tip> :http-request="salaryUpload"
<div> >
<el-link type="primary" :underline="false" @click="downloadTemplateFile(3)"> <el-button type="primary">
点击下载模板文件 <Icon icon="ep:upload" class="mr-5px" /> 点击上传
</el-link> </el-button>
</div> </el-upload>
</template> <el-link type="primary" :underline="false" @click="downloadTemplateFile(3)">
</UploadFile> 点击下载模板文件
</el-link>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -39,7 +41,7 @@
<template #footer> <template #footer>
<span> <span>
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" :disabled="formLoading" @click="handleSave"> 生成 </el-button> <el-button type="primary" :disabled="formLoading" @click="handleSave"> </el-button>
</span> </span>
</template> </template>
</Dialog> </Dialog>
@ -47,8 +49,9 @@
<script setup name="DialogSalaryImport"> <script setup name="DialogSalaryImport">
import * as SalaryApi from '@/api/home/salary.js' import * as SalaryApi from '@/api/home/salary.js'
import { downloadFile } from '@/utils/download' import download from '@/utils/download'
const message = useMessage() //
const dialogVisible = ref(false) const dialogVisible = ref(false)
const formData = ref({}) const formData = ref({})
@ -56,8 +59,7 @@ const formData = ref({})
const formLoading = ref(false) const formLoading = ref(false)
const rules = { const rules = {
period: { required: true, message: '年月不可为空', trigger: 'blur,change' }, period: { required: true, message: '年月不可为空', trigger: 'blur,change' }
attendanceFile: { required: true, message: '考勤文件不可为空', trigger: 'blur,change' }
} }
function open() { function open() {
@ -67,23 +69,66 @@ function open() {
function resetForm() { function resetForm() {
formData.value = { formData.value = {
period: `${new Date().getFullYear()}-${new Date().getMonth() + 1}`, period: `${new Date().getFullYear()}-${new Date().getMonth() + 1}`
rewardSalaryFile: '',
attendanceFile: ''
} }
} }
defineExpose({ open }) defineExpose({ open })
function handleSave() {} const emit = defineEmits(['success'])
const formRef = ref()
async function handleSave() {
//
if (!formRef.value) return
const valid = await formRef.value.validate()
if (!valid) return
if (!fd.value.get('file')) {
message.info('请上传工资文件!')
return
}
//
formLoading.value = true
try {
fd.value.delete('period')
fd.value.append('period', formData.value.period)
await SalaryApi.importSalarySlip(fd.value)
message.success('导入成功')
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
async function downloadTemplateFile(type) { async function downloadTemplateFile(type) {
let data let data
if (type == 3) { if (type == 3) {
data = await SalaryApi.getLinkHistorySalary() data = await SalaryApi.getLinkHistorySalary()
downloadFile(data, '工资条模板.xls') download.excel(data, '工资条模板.xls')
} }
} }
const fileBeforeUpload = (file) => {
let format = '.' + file.name.split('.')[1]
if (!['.xls', '.xlsx'].includes(format)) {
message.error(`请上传指定格式".xls,.xlsx"文件`)
return false
}
let isRightSize = file.size / 1024 / 1024 < 20
if (!isRightSize) {
message.error('文件大小超过 20MB')
}
return isRightSize
}
const fd = ref()
function salaryUpload(data) {
fd.value = new FormData()
fd.value.append('file', data.file)
}
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

@ -11,8 +11,10 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-date-picker <el-date-picker
v-model="searchForm.yearmonth" v-model="searchForm.period"
type="month" type="month"
format="YYYY-MM"
value-format="YYYY-MM"
placeholder="年月" placeholder="年月"
style="width: 100%" style="width: 100%"
@change="handleSearch" @change="handleSearch"
@ -36,20 +38,22 @@
stripe stripe
:default-expand-all="false" :default-expand-all="false"
row-key="id" row-key="id"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :tree-props="{ children: 'userSalaryGrantRespVOList', hasChildren: 'hasChildren' }"
:span-method="spanMethod" :span-method="spanMethod"
> >
<el-table-column label="姓名" min-width="90px"> <el-table-column label="姓名" min-width="90px">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row.children && row.children.length"> <span v-if="row.userSalaryGrantRespVOList && row.userSalaryGrantRespVOList.length">
<span>{{ row.yearmonth }}</span> <span>{{ row.period }}</span>
<span class="ml-20px">应发工资人数30</span> <span class="ml-20px">应发工资人数{{ row.grantNum }}</span>
<span class="ml-20px">应发工资¥{{ row.allGrantSalaryTotal }}</span>
</span> </span>
<span v-else> <span v-else>
{{ row.name }} {{ row.name }}
</span> </span>
</template> </template>
</el-table-column> </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="dept" label="部门" min-width="90px" />
<el-table-column prop="post" label="职位" min-width="90px" /> <el-table-column prop="post" label="职位" min-width="90px" />
<el-table-column label="应发工资" align="center"> <el-table-column label="应发工资" align="center">
@ -262,7 +266,7 @@
<el-button <el-button
type="primary" type="primary"
style="padding: 0" style="padding: 0"
v-if="!row.edit && row.yearmonth" v-if="row.edit === '0'"
text text
v-hasPermi="['home:salary:update']" v-hasPermi="['home:salary:update']"
@click="handleEdit(row)" @click="handleEdit(row)"
@ -271,7 +275,7 @@
</el-button> </el-button>
<el-button <el-button
type="primary" type="primary"
v-else-if="row.edit && row.yearmonth" v-else-if="row.edit === '1'"
text text
style="padding: 0" style="padding: 0"
v-hasPermi="['home:salary:update']" v-hasPermi="['home:salary:update']"
@ -281,7 +285,7 @@
</el-button> </el-button>
<el-button <el-button
type="danger" type="danger"
v-if="row.yearmonth" v-if="row.id"
style="padding: 0" style="padding: 0"
text text
v-hasPermi="['home:salary:sealup']" v-hasPermi="['home:salary:sealup']"
@ -314,9 +318,9 @@ import * as SalaryApi from '@/api/home/salary.js'
const searchForm = ref({ const searchForm = ref({
name: undefined, name: undefined,
yearmonth: undefined, period: undefined,
pageNo: 1, pageNo: 1,
pageSize: 50 pageSize: 20
}) })
onMounted(() => { onMounted(() => {
@ -337,15 +341,25 @@ async function getList() {
let params = { let params = {
...searchForm.value ...searchForm.value
} }
if (params.yearmonth) { if (params.period) {
params = { params = {
...params, ...params,
year: new Date(params.yearmonth).getFullYear(), year: new Date(params.period).getFullYear(),
month: new Date(params.yearmonth).getMonth() + 1 month: new Date(params.period).getMonth() + 1
} }
} }
const data = await SalaryApi.getSalaryPage(removeNullField(params)) const data = await SalaryApi.getSalaryPage(removeNullField(params))
tableList.value = data.list 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,
id: index + 1,
edit: '0'
}))
}
total.value = data.total total.value = data.total
} catch (err) { } catch (err) {
console.log(err) console.log(err)
@ -365,10 +379,10 @@ function importHistorySalary() {
} }
function spanMethod({ row, columnIndex }) { function spanMethod({ row, columnIndex }) {
if (row.children && row.children.length > 0) { if (row.userSalaryGrantRespVOList && row.userSalaryGrantRespVOList.length > 0) {
if (columnIndex === 0) { if (columnIndex === 0) {
return [1, 21] return [1, 22]
} else if (columnIndex == 21) { } else if (columnIndex == 22 && row.id) {
return [1, 1] return [1, 1]
} else { } else {
return [0, 0] return [0, 0]
@ -377,13 +391,13 @@ function spanMethod({ row, columnIndex }) {
} }
function handleEdit(row) { function handleEdit(row) {
row.edit = true row.edit = '1'
row.children.forEach((it) => (it.edit = true)) row.userSalaryGrantRespVOList.forEach((it) => (it.edit = true))
} }
function handleSave(row) { function handleSave(row) {
row.edit = false row.edit = '0'
row.children.forEach((it) => (it.edit = false)) row.userSalaryGrantRespVOList.forEach((it) => (it.edit = false))
} }
</script> </script>

Loading…
Cancel
Save