<template>
|
<div class="app-container self-service-container">
|
|
<!-- 功能导航卡片 -->
|
<el-row :gutter="20" class="nav-cards">
|
<el-col :span="6" v-for="(item, index) in navItems" :key="index">
|
<el-card class="nav-card" @click="handleNavClick(item.type)">
|
<div class="nav-content">
|
<el-icon :size="40" class="nav-icon">
|
<component :is="item.icon" />
|
</el-icon>
|
<h3>{{ item.title }}</h3>
|
<p>{{ item.desc }}</p>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<!-- 主要内容区域 -->
|
<div class="main-content">
|
<!-- 考勤记录 -->
|
<el-card v-if="currentView === 'attendance'" class="content-card">
|
<template #header>
|
<div class="card-header">
|
<span>个人考勤记录</span>
|
<el-button type="primary" @click="addAttendanceRecord">新增记录</el-button>
|
</div>
|
</template>
|
<el-table :data="attendanceData" style="width: 100%" :loading="tableLoading">
|
<el-table-column prop="date" label="日期" />
|
<el-table-column prop="checkIn" label="签到时间" />
|
<el-table-column prop="checkOut" label="签退时间" />
|
<el-table-column prop="workHours" label="工作时长" width="100" />
|
<el-table-column prop="status" label="状态" width="100">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === '正常' ? 'success' : 'danger'">
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="150">
|
<template #default="scope">
|
<el-button size="small" @click="editAttendanceRecord(scope.row)">编辑</el-button>
|
<el-button size="small" type="danger" @click="deleteAttendanceRecord(scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<!-- 薪资单 -->
|
<el-card v-if="currentView === 'salary'" class="content-card">
|
<template #header>
|
<div class="card-header">
|
<span>薪资单查询</span>
|
<el-date-picker v-model="payDateStr" type="month" placeholder="选择月份" value-format="YYYY-MM" format="YYYY-MM" @change="changMonth"/>
|
</div>
|
</template>
|
<el-table :data="salaryData" style="width: 100%">
|
<el-table-column prop="payDate" label="月份" />
|
<el-table-column prop="basicSalary" label="基本工资" />
|
<el-table-column prop="bonus" label="奖金" />
|
<el-table-column prop="deduction" label="扣款" />
|
<el-table-column prop="actualWages" label="实发工资" />
|
<el-table-column prop="status" label="状态" >
|
<template #default="scope">
|
<el-tag :type="scope.row.status === '已发放' ? 'success' : 'warning'">
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<!-- 假期申请 -->
|
<el-card v-if="currentView === 'leave'" class="content-card">
|
<template #header>
|
<div class="card-header">
|
<span>假期申请管理</span>
|
<el-button type="primary" @click="openLeaveForm">申请假期</el-button>
|
</div>
|
</template>
|
<el-table :data="leaveData" style="width: 100%">
|
<el-table-column prop="type" label="假期类型" />
|
<el-table-column prop="startDate" label="开始日期" />
|
<el-table-column prop="endDate" label="结束日期" />
|
<el-table-column prop="days" label="天数" width="80" />
|
<el-table-column prop="reason" label="申请原因" />
|
<el-table-column prop="status" label="审批状态" width="100">
|
<template #default="scope">
|
<el-tag :type="getStatusType(scope.row.status)">
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="150">
|
<template #default="scope">
|
<el-button size="small" @click="editLeaveRecord(scope.row)">编辑</el-button>
|
<el-button size="small" type="danger" @click="deleteLeaveRecord(scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<!-- 个人信息 -->
|
<el-card v-if="currentView === 'profile'" class="content-card">
|
<template #header>
|
<div class="card-header">
|
<span>个人信息维护</span>
|
<el-button type="primary" @click="editProfileForm">编辑信息</el-button>
|
</div>
|
</template>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="姓名">{{ profile.name }}</el-descriptions-item>
|
<el-descriptions-item label="工号">{{ profile.employeeId }}</el-descriptions-item>
|
<el-descriptions-item label="部门">{{ profile.department }}</el-descriptions-item>
|
<el-descriptions-item label="职位">{{ profile.position }}</el-descriptions-item>
|
<el-descriptions-item label="入职日期">{{ profile.hireDate }}</el-descriptions-item>
|
<el-descriptions-item label="联系电话">{{ profile.phone }}</el-descriptions-item>
|
<el-descriptions-item label="邮箱">{{ profile.email }}</el-descriptions-item>
|
<el-descriptions-item label="地址">{{ profile.adress }}</el-descriptions-item>
|
</el-descriptions>
|
</el-card>
|
</div>
|
|
<!-- 假期申请弹窗 -->
|
<el-dialog v-model="showLeaveDialog" :title="leaveOperationType === 'add' ? '申请假期' : '编辑假期'" width="500px">
|
<el-form :model="leaveForm" label-width="100px">
|
<el-form-item label="假期类型">
|
<el-select v-model="leaveForm.type" placeholder="请选择假期类型">
|
<el-option label="年假" value="年假" />
|
<el-option label="病假" value="病假" />
|
<el-option label="调休" value="调休" />
|
<el-option label="事假" value="事假" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="开始日期">
|
<el-date-picker v-model="leaveForm.startDate" type="date" placeholder="选择开始日期" />
|
</el-form-item>
|
<el-form-item label="结束日期">
|
<el-date-picker v-model="leaveForm.endDate" type="date" placeholder="选择结束日期" />
|
</el-form-item>
|
<el-form-item label="申请原因">
|
<el-input v-model="leaveForm.reason" type="textarea" rows="3" />
|
</el-form-item>
|
<!-- <el-form-item label="审批状态">
|
<el-select v-model="leaveForm.status" placeholder="请选择审批状态">
|
<el-option label="审批中" value="审批中" />
|
<el-option label="已通过" value="已通过" />
|
<el-option label="已拒绝" value="已拒绝" />
|
</el-select>
|
</el-form-item> -->
|
</el-form>
|
<template #footer>
|
<el-button @click="showLeaveDialog = false">取消</el-button>
|
<el-button type="primary" @click="submitLeaveApplication">提交申请</el-button>
|
</template>
|
</el-dialog>
|
|
<!-- 新增-编辑考勤记录弹窗 -->
|
<el-dialog v-model="showAttendanceDialog" :title="operationType === 'add' ? '新增考勤记录' : '编辑考勤记录'" width="500px">
|
<el-form :model="attendanceForm" :rules="attendanceRules" ref="attendanceFormRef" label-width="100px">
|
<el-form-item label="日期" prop="date">
|
<el-date-picker v-model="attendanceForm.date" type="date" value-format="YYYY-MM-DD" format="YYYY-MM-DD" placeholder="选择日期" />
|
</el-form-item>
|
<el-form-item label="签到时间" prop="checkIn">
|
<el-time-picker v-model="attendanceForm.checkIn" placeholder="选择签到时间" format="HH:mm" value-format="HH:mm" />
|
</el-form-item>
|
<el-form-item label="签退时间" prop="checkOut">
|
<el-time-picker v-model="attendanceForm.checkOut" placeholder="选择签退时间" format="HH:mm" value-format="HH:mm" />
|
</el-form-item>
|
<el-form-item label="状态" prop="status">
|
<el-select v-model="attendanceForm.status" placeholder="请选择状态">
|
<el-option label="正常" value="正常" />
|
<el-option label="迟到" value="迟到" />
|
<el-option label="早退" value="早退" />
|
<el-option label="缺勤" value="缺勤" />
|
</el-select>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<el-button @click="showAttendanceDialog = false">取消</el-button>
|
<el-button type="primary" @click="submitAttendance">提交</el-button>
|
</template>
|
</el-dialog>
|
|
<!-- 个人信息编辑弹窗 -->
|
<el-dialog v-model="editProfile" title="编辑个人信息" width="500px">
|
<el-form :model="profileForm" label-width="100px">
|
<el-form-item label="姓名">
|
<el-input v-model="profileForm.name" />
|
</el-form-item>
|
<el-form-item label="联系电话">
|
<el-input v-model="profileForm.phone" />
|
</el-form-item>
|
<el-form-item label="邮箱">
|
<el-input v-model="profileForm.email" />
|
</el-form-item>
|
<el-form-item label="地址">
|
<el-input v-model="profileForm.adress" type="textarea" rows="2" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<el-button @click="editProfile = false">取消</el-button>
|
<el-button type="primary" @click="saveProfile">保存</el-button>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, watch, onMounted } from 'vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
import {
|
Calendar,
|
Money,
|
Clock,
|
User
|
} from '@element-plus/icons-vue'
|
import { personalAttendanceRecordsListPage, personalAttendanceRecordsAdd, personalAttendanceRecordsUpdate, personalAttendanceRecordsDelete, holidayApplicationListPage, holidayApplicationAdd, holidayApplicationUpdate, holidayApplicationDelete } from '@/api/personnelManagement/selfService'
|
import { compensationListPage, compensationAdd, compensationUpdate, compensationDelete } from '@/api/personnelManagement/payrollManagement'
|
|
const { proxy } = getCurrentInstance()
|
import { getUserProfile } from '@/api/system/user.js'
|
import {staffJoinUpdate, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
|
import { fa, id } from 'element-plus/es/locales.mjs'
|
|
const tableLoading = ref(false)
|
// 分页参数
|
const page = reactive({
|
current: 1,
|
size: 10,
|
total: 0
|
})
|
|
// 当前视图
|
const currentView = ref('attendance')
|
|
// 导航项
|
const navItems = [
|
{ type: 'attendance', title: '考勤记录', desc: '查询个人考勤信息', icon: 'Calendar' },
|
{ type: 'salary', title: '薪资单', desc: '查看薪资发放记录', icon: 'Money' },
|
{ type: 'leave', title: '假期申请', desc: '在线申请各类假期', icon: 'Clock' },
|
{ type: 'profile', title: '个人信息', desc: '维护个人基本信息', icon: 'User' }
|
]
|
|
// 考勤数据
|
const attendanceData = ref([])
|
|
// 薪资数据
|
const salaryData = ref([])
|
|
|
// 假期数据
|
const leaveData = ref([])
|
|
const currentUser = ref()
|
const user= ref()
|
// 个人信息
|
const profile = ref({
|
id: '',
|
name: '',
|
employeeId: '',
|
department: '',
|
position: '',
|
hireDate: '',
|
phone: '',
|
email: '',
|
adress: ''
|
})
|
|
// 弹窗控制
|
const showLeaveDialog = ref(false)
|
const editProfile = ref(false)
|
const payDateStr = ref('')
|
|
// 表单数据
|
const leaveForm = reactive({
|
id: '',
|
type: '',
|
startDate: '',
|
endDate: '',
|
days: 0,
|
reason: '',
|
status: ''
|
})
|
const profileForm = reactive({
|
name: "",
|
email: "",
|
adress: "",
|
phone: "",
|
})
|
const joinForm = reactive({
|
id: "",
|
staffNo: "",
|
staffName: "",
|
email: "",
|
adress: "",
|
sex: "",
|
nativePlace: "",
|
postJob: "",
|
firstStudy: "",
|
profession: "",
|
identityCard: "",
|
age: 0,
|
phone: "",
|
emergencyContact: "",
|
emergencyContactPhone: "",
|
contractTerm: 0,
|
contractStartTime: "",
|
contractEndTime: "",
|
staffState: 1,
|
})
|
|
// 新增考勤记录:弹窗与表单
|
const operationType = ref('add')
|
const leaveOperationType = ref('add')
|
const showAttendanceDialog = ref(false)
|
const attendanceFormRef = ref(null)
|
const attendanceForm = reactive({
|
id: '',
|
date: '',
|
checkIn: '',
|
checkOut: '',
|
workHours: '',
|
status: '正常'
|
})
|
const attendanceRules = {
|
date: [{ required: true, message: '请选择日期', trigger: 'change' }],
|
checkIn: [{ required: true, message: '请选择签到时间', trigger: 'change' }],
|
checkOut: [{ required: true, message: '请选择签退时间', trigger: 'change' }],
|
status: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
}
|
|
// 处理导航点击
|
const handleNavClick = (type) => {
|
currentView.value = type
|
}
|
|
// 获取状态类型
|
const getStatusType = (status) => {
|
const types = {
|
'已通过': 'success',
|
'审批中': 'warning',
|
'已拒绝': 'danger'
|
}
|
return types[status] || 'info'
|
}
|
|
// 新增考勤记录(打开弹窗并预填默认值)
|
const addAttendanceRecord = () => {
|
operationType.value = 'add'
|
attendanceForm.date = new Date().toISOString().split('T')[0]
|
attendanceForm.checkIn = '09:00'
|
attendanceForm.checkOut = '18:00'
|
attendanceForm.status = '正常'
|
showAttendanceDialog.value = true
|
}
|
|
// 计算工时
|
const computeWorkHours = (inStr, outStr) => {
|
const [inH, inM] = inStr.split(':').map(n => parseInt(n, 10))
|
const [outH, outM] = outStr.split(':').map(n => parseInt(n, 10))
|
const inMin = inH * 60 + inM
|
const outMin = outH * 60 + outM
|
const diff = Math.max(0, outMin - inMin)
|
const h = Math.floor(diff / 60)
|
const m = diff % 60
|
return m === 0 ? `${h}小时` : `${h}小时${m}分`
|
}
|
|
// 编辑考勤记录
|
const editAttendanceRecord = (row) => {
|
operationType.value = 'edit'
|
Object.assign(attendanceForm, row)
|
showAttendanceDialog.value = true
|
}
|
// 提交新增-编辑考勤记录
|
const submitAttendance = () => {
|
// if (!attendanceFormRef.value) return
|
const workHours = computeWorkHours(attendanceForm.checkIn, attendanceForm.checkOut)
|
const newRecord = {
|
date: attendanceForm.date,
|
checkIn: attendanceForm.checkIn,
|
checkOut: attendanceForm.checkOut,
|
workHours,
|
status: attendanceForm.status
|
}
|
if (operationType.value === 'add') {
|
personalAttendanceRecordsAdd(newRecord)
|
.then(res => {
|
if (res.code === 200) {
|
ElMessage.success('考勤记录添加成功')
|
getPersonalAttendanceRecordsList()
|
showAttendanceDialog.value = false
|
// 重置表单
|
attendanceForm.date = ''
|
attendanceForm.checkIn = ''
|
attendanceForm.checkOut = ''
|
attendanceForm.status = '正常'
|
}
|
}).catch(err => {
|
ElMessage.error('考勤记录添加失败')
|
})
|
}else{
|
attendanceForm.workHours = computeWorkHours(attendanceForm.checkIn, attendanceForm.checkOut)
|
personalAttendanceRecordsUpdate(attendanceForm)
|
.then(res => {
|
if (res.code === 200) {
|
ElMessage.success('考勤记录更新成功')
|
getPersonalAttendanceRecordsList()
|
showAttendanceDialog.value = false
|
// 重置表单
|
attendanceForm.date = ''
|
attendanceForm.checkIn = ''
|
attendanceForm.checkOut = ''
|
attendanceForm.status = '正常'
|
}
|
}).catch(err => {
|
ElMessage.error('考勤记录更新失败')
|
})
|
}
|
// attendanceFormRef.value.validate((valid) => {
|
// if (!valid) return
|
|
|
// })
|
}
|
// 删除考勤记录
|
const deleteAttendanceRecord = (row) => {
|
|
ElMessageBox.confirm('确定删除该考勤记录吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
personalAttendanceRecordsDelete(row.id)
|
.then(res => {
|
if (res.code === 200) {
|
ElMessage.success('考勤记录删除成功')
|
getPersonalAttendanceRecordsList()
|
}
|
}).catch(err => {
|
ElMessage.error('考勤记录删除失败')
|
})
|
}).catch(() => {
|
ElMessage({
|
type: 'info',
|
message: '已取消删除'
|
})
|
})
|
}
|
// 申请假期
|
const openLeaveForm = () => {
|
leaveOperationType.value = 'add'
|
showLeaveDialog.value = true
|
// leaveForm.type = ''
|
// leaveForm.startDate = ''
|
// leaveForm.endDate = ''
|
// leaveForm.days = 0
|
// leaveForm.reason = ''
|
// leaveForm.status = 'warning'
|
}
|
// 编辑假期记录
|
const editLeaveRecord = (row) => {
|
leaveOperationType.value = 'edit'
|
showLeaveDialog.value = true
|
Object.assign(leaveForm, row)
|
// ElMessage.info('编辑功能开发中...')
|
}
|
|
// 删除假期记录
|
const deleteLeaveRecord = (row) => {
|
ElMessageBox.confirm('确定删除该假期记录吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
holidayApplicationDelete(row.id)
|
.then(res => {
|
if (res.code === 200) {
|
ElMessage.success('假期记录删除成功')
|
getHolidayApplicationList()
|
}
|
}).catch(err => {
|
ElMessage.error('假期记录删除失败')
|
})
|
}).catch(() => {
|
ElMessage({
|
type: 'info',
|
message: '已取消删除'
|
})
|
})
|
}
|
|
//计算假期天数
|
const calculateDays = () => {
|
try {
|
if (leaveForm.startDate && leaveForm.endDate) {
|
const start = new Date(leaveForm.startDate)
|
const end = new Date(leaveForm.endDate)
|
leaveForm.startDate = start.toISOString().split('T')[0]
|
leaveForm.endDate = end.toISOString().split('T')[0]
|
|
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
console.warn('无效的日期格式')
|
return
|
}
|
|
const diffTime = Math.abs(end - start)
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1
|
leaveForm.days = diffDays
|
}
|
} catch (error) {
|
console.error('计算天数失败:', error)
|
}
|
}
|
|
// 提交假期申请
|
const submitLeaveApplication = () => {
|
if (leaveOperationType.value === 'add') {
|
if (!leaveForm.type || !leaveForm.startDate || !leaveForm.endDate || !leaveForm.reason) {
|
ElMessage.warning('请填写完整信息')
|
return
|
}
|
calculateDays()
|
const newLeave = {
|
type: leaveForm.type,
|
startDate: leaveForm.startDate,
|
endDate: leaveForm.endDate,
|
days: leaveForm.days, // 简单计算
|
reason: leaveForm.reason,
|
status: '审批中'
|
}
|
|
holidayApplicationAdd(newLeave)
|
.then(res => {
|
if (res.code === 200) {
|
ElMessage.success('假期申请提交成功')
|
getHolidayApplicationList()
|
showLeaveDialog.value = false
|
// 重置表单
|
Object.keys(leaveForm).forEach(key => {
|
leaveForm[key] = ''
|
})
|
}
|
}).catch(err => {
|
ElMessage.error('假期申请提交失败')
|
})
|
}else{
|
calculateDays()
|
holidayApplicationUpdate(leaveForm)
|
.then(res => {
|
if (res.code === 200) {
|
ElMessage.success('假期申请更新成功')
|
getHolidayApplicationList()
|
showLeaveDialog.value = false
|
// 重置表单
|
Object.keys(leaveForm).forEach(key => {
|
leaveForm[key] = ''
|
})
|
}
|
}).catch(err => {
|
ElMessage.error('假期申请更新失败')
|
})
|
}
|
}
|
|
// 获取个人信息
|
const getProfile = () => {
|
tableLoading.value = true;
|
getUserProfile().then(res => {
|
if (res.code === 200) {
|
currentUser.value = res.data
|
// console.log("----",currentUser.value)
|
//得到人员列表
|
staffJoinListPage({staffState: 1}).then(res => {
|
//筛选出和currentUser同名的人员
|
// let tableData = res.data.records
|
user.value = res.data.records.find(item => item.staffName === currentUser.value.userName)
|
// console.log("++++",user.value)
|
if(user.value){
|
profile.value.id=user.value.id
|
profile.value.name=user.value.staffName
|
profile.value.employeeId=user.value.staffNo
|
profile.value.phone=user.value.phone
|
profile.value.email=currentUser.value.email
|
profile.value.adress=user.value.adress
|
profile.value.position=user.value.postJob
|
profile.value.hireDate=user.value.createTime
|
profile.value.department=currentUser.value.deptNames
|
}
|
// console.log(profile.value)
|
// tableLoading.value = false;
|
}).catch(err => {})
|
}
|
}).catch(err => {
|
tableLoading.value = false;
|
ElMessage.error('获取个人信息失败')
|
})
|
}
|
// 保存个人信息
|
const saveProfile = async () => {
|
tableLoading.value = true;
|
try {
|
const userRes = await getUserProfile();
|
if (userRes.code === 200) {
|
currentUser.value = userRes.data;
|
const staffListRes = await staffJoinListPage({ staffState: 1 });
|
user.value = staffListRes.data.records.find(item => item.staffName === currentUser.value.userName);
|
// console.log("++++", user.value);
|
|
Object.assign(joinForm, user.value);
|
joinForm.staffName = profileForm.name;
|
joinForm.phone = profileForm.phone;
|
joinForm.email = profileForm.email;
|
joinForm.adress = profileForm.adress;
|
console.log(joinForm)
|
// 调用更新个人信息的接口
|
staffJoinUpdate(joinForm).then(res => {
|
if (res.code === 200) {
|
ElMessage.success('个人信息保存成功');
|
getProfile();
|
editProfile.value = false;
|
}
|
}).catch(err => {
|
ElMessage.error('个人信息保存失败');
|
})
|
}
|
} catch (err) {
|
ElMessage.error('获取个人信息失败');
|
} finally {
|
tableLoading.value = false;
|
}
|
};
|
|
// 编辑个人信息
|
const editProfileForm = () => {
|
editProfile.value = true;
|
Object.assign(profileForm, {
|
name: profile.value.name,
|
phone: profile.value.phone,
|
email: profile.value.email,
|
adress: profile.value.adress,
|
});
|
};
|
|
//月份改变
|
const changMonth = () => {
|
getCompensationList()
|
}
|
//获取考勤记录列表
|
const getPersonalAttendanceRecordsList = async () => {
|
tableLoading.value = true
|
personalAttendanceRecordsListPage(page)
|
.then(res => {
|
|
attendanceData.value = res.data.records
|
page.value.total = res.data.total;
|
tableLoading.value = false;
|
|
}).catch(err => {
|
tableLoading.value = false;
|
})
|
}
|
//薪资单查询
|
const getCompensationList = async () => {
|
tableLoading.value = true
|
compensationListPage({...page,payDateStr:payDateStr.value})
|
.then(res => {
|
salaryData.value = res.data.records
|
//过滤出当前月份的扣款合计
|
salaryData.value.forEach(item => {
|
item.deduction =0 + item.deductionAbsenteeism+item.sickLeaveDeductions+item.deductionPersonalLeave+item.forgetClockDeduct,
|
item.bonus=0,
|
item.status='已发放'
|
})
|
|
page.value.total = res.data.total;
|
tableLoading.value = false;
|
}).catch(err => {
|
tableLoading.value = false;
|
})
|
}
|
//获取假期申请列表
|
const getHolidayApplicationList = async () => {
|
tableLoading.value = true
|
holidayApplicationListPage(page)
|
.then(res => {
|
leaveData.value = res.data.records
|
page.value.total = res.data.total;
|
tableLoading.value = false;
|
}).catch(err => {
|
tableLoading.value = false;
|
})
|
}
|
onMounted(() => {
|
// 初始化
|
getPersonalAttendanceRecordsList()
|
getCompensationList()
|
getHolidayApplicationList()
|
getProfile()
|
})
|
</script>
|
|
<style scoped>
|
.self-service-container {
|
padding: 20px;
|
background-color: #f5f7fa;
|
min-height: 100vh;
|
}
|
|
.page-header {
|
text-align: center;
|
margin-bottom: 30px;
|
padding: 20px;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
border-radius: 12px;
|
color: white;
|
}
|
|
.page-header h2 {
|
color: white;
|
margin-bottom: 10px;
|
font-size: 28px;
|
font-weight: 600;
|
}
|
|
.page-header p {
|
color: rgba(255, 255, 255, 0.9);
|
font-size: 14px;
|
margin: 0;
|
}
|
|
.nav-cards {
|
margin-bottom: 30px;
|
}
|
|
.nav-card {
|
cursor: pointer;
|
transition: all 0.3s ease;
|
border-radius: 12px;
|
border: none;
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
}
|
|
.nav-card:hover {
|
transform: translateY(-5px);
|
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
}
|
|
.nav-content {
|
text-align: center;
|
padding: 20px;
|
}
|
|
.nav-icon {
|
color: #409EFF;
|
margin-bottom: 15px;
|
}
|
|
.nav-content h3 {
|
margin: 0 0 10px 0;
|
color: #303133;
|
font-size: 18px;
|
}
|
|
.nav-content p {
|
margin: 0;
|
color: #909399;
|
font-size: 14px;
|
}
|
|
.main-content {
|
margin-bottom: 30px;
|
}
|
|
.content-card {
|
border-radius: 12px;
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
border: none;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
font-weight: 600;
|
color: #303133;
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 768px) {
|
.self-service-container {
|
padding: 10px;
|
}
|
|
.nav-cards .el-col {
|
margin-bottom: 15px;
|
}
|
|
.page-header h2 {
|
font-size: 24px;
|
}
|
}
|
</style>
|