You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
546 lines
14 KiB
546 lines
14 KiB
<!--员工-我的工资-->
|
|
<template>
|
|
<view class="main_box">
|
|
<view class="main_section">
|
|
|
|
<!-- 筛选条件 -->
|
|
<view class="filter_section">
|
|
<view class="filter_item">
|
|
<picker mode="date" fields="month" :value="selectedMonth" @change="onMonthChange">
|
|
<view class="picker_display">
|
|
<text>{{ selectedMonth || '选择月份' }}</text>
|
|
<text class="picker_arrow">></text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
<view class="filter_btn" @click="loadSalaryList">查询</view>
|
|
</view>
|
|
|
|
<!-- 工资条列表 -->
|
|
<view class="salary_list" v-if="salaryList.length > 0">
|
|
<view
|
|
class="salary_item"
|
|
v-for="(item, index) in salaryList"
|
|
:key="item.id"
|
|
@click="viewSalaryDetail(item)"
|
|
>
|
|
<view class="salary_header">
|
|
<view class="salary_month">{{ formatMonth(item.salary_month) }}</view>
|
|
<view class="salary_status" :class="getStatusClass(item.status)">
|
|
{{ getStatusText(item.status) }}
|
|
</view>
|
|
</view>
|
|
|
|
<view class="salary_content">
|
|
<view class="salary_row">
|
|
<text class="label">基础工资:</text>
|
|
<text class="value">¥{{ formatMoney(item.base_salary) }}</text>
|
|
</view>
|
|
<view class="salary_row">
|
|
<text class="label">出勤工资:</text>
|
|
<text class="value">¥{{ formatMoney(item.work_salary) }}</text>
|
|
</view>
|
|
<view class="salary_row">
|
|
<text class="label">应发工资:</text>
|
|
<text class="value highlight">¥{{ formatMoney(item.gross_salary) }}</text>
|
|
</view>
|
|
<view class="salary_row">
|
|
<text class="label">实发工资:</text>
|
|
<text class="value net_salary">¥{{ formatMoney(item.net_salary) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="salary_footer">
|
|
<text class="view_detail">点击查看详情 ></text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 暂无数据 -->
|
|
<view class="no_data" v-else-if="!loading">
|
|
<image class="no_data_icon" src="/static/images/no_data.png" mode="aspectFit"></image>
|
|
<text class="no_data_text">暂无工资数据</text>
|
|
</view>
|
|
|
|
<!-- 加载中 -->
|
|
<view class="loading" v-if="loading">
|
|
<text>加载中...</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 工资详情弹窗 -->
|
|
<view class="salary_modal" v-if="showDetail" @click="closeDetail">
|
|
<view class="modal_content" @click.stop>
|
|
<view class="modal_header">
|
|
<text class="modal_title">工资详情</text>
|
|
<text class="modal_close" @click="closeDetail">×</text>
|
|
</view>
|
|
|
|
<view class="modal_body" v-if="salaryDetail">
|
|
<view class="detail_section">
|
|
<view class="section_title">基础信息</view>
|
|
<view class="detail_row">
|
|
<text class="detail_label">工资月份:</text>
|
|
<text class="detail_value">{{ formatMonth(salaryDetail.salary_month) }}</text>
|
|
</view>
|
|
<view class="detail_row">
|
|
<text class="detail_label">基础工资:</text>
|
|
<text class="detail_value">¥{{ formatMoney(salaryDetail.base_salary) }}</text>
|
|
</view>
|
|
<view class="detail_row">
|
|
<text class="detail_label">满勤天数:</text>
|
|
<text class="detail_value">{{ salaryDetail.full_attendance_days }}天</text>
|
|
</view>
|
|
<view class="detail_row">
|
|
<text class="detail_label">出勤天数:</text>
|
|
<text class="detail_value">{{ salaryDetail.attendance }}天</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail_section">
|
|
<view class="section_title">收入明细</view>
|
|
<view class="detail_row">
|
|
<text class="detail_label">出勤工资:</text>
|
|
<text class="detail_value">¥{{ formatMoney(salaryDetail.work_salary) }}</text>
|
|
</view>
|
|
<view class="detail_row" v-if="salaryDetail.mgr_performance > 0">
|
|
<text class="detail_label">管理绩效:</text>
|
|
<text class="detail_value">¥{{ formatMoney(salaryDetail.mgr_performance) }}</text>
|
|
</view>
|
|
<view class="detail_row" v-if="salaryDetail.performance_bonus > 0">
|
|
<text class="detail_label">销售提成:</text>
|
|
<text class="detail_value">¥{{ formatMoney(salaryDetail.performance_bonus) }}</text>
|
|
</view>
|
|
<view class="detail_row" v-if="salaryDetail.other_subsidies > 0">
|
|
<text class="detail_label">其他补贴:</text>
|
|
<text class="detail_value">¥{{ formatMoney(salaryDetail.other_subsidies) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail_section">
|
|
<view class="section_title">扣除明细</view>
|
|
<view class="detail_row" v-if="salaryDetail.deductions > 0">
|
|
<text class="detail_label">其他扣款:</text>
|
|
<text class="detail_value text_red">-¥{{ formatMoney(salaryDetail.deductions) }}</text>
|
|
</view>
|
|
<view class="detail_row" v-if="salaryDetail.social_security > 0">
|
|
<text class="detail_label">社保:</text>
|
|
<text class="detail_value text_red">-¥{{ formatMoney(salaryDetail.social_security) }}</text>
|
|
</view>
|
|
<view class="detail_row" v-if="salaryDetail.individual_income_tax > 0">
|
|
<text class="detail_label">个税:</text>
|
|
<text class="detail_value text_red">-¥{{ formatMoney(salaryDetail.individual_income_tax) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail_section">
|
|
<view class="section_title">工资汇总</view>
|
|
<view class="detail_row highlight_row">
|
|
<text class="detail_label">应发工资:</text>
|
|
<text class="detail_value highlight">¥{{ formatMoney(salaryDetail.gross_salary) }}</text>
|
|
</view>
|
|
<view class="detail_row net_salary_row">
|
|
<text class="detail_label">实发工资:</text>
|
|
<text class="detail_value net_salary">¥{{ formatMoney(salaryDetail.net_salary) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail_section" v-if="salaryDetail.remarks">
|
|
<view class="section_title">备注</view>
|
|
<view class="detail_remarks">{{ salaryDetail.remarks }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import memberApi from '@/api/member.js';
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
selectedMonth: '',
|
|
salaryList: [],
|
|
loading: false,
|
|
showDetail: false,
|
|
salaryDetail: null,
|
|
}
|
|
},
|
|
|
|
onLoad() {
|
|
// 默认查询当月数据
|
|
const now = new Date();
|
|
this.selectedMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
|
|
this.loadSalaryList();
|
|
},
|
|
|
|
methods: {
|
|
// 月份选择
|
|
onMonthChange(e) {
|
|
this.selectedMonth = e.detail.value;
|
|
},
|
|
|
|
// 加载工资列表
|
|
async loadSalaryList() {
|
|
this.loading = true;
|
|
try {
|
|
const params = {};
|
|
if (this.selectedMonth) {
|
|
params.salary_month = this.selectedMonth;
|
|
}
|
|
|
|
const res = await memberApi.getSalaryList(params);
|
|
if (res.code === 1) {
|
|
this.salaryList = res.data.list || [];
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg || '获取数据失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('获取工资列表失败:', error);
|
|
uni.showToast({
|
|
title: '网络错误,请稍后重试',
|
|
icon: 'none'
|
|
});
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
// 查看工资详情
|
|
async viewSalaryDetail(item) {
|
|
try {
|
|
const res = await memberApi.getSalaryInfo({ id: item.id });
|
|
if (res.code === 1) {
|
|
this.salaryDetail = res.data;
|
|
this.showDetail = true;
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg || '获取详情失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('获取工资详情失败:', error);
|
|
uni.showToast({
|
|
title: '网络错误,请稍后重试',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
},
|
|
|
|
// 关闭详情弹窗
|
|
closeDetail() {
|
|
this.showDetail = false;
|
|
this.salaryDetail = null;
|
|
},
|
|
|
|
// 格式化月份显示
|
|
formatMonth(month) {
|
|
if (!month) return '';
|
|
return month.substring(0, 7).replace('-', '年') + '月';
|
|
},
|
|
|
|
// 格式化金额
|
|
formatMoney(amount) {
|
|
if (!amount && amount !== 0) return '0.00';
|
|
return Number(amount).toFixed(2);
|
|
},
|
|
|
|
// 获取状态文字
|
|
getStatusText(status) {
|
|
switch (status) {
|
|
case 1: return '未发放';
|
|
case 2: return '已发放';
|
|
default: return '未知';
|
|
}
|
|
},
|
|
|
|
// 获取状态样式类
|
|
getStatusClass(status) {
|
|
switch (status) {
|
|
case 1: return 'status_pending';
|
|
case 2: return 'status_paid';
|
|
default: return '';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.main_box {
|
|
background: #292929;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.main_section {
|
|
padding: 20rpx;
|
|
padding-bottom: 150rpx;
|
|
}
|
|
|
|
/* 筛选条件 */
|
|
.filter_section {
|
|
display: flex;
|
|
align-items: center;
|
|
background: #434544;
|
|
border-radius: 10rpx;
|
|
padding: 20rpx;
|
|
margin-bottom: 20rpx;
|
|
|
|
.filter_item {
|
|
flex: 1;
|
|
|
|
.picker_display {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
color: #D7D7D7;
|
|
font-size: 28rpx;
|
|
|
|
.picker_arrow {
|
|
color: #25a18b;
|
|
font-size: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.filter_btn {
|
|
background: #25a18b;
|
|
color: #fff;
|
|
padding: 15rpx 30rpx;
|
|
border-radius: 8rpx;
|
|
font-size: 26rpx;
|
|
margin-left: 20rpx;
|
|
}
|
|
}
|
|
|
|
/* 工资条列表 */
|
|
.salary_list {
|
|
.salary_item {
|
|
background: #434544;
|
|
border-radius: 10rpx;
|
|
padding: 30rpx;
|
|
margin-bottom: 20rpx;
|
|
|
|
.salary_header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
padding-bottom: 15rpx;
|
|
border-bottom: 1rpx solid #555;
|
|
|
|
.salary_month {
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.salary_status {
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 20rpx;
|
|
font-size: 24rpx;
|
|
|
|
&.status_pending {
|
|
background: rgba(255, 165, 0, 0.2);
|
|
color: #FFA500;
|
|
}
|
|
|
|
&.status_paid {
|
|
background: rgba(34, 197, 94, 0.2);
|
|
color: #22c55e;
|
|
}
|
|
}
|
|
}
|
|
|
|
.salary_content {
|
|
.salary_row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 15rpx;
|
|
|
|
.label {
|
|
color: #D7D7D7;
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
.value {
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
|
|
&.highlight {
|
|
color: #25a18b;
|
|
font-weight: bold;
|
|
}
|
|
|
|
&.net_salary {
|
|
color: #22c55e;
|
|
font-weight: bold;
|
|
font-size: 30rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.salary_footer {
|
|
text-align: center;
|
|
margin-top: 20rpx;
|
|
padding-top: 15rpx;
|
|
border-top: 1rpx solid #555;
|
|
|
|
.view_detail {
|
|
color: #25a18b;
|
|
font-size: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 暂无数据 */
|
|
.no_data {
|
|
text-align: center;
|
|
padding: 100rpx 0;
|
|
color: #888;
|
|
|
|
.no_data_icon {
|
|
width: 150rpx;
|
|
height: 150rpx;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.no_data_text {
|
|
font-size: 28rpx;
|
|
}
|
|
}
|
|
|
|
/* 加载中 */
|
|
.loading {
|
|
text-align: center;
|
|
padding: 50rpx 0;
|
|
color: #888;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
/* 工资详情弹窗 */
|
|
.salary_modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 1000;
|
|
|
|
.modal_content {
|
|
background: #434544;
|
|
border-radius: 15rpx;
|
|
width: 90%;
|
|
max-height: 80%;
|
|
overflow: hidden;
|
|
|
|
.modal_header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 30rpx;
|
|
border-bottom: 1rpx solid #555;
|
|
|
|
.modal_title {
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.modal_close {
|
|
color: #888;
|
|
font-size: 40rpx;
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
}
|
|
|
|
.modal_body {
|
|
max-height: 60vh;
|
|
overflow-y: auto;
|
|
padding: 30rpx;
|
|
|
|
.detail_section {
|
|
margin-bottom: 40rpx;
|
|
|
|
.section_title {
|
|
color: #25a18b;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
margin-bottom: 20rpx;
|
|
padding-bottom: 10rpx;
|
|
border-bottom: 1rpx solid #555;
|
|
}
|
|
|
|
.detail_row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 15rpx;
|
|
|
|
.detail_label {
|
|
color: #D7D7D7;
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
.detail_value {
|
|
color: #fff;
|
|
font-size: 26rpx;
|
|
|
|
&.highlight {
|
|
color: #25a18b;
|
|
font-weight: bold;
|
|
}
|
|
|
|
&.net_salary {
|
|
color: #22c55e;
|
|
font-weight: bold;
|
|
}
|
|
|
|
&.text_red {
|
|
color: #f56565;
|
|
}
|
|
}
|
|
}
|
|
|
|
&.highlight_row {
|
|
background: rgba(37, 161, 139, 0.1);
|
|
padding: 15rpx;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
&.net_salary_row {
|
|
background: rgba(34, 197, 94, 0.1);
|
|
padding: 15rpx;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
.detail_remarks {
|
|
background: #555;
|
|
padding: 20rpx;
|
|
border-radius: 8rpx;
|
|
color: #D7D7D7;
|
|
font-size: 26rpx;
|
|
line-height: 1.6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|