feat(hrm): 新增人力资源管理系统功能模块
新增请假、外出、报餐等HRM功能模块及相关组件 添加审批流程管理及待办事项功能 扩展用户信息存储nickName字段 优化部门选择组件及代理配置
This commit is contained in:
44
klp-ui/src/api/wms/approval.js
Normal file
44
klp-ui/src/api/wms/approval.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询通用审批(支持请假/外出等申请的审批)列表
|
||||
export function listApproval(query) {
|
||||
return request({
|
||||
url: '/wms/approval/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询通用审批(支持请假/外出等申请的审批)详细
|
||||
export function getApproval(approvalId) {
|
||||
return request({
|
||||
url: '/wms/approval/' + approvalId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增通用审批(支持请假/外出等申请的审批)
|
||||
export function addApproval(data) {
|
||||
return request({
|
||||
url: '/wms/approval',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改通用审批(支持请假/外出等申请的审批)
|
||||
export function updateApproval(data) {
|
||||
return request({
|
||||
url: '/wms/approval',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除通用审批(支持请假/外出等申请的审批)
|
||||
export function delApproval(approvalId) {
|
||||
return request({
|
||||
url: '/wms/approval/' + approvalId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
44
klp-ui/src/api/wms/outRequest.js
Normal file
44
klp-ui/src/api/wms/outRequest.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询员工外出申请列表
|
||||
export function listOutRequest(query) {
|
||||
return request({
|
||||
url: '/wms/outRequest/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询员工外出申请详细
|
||||
export function getOutRequest(outId) {
|
||||
return request({
|
||||
url: '/wms/outRequest/' + outId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增员工外出申请
|
||||
export function addOutRequest(data) {
|
||||
return request({
|
||||
url: '/wms/outRequest',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改员工外出申请
|
||||
export function updateOutRequest(data) {
|
||||
return request({
|
||||
url: '/wms/outRequest',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除员工外出申请
|
||||
export function delOutRequest(outId) {
|
||||
return request({
|
||||
url: '/wms/outRequest/' + outId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
17
klp-ui/src/components/KLPService/DeptSelect/index.vue
Normal file
17
klp-ui/src/components/KLPService/DeptSelect/index.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listDept } from '@/api/wms/hrm/dept'
|
||||
|
||||
export default {
|
||||
name: 'DeptSelect',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -9,6 +9,7 @@ const getters = {
|
||||
avatar: state => state.user.avatar,
|
||||
id: state => state.user.id,
|
||||
name: state => state.user.name,
|
||||
nickName: state => state.user.nickName,
|
||||
avatar: state => state.user.avatar,
|
||||
introduction: state => state.user.introduction,
|
||||
roles: state => state.user.roles,
|
||||
|
||||
@@ -6,6 +6,7 @@ const user = {
|
||||
id: '',
|
||||
token: getToken(),
|
||||
name: '',
|
||||
nickName: '',
|
||||
avatar: '',
|
||||
roles: [],
|
||||
permissions: []
|
||||
@@ -18,6 +19,9 @@ const user = {
|
||||
SET_NAME: (state, name) => {
|
||||
state.name = name
|
||||
},
|
||||
SET_NICK_NAME: (state, nickName) => {
|
||||
state.nickName = nickName
|
||||
},
|
||||
SET_AVATAR: (state, avatar) => {
|
||||
state.avatar = avatar
|
||||
},
|
||||
@@ -63,6 +67,7 @@ const user = {
|
||||
commit('SET_ROLES', ['ROLE_DEFAULT'])
|
||||
}
|
||||
commit('SET_NAME', user.userName)
|
||||
commit('SET_NICK_NAME', user.nickName)
|
||||
commit('SET_AVATAR', avatar)
|
||||
commit('SET_ID', user.userId)
|
||||
resolve(res)
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="leader">
|
||||
<el-input
|
||||
v-model="queryParams.leader"
|
||||
placeholder="请输入负责人"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
@@ -54,10 +62,11 @@
|
||||
:data="deptList"
|
||||
row-key="deptId"
|
||||
:default-expand-all="isExpandAll"
|
||||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
||||
<el-table-column prop="orderNum" label="排序" width="200"></el-table-column>
|
||||
<el-table-column prop="leader" label="负责人" width="200"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
||||
|
||||
315
klp-ui/src/views/wms/hrm/apply/goout.vue
Normal file
315
klp-ui/src/views/wms/hrm/apply/goout.vue
Normal file
@@ -0,0 +1,315 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-card>
|
||||
<template slot="header">
|
||||
<span>提交请假申请</span>
|
||||
</template>
|
||||
<!-- 左侧是新增表单 -->
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px" v-loading="loading">
|
||||
<el-form-item label="审批部门" prop="applicantDeptName">
|
||||
<el-select v-model="form.applicantDeptName" placeholder="请选择审批部门" filterable @change="getDeptLeader">
|
||||
<el-option v-for="item in deptOptions" :key="item.deptId"
|
||||
:label="item.deptName + '(' + (item.leader || '无负责人') + ')'" :value="item.deptName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="外出类型" prop="outType">
|
||||
<el-select v-model="form.outType" placeholder="请选择外出类型">
|
||||
<el-option v-for="dict in dict.type.hrm_out_type" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="外出人姓名" prop="applicantName">
|
||||
<dict-select v-model="form.applicantName" dict-type="hrm_leave_employee"
|
||||
placeholder="请选择外出人姓名"></dict-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<el-date-picker clearable v-model="form.startTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择外出开始时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="endTime">
|
||||
<el-date-picker clearable v-model="form.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择外出结束时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="外出小时数" prop="outHours">
|
||||
<el-input v-model="form.outHours" placeholder="选择时间后自动计算,也可手动修改" />
|
||||
</el-form-item>
|
||||
<el-form-item label="外出地点" prop="outPlace">
|
||||
<el-input v-model="form.outPlace" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="外出原因" prop="outReason">
|
||||
<el-input v-model="form.outReason" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="attachmentUrls">
|
||||
<FileUpload v-model="form.attachmentUrls" :max-count="1" :show-file-list="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align: center;">
|
||||
<el-button type="primary" @click="handleSubmit" v-loading="loading">{{ form.applyId ? '更新申请' : '提交申请' }}</el-button>
|
||||
<el-button @click="handleReset">重置表单</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-card>
|
||||
<template slot="header">
|
||||
<span>请假申请列表</span>
|
||||
<el-button style="float: right;" icon="el-icon-refresh" @click="getList">刷新</el-button>
|
||||
</template>
|
||||
<el-table v-loading="loading" :data="leaveRequestList">
|
||||
<el-table-column label="申请状态" align="center" prop="approvalStatus"></el-table-column>
|
||||
<el-table-column label="外出类型" align="center" prop="outType">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.hrm_out_type" :value="scope.row.outType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="外出人姓名" align="center" prop="applicantName">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.hrm_leave_employee" :value="scope.row.applicantName" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批人" align="center" prop="approverName"></el-table-column>
|
||||
<el-table-column label="开始时间" align="center" prop="startTime" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="endTime" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="外出小时数" align="center" prop="outHours" />
|
||||
<el-table-column label="外出地点" align="center" prop="outPlace" show-overflow-tooltip />
|
||||
<el-table-column label="外出原因" align="center" prop="outReason" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" width="160">
|
||||
<template slot-scope="scope" v-if="scope.row.approvalStatus === '待审批'">
|
||||
<el-button icon="el-icon-edit" size="mini" @click="handleEdit(scope.row)">修改</el-button>
|
||||
<el-button icon="el-icon-delete" size="mini" @click="handleWithdraw(scope.row)">撤回</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getOutRequest, addOutRequest, updateOutRequest } from "@/api/wms/outRequest";
|
||||
import { listApproval, updateApproval } from "@/api/wms/approval"
|
||||
import { listDept } from "@/api/system/dept"
|
||||
import FileUpload from '@/components/FileUpload'
|
||||
import DictSelect from '@/components/DictSelect'
|
||||
|
||||
export default {
|
||||
name: 'LeaveApply',
|
||||
dicts: ['hrm_leave_shift', 'hrm_out_type', 'hrm_department', 'hrm_leave_employee'],
|
||||
components: {
|
||||
FileUpload,
|
||||
DictSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 表单参数
|
||||
form: {},
|
||||
loading: false,
|
||||
buttonLoading: false,
|
||||
leaveRequestList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
leaveStatus: undefined,
|
||||
applyType: 'out',
|
||||
createBy: this.$store.getters.name,
|
||||
},
|
||||
// 表单校验规则【核心新增:完整必填校验】
|
||||
rules: {
|
||||
leaveTitle: [{ required: true, message: '请假原因不能为空', trigger: ['blur', 'change'] }],
|
||||
leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'change' }],
|
||||
applicantName: [{ required: true, message: '请假人姓名不能为空', trigger: 'change' }],
|
||||
startTime: [{ required: true, message: '开始时间不能为空', trigger: 'change' }],
|
||||
endTime: [{ required: true, message: '结束时间不能为空', trigger: 'change' }],
|
||||
leaveShift: [{ required: true, message: '请假班次不能为空', trigger: 'change' }],
|
||||
leaveDays: [
|
||||
{ required: true, message: '请假天数不能为空', trigger: ['blur', 'change'] },
|
||||
],
|
||||
applicantDeptName: [{ required: true, message: '审批部门不能为空', trigger: 'change' }],
|
||||
},
|
||||
deptOptions: []
|
||||
}
|
||||
},
|
||||
// 核心新增:监听开始/结束时间变化,自动计算天数
|
||||
watch: {
|
||||
'form.startTime': {
|
||||
handler() {
|
||||
this.calculateLeaveDays()
|
||||
},
|
||||
immediate: false
|
||||
},
|
||||
'form.endTime': {
|
||||
handler() {
|
||||
this.calculateLeaveDays()
|
||||
},
|
||||
immediate: false
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDeptList();
|
||||
},
|
||||
methods: {
|
||||
getDeptList() {
|
||||
listDept().then(response => {
|
||||
this.deptOptions = response.data
|
||||
})
|
||||
},
|
||||
// 获取部门负责人
|
||||
getDeptLeader() {
|
||||
const selectedDept = this.deptOptions.find(item => item.deptName === this.form.applicantDeptName)
|
||||
const approverName = selectedDept.leader;
|
||||
if (!approverName) {
|
||||
this.$message.warning('该部门无负责人,申请将无人审批');
|
||||
return;
|
||||
}
|
||||
this.form.approverName = approverName
|
||||
},
|
||||
/** 查询员工请假申请列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listApproval(this.queryParams).then(response => {
|
||||
this.leaveRequestList = response.rows.map(item => {
|
||||
return {
|
||||
approvalStatus: item.approval.approvalStatus,
|
||||
applyId: item.approval.applyId,
|
||||
approvalId: item.approval.approvalId,
|
||||
approvalType: item.approval.approvalType,
|
||||
approverName: item.approval.approverName,
|
||||
...item.detail,
|
||||
}
|
||||
});
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleReset() {
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
outId: undefined,
|
||||
outTitle: undefined,
|
||||
outType: undefined,
|
||||
applicantName: undefined,
|
||||
applicantDeptName: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
outHours: undefined,
|
||||
outPlace: undefined,
|
||||
outReason: undefined,
|
||||
attachmentUrls: undefined,
|
||||
createBy: undefined,
|
||||
createTime: undefined,
|
||||
updateBy: undefined,
|
||||
updateTime: undefined,
|
||||
delFlag: undefined,
|
||||
remark: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleEdit(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const outId = row.applyId
|
||||
getOutRequest(outId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
handleSubmit() {
|
||||
this.form.outTitle = `${this.form.applicantName}-${this.form.outType}-${this.form.startTime}-${this.form.outReason || ''}`
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.outId != null) {
|
||||
updateOutRequest(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.getList();
|
||||
this.reset()
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addOutRequest(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.getList();
|
||||
this.reset()
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleWithdraw(row) {
|
||||
this.$modal.confirm('是否确认撤回请假申请编号为"' + row.applyId + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return updateApproval({
|
||||
approvalId: row.approvalId,
|
||||
approvalStatus: '已撤销'
|
||||
});
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("撤回成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 核心新增:自动计算请假天数的方法
|
||||
calculateLeaveDays() {
|
||||
const { startTime, endTime } = this.form;
|
||||
// 两个时间都选择后才计算
|
||||
if (startTime && endTime) {
|
||||
// 转成时间戳
|
||||
const start = new Date(startTime).getTime();
|
||||
const end = new Date(endTime).getTime();
|
||||
// 判断结束时间不能小于开始时间
|
||||
if (end < start) {
|
||||
this.$modal.msgWarning('结束时间不能早于开始时间,请重新选择!');
|
||||
this.form.leaveDays = undefined;
|
||||
return;
|
||||
}
|
||||
// 计算时间差(毫秒) → 转天 → 保留2位小数
|
||||
const diffTime = end - start;
|
||||
const diffHours = parseInt((diffTime / (1000 * 60 * 60)));
|
||||
// 赋值到天数输入框
|
||||
this.form.outHours = diffHours;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
325
klp-ui/src/views/wms/hrm/apply/leave.vue
Normal file
325
klp-ui/src/views/wms/hrm/apply/leave.vue
Normal file
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-card>
|
||||
<template slot="header">
|
||||
<span>提交请假申请</span>
|
||||
</template>
|
||||
<!-- 左侧是新增表单 -->
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px" v-loading="loading">
|
||||
<el-form-item label="审批部门" prop="applicantDeptName">
|
||||
<!-- <dict-select v-model="form.applicantDeptName" dict-type="hrm_department"
|
||||
placeholder="请选择审批部门"></dict-select> -->
|
||||
<el-select v-model="form.applicantDeptName" placeholder="请选择审批部门" filterable @change="getDeptLeader">
|
||||
<el-option v-for="item in deptOptions" :key="item.deptId"
|
||||
:label="item.deptName + '(' + (item.leader || '无负责人') + ')'" :value="item.deptName"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请假类型" prop="leaveType">
|
||||
<el-select v-model="form.leaveType" placeholder="请选择请假类型">
|
||||
<el-option v-for="dict in dict.type.hrm_leave_type" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请假人姓名" prop="applicantName">
|
||||
<dict-select v-model="form.applicantName" dict-type="hrm_leave_employee"
|
||||
placeholder="请选择请假人姓名"></dict-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<el-date-picker clearable v-model="form.startTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择请假开始时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="endTime">
|
||||
<el-date-picker clearable v-model="form.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择请假结束时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="请假班次" prop="leaveShift">
|
||||
<el-select v-model="form.leaveShift" placeholder="请选择请假班次">
|
||||
<el-option v-for="dict in dict.type.hrm_leave_shift" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请假天数" prop="leaveDays">
|
||||
<el-input v-model="form.leaveDays" placeholder="选择时间后自动计算,也可手动修改" />
|
||||
</el-form-item>
|
||||
<el-form-item label="请假原因" prop="leaveReason">
|
||||
<el-input v-model="form.leaveReason" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="attachmentUrls">
|
||||
<FileUpload v-model="form.attachmentUrls" :max-count="1" :show-file-list="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align: center;">
|
||||
<el-button type="primary" @click="handleSubmit" v-loading="loading">{{ form.applyId ? '更新申请' : '提交申请' }}</el-button>
|
||||
<el-button @click="handleReset">重置表单</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-card>
|
||||
<template slot="header">
|
||||
<span>请假申请列表</span>
|
||||
<el-button style="float: right;" icon="el-icon-refresh" @click="getList">刷新</el-button>
|
||||
</template>
|
||||
<el-table v-loading="loading" :data="leaveRequestList">
|
||||
<el-table-column label="申请状态" align="center" prop="approvalStatus"></el-table-column>
|
||||
<el-table-column label="请假类型" align="center" prop="leaveType">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.hrm_leave_type" :value="scope.row.leaveType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请假人姓名" align="center" prop="applicantName">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.hrm_leave_employee" :value="scope.row.applicantName" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批人" align="center" prop="approverName"></el-table-column>
|
||||
<el-table-column label="开始时间" align="center" prop="startTime" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="endTime" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请假班次" align="center" prop="leaveShift">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.hrm_leave_shift" :value="scope.row.leaveShift" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="具体原因" align="center" prop="leaveReason" show-overflow-tooltip />
|
||||
<el-table-column label="请假天数" align="center" prop="leaveDays" />
|
||||
<el-table-column label="操作" align="center" width="160">
|
||||
<template slot-scope="scope" v-if="scope.row.approvalStatus === '待审批'">
|
||||
<el-button icon="el-icon-edit" size="mini" @click="handleEdit(scope.row)">修改</el-button>
|
||||
<el-button icon="el-icon-delete" size="mini" @click="handleWithdraw(scope.row)">撤回</el-button>
|
||||
<!-- <el-button type="primary" size="mini" @click="handleApprove(scope.row)">删除</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLeaveRequest, addLeaveRequest, updateLeaveRequest } from "@/api/wms/leaveRequest";
|
||||
import { listApproval, updateApproval } from "@/api/wms/approval"
|
||||
import { listDept } from "@/api/system/dept"
|
||||
import FileUpload from '@/components/FileUpload'
|
||||
import DictSelect from '@/components/DictSelect'
|
||||
|
||||
export default {
|
||||
name: 'LeaveApply',
|
||||
dicts: ['hrm_leave_shift', 'hrm_leave_type', 'hrm_department', 'hrm_leave_employee'],
|
||||
components: {
|
||||
FileUpload,
|
||||
DictSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 表单参数
|
||||
form: {},
|
||||
loading: false,
|
||||
buttonLoading: false,
|
||||
leaveRequestList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
leaveStatus: undefined,
|
||||
applyType: 'leave',
|
||||
createBy: this.$store.getters.name,
|
||||
},
|
||||
// 表单校验规则【核心新增:完整必填校验】
|
||||
rules: {
|
||||
leaveTitle: [{ required: true, message: '请假原因不能为空', trigger: ['blur', 'change'] }],
|
||||
leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'change' }],
|
||||
applicantName: [{ required: true, message: '请假人姓名不能为空', trigger: 'change' }],
|
||||
startTime: [{ required: true, message: '开始时间不能为空', trigger: 'change' }],
|
||||
endTime: [{ required: true, message: '结束时间不能为空', trigger: 'change' }],
|
||||
leaveShift: [{ required: true, message: '请假班次不能为空', trigger: 'change' }],
|
||||
leaveDays: [
|
||||
{ required: true, message: '请假天数不能为空', trigger: ['blur', 'change'] },
|
||||
],
|
||||
applicantDeptName: [{ required: true, message: '审批部门不能为空', trigger: 'change' }],
|
||||
},
|
||||
deptOptions: []
|
||||
}
|
||||
},
|
||||
// 核心新增:监听开始/结束时间变化,自动计算天数
|
||||
watch: {
|
||||
'form.startTime': {
|
||||
handler() {
|
||||
this.calculateLeaveDays()
|
||||
},
|
||||
immediate: false
|
||||
},
|
||||
'form.endTime': {
|
||||
handler() {
|
||||
this.calculateLeaveDays()
|
||||
},
|
||||
immediate: false
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDeptList();
|
||||
},
|
||||
methods: {
|
||||
getDeptList() {
|
||||
listDept().then(response => {
|
||||
this.deptOptions = response.data
|
||||
})
|
||||
},
|
||||
// 获取部门负责人
|
||||
getDeptLeader() {
|
||||
const selectedDept = this.deptOptions.find(item => item.deptName === this.form.applicantDeptName)
|
||||
const approverName = selectedDept.leader;
|
||||
if (!approverName) {
|
||||
this.$message.warning('该部门无负责人,申请将无人审批');
|
||||
return;
|
||||
}
|
||||
this.form.approverName = approverName
|
||||
},
|
||||
/** 查询员工请假申请列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listApproval(this.queryParams).then(response => {
|
||||
this.leaveRequestList = response.rows.map(item => {
|
||||
return {
|
||||
approvalStatus: item.approval.approvalStatus,
|
||||
applyId: item.approval.applyId,
|
||||
approvalId: item.approval.approvalId,
|
||||
approvalType: item.approval.approvalType,
|
||||
approverName: item.approval.approverName,
|
||||
...item.detail,
|
||||
}
|
||||
});
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleReset() {
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
leaveId: undefined,
|
||||
leaveTitle: undefined,
|
||||
leaveType: undefined,
|
||||
applicantName: undefined,
|
||||
applicantDeptName: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
leaveShift: undefined,
|
||||
leaveDays: undefined,
|
||||
leaveReason: undefined,
|
||||
attachmentUrls: undefined,
|
||||
createBy: undefined,
|
||||
createTime: undefined,
|
||||
updateBy: undefined,
|
||||
updateTime: undefined,
|
||||
delFlag: undefined,
|
||||
remark: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleEdit(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const leaveId = row.applyId
|
||||
getLeaveRequest(leaveId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
handleSubmit() {
|
||||
this.form.leaveTitle = `${this.form.applicantName}-${this.form.leaveType}-${this.form.startTime}-${this.form.leaveReason || ''}`
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.leaveId != null) {
|
||||
updateLeaveRequest(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.getList();
|
||||
this.reset()
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addLeaveRequest(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.getList();
|
||||
this.reset()
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleWithdraw(row) {
|
||||
this.$modal.confirm('是否确认撤回请假申请编号为"' + row.applyId + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return updateApproval({
|
||||
approvalId: row.approvalId,
|
||||
approvalStatus: '已撤销'
|
||||
});
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("撤回成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 核心新增:自动计算请假天数的方法
|
||||
calculateLeaveDays() {
|
||||
const { startTime, endTime } = this.form;
|
||||
// 两个时间都选择后才计算
|
||||
if (startTime && endTime) {
|
||||
// 转成时间戳
|
||||
const start = new Date(startTime).getTime();
|
||||
const end = new Date(endTime).getTime();
|
||||
// 判断结束时间不能小于开始时间
|
||||
if (end < start) {
|
||||
this.$modal.msgWarning('结束时间不能早于开始时间,请重新选择!');
|
||||
this.form.leaveDays = undefined;
|
||||
return;
|
||||
}
|
||||
// 计算时间差(毫秒) → 转天 → 保留2位小数
|
||||
const diffTime = end - start;
|
||||
const diffDays = (diffTime / (1000 * 60 * 60 * 24)).toFixed(2);
|
||||
// 赋值到天数输入框
|
||||
this.form.leaveDays = diffDays;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
0
klp-ui/src/views/wms/hrm/apply/meal.vue
Normal file
0
klp-ui/src/views/wms/hrm/apply/meal.vue
Normal file
0
klp-ui/src/views/wms/hrm/records/goout.vue
Normal file
0
klp-ui/src/views/wms/hrm/records/goout.vue
Normal file
@@ -20,6 +20,16 @@
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 新增:截至时间输入框 -->
|
||||
<el-form-item label="截至时间" prop="deadlineTime">
|
||||
<el-time-picker
|
||||
v-model="queryParams.deadlineTime"
|
||||
format="HH:mm:ss"
|
||||
value-format="HH:mm:ss"
|
||||
placeholder="请选择截至时间"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<DictSelect dictType="hrm_department" v-model="queryParams.deptName" placeholder="请选择部门名称"></DictSelect>
|
||||
</el-form-item>
|
||||
@@ -48,14 +58,26 @@
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- ✅ 新增:表格上方的人数合计统计组件 el-description -->
|
||||
<!-- 修改:统计组件扩展为6列,展示有效/无效的6项统计 -->
|
||||
<el-descriptions size="small" border class="mb8" :column="3">
|
||||
<el-descriptions-item label="堂食人数合计">{{ totalDineIn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="打包人数合计">{{ totalTakeout }}</el-descriptions-item>
|
||||
<el-descriptions-item label="用餐总人数合计">{{ totalAll }}</el-descriptions-item>
|
||||
<el-descriptions-item label="堂食人数">{{ validDineIn + invalidDineIn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="打包人数">{{ validTakeout + invalidTakeout }}</el-descriptions-item>
|
||||
<el-descriptions-item label="总人数">{{ validTotal + invalidTotal }}</el-descriptions-item>
|
||||
<el-descriptions-item label="有效堂食人数">{{ validDineIn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="有效打包人数">{{ validTakeout }}</el-descriptions-item>
|
||||
<el-descriptions-item label="有效总人数">{{ validTotal }}</el-descriptions-item>
|
||||
<el-descriptions-item label="无效堂食人数">{{ invalidDineIn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="无效打包人数">{{ invalidTakeout }}</el-descriptions-item>
|
||||
<el-descriptions-item label="无效总人数">{{ invalidTotal }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-table v-loading="loading" :data="mealReportList" @selection-change="handleSelectionChange">
|
||||
<!-- 修改:添加行样式判断,为无效报餐行加背景色 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="mealReportList"
|
||||
@selection-change="handleSelectionChange"
|
||||
:row-class-name="tableRowClassName"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="主键ID" align="center" prop="reportId" v-if="false"/>
|
||||
<el-table-column label="用餐日期" align="center" prop="reportDate" width="180">
|
||||
@@ -86,6 +108,13 @@
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报餐状态" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="isValidMealReport(scope.row.createTime) ? 'success' : 'danger'">
|
||||
{{ isValidMealReport(scope.row.createTime) ? '有效' : '无效' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
@@ -121,7 +150,6 @@
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<DictSelect dictType="hrm_department" v-model="form.deptName" placeholder="请选择部门名称"></DictSelect>
|
||||
</el-form-item>
|
||||
<!-- 优化:增加number类型,禁止输入非数字,限制最小值0 -->
|
||||
<el-form-item label="堂食人数" prop="dineInPeople">
|
||||
<el-input v-model="form.dineInPeople" placeholder="请输入堂食人数" type="number" min="0" />
|
||||
</el-form-item>
|
||||
@@ -156,7 +184,6 @@ export default {
|
||||
components: { DictSelect },
|
||||
data() {
|
||||
// 用餐日期默认选中今天
|
||||
// 格式化日期为yyyy-MM-dd
|
||||
function addZero(num) {
|
||||
return num < 10 ? '0' + num : num;
|
||||
}
|
||||
@@ -184,12 +211,16 @@ export default {
|
||||
deptName: undefined,
|
||||
reportUserName: undefined,
|
||||
status: undefined,
|
||||
deadlineTime: '12:00:00' // 新增:截至时间默认12点
|
||||
},
|
||||
form: {},
|
||||
// 合计统计的三个变量 ✅新增
|
||||
totalDineIn: 0, // 堂食合计
|
||||
totalTakeout: 0, // 打包合计
|
||||
totalAll: 0, // 总人数合计
|
||||
// 替换原有统计变量,新增6个有效/无效统计项
|
||||
validDineIn: 0, // 有效堂食人数
|
||||
validTakeout: 0, // 有效打包人数
|
||||
validTotal: 0, // 有效总人数
|
||||
invalidDineIn: 0, // 无效堂食人数
|
||||
invalidTakeout: 0, // 无效打包人数
|
||||
invalidTotal: 0, // 无效总人数
|
||||
// 表单校验规则
|
||||
rules: {
|
||||
reportDate: [{ required: true, message: '用餐日期不能为空', trigger: 'change' }],
|
||||
@@ -227,24 +258,61 @@ export default {
|
||||
this.mealReportList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
this.calcTableSum(); // ✅新增:获取表格数据后,立即计算合计
|
||||
this.calcTableSum(); // 重新计算统计数据
|
||||
});
|
||||
},
|
||||
// ✅ 核心新增:计算表格中堂食、打包、总人数的合计方法
|
||||
/** 核心修改:区分有效/无效统计 */
|
||||
calcTableSum(){
|
||||
let dineIn = 0;
|
||||
let takeout = 0;
|
||||
let all = 0;
|
||||
// 遍历表格数据累加,处理空值/非数字,避免NaN
|
||||
this.mealReportList.forEach(item => {
|
||||
dineIn += item.dineInPeople ? Number(item.dineInPeople) : 0;
|
||||
takeout += item.takeoutPeople ? Number(item.takeoutPeople) : 0;
|
||||
all += item.totalPeople ? Number(item.totalPeople) : 0;
|
||||
});
|
||||
// 赋值到统计变量
|
||||
this.totalDineIn = dineIn;
|
||||
this.totalTakeout = takeout;
|
||||
this.totalAll = all;
|
||||
// 初始化统计变量
|
||||
let validDine = 0, validTake = 0, validAll = 0;
|
||||
let invalidDine = 0, invalidTake = 0, invalidAll = 0;
|
||||
|
||||
this.mealReportList.forEach(item => {
|
||||
// 处理空值,转为数字
|
||||
const dine = item.dineInPeople ? Number(item.dineInPeople) : 0;
|
||||
const take = item.takeoutPeople ? Number(item.takeoutPeople) : 0;
|
||||
const total = item.totalPeople ? Number(item.totalPeople) : 0;
|
||||
|
||||
// 判断当前报餐是否有效
|
||||
if (this.isValidMealReport(item.createTime)) {
|
||||
validDine += dine;
|
||||
validTake += take;
|
||||
validAll += total;
|
||||
} else {
|
||||
invalidDine += dine;
|
||||
invalidTake += take;
|
||||
invalidAll += total;
|
||||
}
|
||||
});
|
||||
|
||||
// 赋值到统计变量
|
||||
this.validDineIn = validDine;
|
||||
this.validTakeout = validTake;
|
||||
this.validTotal = validAll;
|
||||
this.invalidDineIn = invalidDine;
|
||||
this.invalidTakeout = invalidTake;
|
||||
this.invalidTotal = invalidAll;
|
||||
},
|
||||
/** 新增:判断报餐是否有效(仅比较时分秒) */
|
||||
isValidMealReport(createTime) {
|
||||
if (!createTime || !this.queryParams.deadlineTime) return true; // 无时间默认有效
|
||||
|
||||
// 提取报餐时间的时分秒
|
||||
const reportTime = new Date(createTime);
|
||||
const reportHms = `${addZero(reportTime.getHours())}:${addZero(reportTime.getMinutes())}:${addZero(reportTime.getSeconds())}`;
|
||||
|
||||
// 比较时分秒字符串(格式HH:mm:ss,可直接字符串比较)
|
||||
return reportHms <= this.queryParams.deadlineTime;
|
||||
|
||||
// 辅助函数:补零
|
||||
function addZero(num) {
|
||||
return num < 10 ? '0' + num : num;
|
||||
}
|
||||
},
|
||||
/** 新增:表格行样式判断 */
|
||||
tableRowClassName({ row }) {
|
||||
// 无效报餐行添加样式类
|
||||
return this.isValidMealReport(row.createTime) ? '' : 'invalid-meal-row';
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
@@ -280,6 +348,8 @@ export default {
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
// 重置时恢复截至时间默认值
|
||||
this.queryParams.deadlineTime = '12:00:00';
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
@@ -366,4 +436,15 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 新增:无效报餐行样式 */
|
||||
.invalid-meal-row {
|
||||
background-color: #fff0f0 !important; /* 浅红色背景,可根据需求调整 */
|
||||
}
|
||||
/* 优化表格行hover样式 */
|
||||
::v-deep .el-table .invalid-meal-row:hover>td {
|
||||
background-color: #ffe0e0 !important;
|
||||
}
|
||||
</style>
|
||||
475
klp-ui/src/views/wms/hrm/todo/index.vue
Normal file
475
klp-ui/src/views/wms/hrm/todo/index.vue
Normal file
@@ -0,0 +1,475 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!-- 左侧筛选区域 - 自定义样式替代el-tabs -->
|
||||
<el-col :span="4">
|
||||
<div class="filter-container">
|
||||
<!-- <h4>筛选条件</h4> -->
|
||||
|
||||
<!-- 申请类型:自定义选项卡替代el-tabs -->
|
||||
<div class="custom-tabs">
|
||||
<div class="custom-tabs-header">申请类型</div>
|
||||
<div class="custom-tabs-nav">
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.applyType === undefined || queryParams.applyType === '' }"
|
||||
@click="handleTabClick('applyType', '')"
|
||||
>
|
||||
全部
|
||||
</div>
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.applyType === 'leave' }"
|
||||
@click="handleTabClick('applyType', 'leave')"
|
||||
>
|
||||
请假
|
||||
</div>
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.applyType === 'out' }"
|
||||
@click="handleTabClick('applyType', 'out')"
|
||||
>
|
||||
外出
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 审批状态:自定义选项卡替代el-tabs -->
|
||||
<div class="custom-tabs">
|
||||
<div class="custom-tabs-header">审批状态</div>
|
||||
<div class="custom-tabs-nav">
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.approveStatus === undefined || queryParams.approveStatus === '' }"
|
||||
@click="handleTabClick('approveStatus', '')"
|
||||
>
|
||||
全部
|
||||
</div>
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.approveStatus === 'pending' }"
|
||||
@click="handleTabClick('approveStatus', 'pending')"
|
||||
>
|
||||
待审批
|
||||
</div>
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.approveStatus === 'approved' }"
|
||||
@click="handleTabClick('approveStatus', 'approved')"
|
||||
>
|
||||
已审批
|
||||
</div>
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.approveStatus === 'rejected' }"
|
||||
@click="handleTabClick('approveStatus', 'rejected')"
|
||||
>
|
||||
已驳回
|
||||
</div>
|
||||
<div
|
||||
class="custom-tabs-item"
|
||||
:class="{ active: queryParams.approveStatus === 'withdrawn' }"
|
||||
@click="handleTabClick('approveStatus', 'withdrawn')"
|
||||
>
|
||||
已撤回
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 重置按钮 -->
|
||||
<!-- <el-button type="text" @click="resetQuery" style="width: 100%">重置筛选</el-button> -->
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧表格区域(修复el-table多余的total属性) -->
|
||||
<el-col :span="20">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="todoList"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<!-- 通用列 -->
|
||||
<el-table-column prop="applicantName" label="申请人" align="center" />
|
||||
<el-table-column prop="createBy" label="发起人" align="center" />
|
||||
<el-table-column prop="applyType" label="申请类型" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ getApplyTypeText(scope.row.applyType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="applicantDeptName" label="审批部门" align="center" show-overflow-tooltip/>
|
||||
<el-table-column prop="startTime" label="开始时间" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.startTime ? formatTime(scope.row.startTime) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="endTime" label="结束时间" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.endTime ? formatTime(scope.row.endTime) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="approvalStatus" label="审批状态" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="getStatusTagType(scope.row.approvalStatus)">
|
||||
{{ getStatusText(scope.row.approvalStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="240">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="small"
|
||||
icon="el-icon-view"
|
||||
@click="handleDetail(scope.row)"
|
||||
>
|
||||
详情
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.approvalStatus === '待审批'"
|
||||
size="small"
|
||||
icon="el-icon-check"
|
||||
@click="handleApprove(scope.row)"
|
||||
:loading="buttonLoading"
|
||||
>
|
||||
同意
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.approvalStatus === '待审批'"
|
||||
size="small"
|
||||
icon="el-icon-close"
|
||||
@click="handleReject(scope.row)"
|
||||
:loading="buttonLoading"
|
||||
>
|
||||
驳回
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="queryParams.pageNum"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="queryParams.pageSize"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
style="margin-top: 20px; text-align: right"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 详情弹窗(无变化) -->
|
||||
<el-dialog
|
||||
title="申请详情"
|
||||
:visible.sync="detailDialogVisible"
|
||||
width="600px"
|
||||
destroy-on-close
|
||||
>
|
||||
<div v-if="currentDetail.applyType === 'leave'" class="detail-content">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="请假标题">{{ currentDetail.leaveTitle || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="请假类型">{{ currentDetail.leaveType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请人">{{ currentDetail.applicantName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请部门">{{ currentDetail.applicantDeptName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="请假开始时间">{{ formatTime(currentDetail.startTime) || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="请假结束时间">{{ formatTime(currentDetail.endTime) || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="请假班次">{{ currentDetail.leaveShift || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="请假天数">{{ currentDetail.leaveDays || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="请假原因">{{ currentDetail.leaveReason || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{ currentDetail.remark || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="currentDetail.applyType === 'out'" class="detail-content">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="外出类型">{{ currentDetail.outType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请人">{{ currentDetail.applicantName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请部门">{{ currentDetail.applicantDeptName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="外出开始时间">{{ formatTime(currentDetail.startTime) || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="外出结束时间">{{ formatTime(currentDetail.endTime) || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="外出时长(小时)">{{ currentDetail.outHours || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="外出地点">{{ currentDetail.outPlace || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="外出原因">{{ currentDetail.outReason || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{ currentDetail.remark || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<template v-slot:footer>
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listApproval, updateApproval } from '@/api/wms/approval'
|
||||
|
||||
export default {
|
||||
name: 'TodoList',
|
||||
data() {
|
||||
return {
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
approveStatus: '', // 审批状态:pending(待审批)、approved(已审批)、rejected(已驳回)、withdrawn(已撤回)
|
||||
applyType: '', // 申请类型:leave(请假)、out(外出),空为全部
|
||||
},
|
||||
// 列表数据
|
||||
todoList: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
buttonLoading: false,
|
||||
// 详情弹窗相关
|
||||
detailDialogVisible: false,
|
||||
currentDetail: {},
|
||||
}
|
||||
},
|
||||
// 新增:从Vuex获取nickName
|
||||
computed: {
|
||||
nickName() {
|
||||
return this.$store.getters.nickName
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 页面加载时查询列表
|
||||
this.getTodoList()
|
||||
},
|
||||
methods: {
|
||||
// 查询待办列表 - 核心修改:新增approveName参数
|
||||
getTodoList() {
|
||||
this.loading = true
|
||||
// 拼接请求参数,新增approveName
|
||||
const requestParams = {
|
||||
...this.queryParams,
|
||||
approveName: this.nickName
|
||||
}
|
||||
listApproval(requestParams)
|
||||
.then((res) => {
|
||||
this.todoList = res.rows.map((item) => {
|
||||
return {
|
||||
approvalStatus: item.approval.approvalStatus,
|
||||
applyId: item.approval.applyId,
|
||||
approvalId: item.approval.approvalId,
|
||||
applyType: item.approval.applyType,
|
||||
approverName: item.approval.approverName,
|
||||
...item.detail, // 合并请假/外出的详情字段
|
||||
}
|
||||
})
|
||||
this.total = res.total
|
||||
this.loading = false
|
||||
})
|
||||
.catch((err) => {
|
||||
this.loading = false
|
||||
this.$message.error('查询待办列表失败:' + err.message)
|
||||
})
|
||||
},
|
||||
|
||||
// 自定义tab点击事件(替代原el-tabs的tab-click)
|
||||
handleTabClick(field, value) {
|
||||
this.queryParams[field] = value
|
||||
this.handleQuery()
|
||||
},
|
||||
|
||||
// 处理筛选查询
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1 // 筛选时重置页码
|
||||
this.getTodoList()
|
||||
},
|
||||
|
||||
// 重置筛选条件
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
approveStatus: '',
|
||||
applyType: '',
|
||||
}
|
||||
this.getTodoList()
|
||||
},
|
||||
|
||||
// 分页-每页条数变更
|
||||
handleSizeChange(val) {
|
||||
this.queryParams.pageSize = val
|
||||
this.getTodoList()
|
||||
},
|
||||
|
||||
// 分页-当前页变更
|
||||
handleCurrentChange(val) {
|
||||
this.queryParams.pageNum = val
|
||||
this.getTodoList()
|
||||
},
|
||||
|
||||
// 查看详情
|
||||
handleDetail(row) {
|
||||
this.currentDetail = { ...row } // 深拷贝避免原数据被修改
|
||||
this.detailDialogVisible = true
|
||||
},
|
||||
|
||||
// 审批通过
|
||||
handleApprove(row) {
|
||||
this.$confirm('确定要审批通过该申请吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
this.buttonLoading = true
|
||||
try {
|
||||
// 这里替换为你的审批接口调用
|
||||
await updateApproval({
|
||||
approvalId: row.approvalId,
|
||||
approvalStatus: '已同意',
|
||||
})
|
||||
this.$message.success('审批通过成功!')
|
||||
this.getTodoList() // 重新查询列表
|
||||
} catch (err) {
|
||||
this.$message.error('审批通过失败:' + err.message)
|
||||
} finally {
|
||||
this.buttonLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 驳回申请
|
||||
handleReject(row) {
|
||||
this.$confirm('确定要驳回该申请吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
required: true,
|
||||
}).then(async ({ value }) => {
|
||||
this.buttonLoading = true
|
||||
try {
|
||||
// 这里替换为你的驳回接口调用
|
||||
await updateApproval({
|
||||
approvalId: row.approvalId,
|
||||
approvalStatus: '已驳回'
|
||||
})
|
||||
this.$message.success('驳回成功!')
|
||||
this.getTodoList() // 重新查询列表
|
||||
} catch (err) {
|
||||
this.$message.error('驳回失败:' + err.message)
|
||||
} finally {
|
||||
this.buttonLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 格式化时间(如果项目没有内置工具,可使用此方法)
|
||||
formatTime(time) {
|
||||
if (!time) return '-'
|
||||
return this.parseTime(time, '{y}-{m}-{d} {h}')
|
||||
},
|
||||
|
||||
// 获取审批状态对应的标签类型
|
||||
getStatusTagType(status) {
|
||||
const typeMap = {
|
||||
'待审批': 'warning',
|
||||
'已同意': 'success',
|
||||
'已驳回': 'danger',
|
||||
'已撤消': 'info',
|
||||
}
|
||||
return typeMap[status] || 'default'
|
||||
},
|
||||
|
||||
// 获取审批状态的中文文本
|
||||
getStatusText(status) {
|
||||
const textMap = {
|
||||
'待审批': '待审批',
|
||||
'已同意': '已同意',
|
||||
'已驳回': '已驳回',
|
||||
'已撤消': '已撤消',
|
||||
}
|
||||
return textMap[status] || '未知状态'
|
||||
},
|
||||
|
||||
getApplyTypeText(type) {
|
||||
const textMap = {
|
||||
'leave': '请假',
|
||||
'out': '外出',
|
||||
}
|
||||
return textMap[type] || '未知类型'
|
||||
},
|
||||
|
||||
// 表格多选事件(可选,根据需求使用)
|
||||
handleSelectionChange(val) {
|
||||
// 可用于批量操作
|
||||
console.log('选中的数据:', val)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
background: #f5f7fa;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.filter-container h4 {
|
||||
margin: 0 0 20px 0;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 自定义tabs样式 */
|
||||
.custom-tabs {
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.custom-tabs-header {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.custom-tabs-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.custom-tabs-item {
|
||||
padding: 10px 15px;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.custom-tabs-item:hover {
|
||||
background: #ecf5ff;
|
||||
border-color: #c6e2ff;
|
||||
}
|
||||
|
||||
.custom-tabs-item.active {
|
||||
background: #409eff;
|
||||
color: #ffffff;
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.el-descriptions {
|
||||
--el-descriptions-item-label-color: #606266;
|
||||
--el-descriptions-item-content-color: #303133;
|
||||
}
|
||||
</style>
|
||||
@@ -47,10 +47,10 @@ module.exports = {
|
||||
},
|
||||
// 直接代理Zinc1相关路径
|
||||
'/zinc-api': {
|
||||
target: `http://140.143.206.120:18082/prod-api`,
|
||||
target: `http://140.143.206.120:18081`,
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
['^' + process.env.VUE_APP_BASE_API]: ''
|
||||
['^' + '/zinc-api']: '/api'
|
||||
}
|
||||
},
|
||||
// 直接代理WebSocket相关路径
|
||||
|
||||
Reference in New Issue
Block a user