Merge remote-tracking branch 'origin/main'

This commit is contained in:
2025-03-09 20:15:57 +08:00
3 changed files with 278 additions and 0 deletions

View 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'
}
})
}

View 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>