✨ feat: 薪资计算
This commit is contained in:
32
ruoyi-ui/src/api/oa/salary.js
Normal file
32
ruoyi-ui/src/api/oa/salary.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据月份和文件计算工资
|
||||||
|
* @param {*} param0.monthStr: 月份
|
||||||
|
* @param {*} param0.filePath: 文件路径
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function calculateSalary({ monthStr, filePath }) {
|
||||||
|
return request({
|
||||||
|
url: '/oa/salary/calc',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
monthStr,
|
||||||
|
filePath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oss文件上传
|
||||||
|
*/
|
||||||
|
export function uploadOssFile(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/oss/upload',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
246
ruoyi-ui/src/views/oa/peoples/salary/staff/index.vue
Normal file
246
ruoyi-ui/src/views/oa/peoples/salary/staff/index.vue
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
<template>
|
||||||
|
<div class="salary-container">
|
||||||
|
<!-- 操作栏 -->
|
||||||
|
<div class="operation-bar">
|
||||||
|
<el-button type="primary" @click="showUploadDialog">新增计算</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="薪资计算"
|
||||||
|
:visible.sync="uploadVisible"
|
||||||
|
width="30%"
|
||||||
|
@closed="resetUpload"
|
||||||
|
:close-on-click-modal="false">
|
||||||
|
<el-form ref="calcForm">
|
||||||
|
<el-form-item label="计算月份" required>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="month"
|
||||||
|
type="month"
|
||||||
|
value-format="yyyyMM"
|
||||||
|
placeholder="选择月份"
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="isUploading">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="薪资文件" required>
|
||||||
|
<el-upload
|
||||||
|
class="upload-demo"
|
||||||
|
drag
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:file-list="fileList"
|
||||||
|
:disabled="isUploading">
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
<div class="el-upload__tip" slot="tip">仅支持xlsx格式文件</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="uploadVisible = false" :disabled="isUploading">取消</el-button>
|
||||||
|
<el-button @click="handleUpload" :disabled="fileList.length === 0">确认上传</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleSubmit"
|
||||||
|
:loading="isUploading"
|
||||||
|
:disabled="!filePath">
|
||||||
|
{{ isUploading ? '计算中...' : '开始计算' }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 计算结果展示 -->
|
||||||
|
<div class="result-area">
|
||||||
|
<!-- 历史记录 -->
|
||||||
|
<div class="history-section" v-if="!showCurrentResult">
|
||||||
|
<h3>计算历史</h3>
|
||||||
|
<el-table :data="historyData" stripe>
|
||||||
|
<el-table-column prop="calcMonth" label="月份" width="120"></el-table-column>
|
||||||
|
<el-table-column prop="calcTime" label="计算时间"></el-table-column>
|
||||||
|
<el-table-column prop="totalAmount" label="总金额">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #67C23A">¥ {{scope.row.totalAmount}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="120">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="text" @click="showDetail(scope.row)">查看</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 本次结果 -->
|
||||||
|
<div class="current-result" v-else>
|
||||||
|
<h3>{{ currentMonth }} 薪资计算结果</h3>
|
||||||
|
<el-table :data="currentResult" border>
|
||||||
|
<el-table-column prop="name" label="姓名"></el-table-column>
|
||||||
|
<el-table-column prop="baseSalary" label="基本工资"></el-table-column>
|
||||||
|
<el-table-column prop="bonus" label="奖金"></el-table-column>
|
||||||
|
<el-table-column prop="deduction" label="扣款"></el-table-column>
|
||||||
|
<el-table-column prop="total" label="实发工资">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span class="highlight">¥ {{scope.row.total}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="summary">
|
||||||
|
<span>合计人数:{{currentResult.length}} 人</span>
|
||||||
|
<span class="total-amount">总金额:¥ {{totalAmount}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { calculateSalary, uploadOssFile } from '@/api/oa/salary'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadVisible: false,
|
||||||
|
isUploading: false,
|
||||||
|
month: '',
|
||||||
|
fileList: [],
|
||||||
|
currentResult: [],
|
||||||
|
showCurrentResult: false,
|
||||||
|
currentMonth: '',
|
||||||
|
historyData: [],
|
||||||
|
filePath: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
canSubmit() {
|
||||||
|
return this.month && this.fileList.length > 0
|
||||||
|
},
|
||||||
|
totalAmount() {
|
||||||
|
return this.currentResult.reduce((sum, item) => sum + item.total, 0)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showUploadDialog() {
|
||||||
|
this.uploadVisible = true
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFileChange(file, fileList) {
|
||||||
|
// 限制单个文件上传
|
||||||
|
this.fileList = [fileList[fileList.length - 1]]
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleSubmit() {
|
||||||
|
try {
|
||||||
|
this.isUploading = true
|
||||||
|
|
||||||
|
// 第一步:上传文件
|
||||||
|
// const formData = new FormData()
|
||||||
|
// formData.append('file', this.fileList[0].raw)
|
||||||
|
|
||||||
|
// const { data } = await uploadOssFile(formData)
|
||||||
|
|
||||||
|
// const filePath = '/data' + data.url.split('/data')[1];
|
||||||
|
// console.log('上传成功,文件路径:', filePath, this.month)
|
||||||
|
|
||||||
|
// 第二步:提交计算
|
||||||
|
const { result } = await calculateSalary({
|
||||||
|
filePath: this.filePath,
|
||||||
|
monthStr: this.month
|
||||||
|
})
|
||||||
|
|
||||||
|
this.currentResult = result.details
|
||||||
|
this.currentMonth = this.month
|
||||||
|
this.showCurrentResult = true
|
||||||
|
|
||||||
|
// 更新历史记录
|
||||||
|
this.historyData.unshift({
|
||||||
|
calcMonth: this.month,
|
||||||
|
calcTime: new Date().toLocaleString(),
|
||||||
|
totalAmount: this.totalAmount
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$message.success('计算完成')
|
||||||
|
this.uploadVisible = false
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error(error.message || '计算失败')
|
||||||
|
} finally {
|
||||||
|
this.isUploading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
async handleUpload() {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', this.fileList[0].raw)
|
||||||
|
|
||||||
|
const { data } = await uploadOssFile(formData)
|
||||||
|
|
||||||
|
const filePath = '/data' + data.url.split('/data')[1];
|
||||||
|
this.filePath = filePath;
|
||||||
|
message.success('上传成功');
|
||||||
|
},
|
||||||
|
|
||||||
|
resetUpload() {
|
||||||
|
this.fileList = []
|
||||||
|
this.month = ''
|
||||||
|
},
|
||||||
|
|
||||||
|
showDetail(row) {
|
||||||
|
// 查看历史详情逻辑
|
||||||
|
console.log('查看详情', row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.salary-container {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-area {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-section h3,
|
||||||
|
.current-result h3 {
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-amount {
|
||||||
|
color: #67C23A;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
color: #E6A23C;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-demo {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user