pull/781/head
quu 2025-05-22 21:10:00 +09:00
parent ed09002861
commit f4eac55974
29 changed files with 4000 additions and 0 deletions

View File

@ -0,0 +1,47 @@
import request from '@/config/axios'
// 考勤记录 VO
export interface AttendRecordVO {
id: number // 主键ID
userId: number // 员工ID
deptId: number // 部门ID
postId: number // 岗位ID
clockStatus: string // 打卡状态(正常、迟到、早退、缺卡等)
clockType: string // 打卡类型(正常上下班、加班)
clockInTime: Date // 打卡开始时间(上班打卡)
clockOutTime: Date // 打卡结束时间(下班打卡)
attendanceDuration: number // 日出勤时长(小时)
}
// 考勤记录 API
export const AttendRecordApi = {
// 查询考勤记录分页
getAttendRecordPage: async (params: any) => {
return await request.get({ url: `/hrm/attend-record/page`, params })
},
// 查询考勤记录详情
getAttendRecord: async (id: number) => {
return await request.get({ url: `/hrm/attend-record/get?id=` + id })
},
// 新增考勤记录
createAttendRecord: async (data: AttendRecordVO) => {
return await request.post({ url: `/hrm/attend-record/create`, data })
},
// 修改考勤记录
updateAttendRecord: async (data: AttendRecordVO) => {
return await request.put({ url: `/hrm/attend-record/update`, data })
},
// 删除考勤记录
deleteAttendRecord: async (id: number) => {
return await request.delete({ url: `/hrm/attend-record/delete?id=` + id })
},
// 导出考勤记录 Excel
exportAttendRecord: async (params) => {
return await request.download({ url: `/hrm/attend-record/export-excel`, params })
}
}

View File

@ -0,0 +1,58 @@
import request from '@/config/axios'
// 考勤规则 VO
export interface AttendRuleVO {
id: number // 主键
name: string // 规则名称
isOvertimeAllowed: boolean // 是否允许加班
overtimeStartAfter: number // 下班多少分钟后算加班
restDayMode: number // 休息日打卡规则1交替一次 2交替多次
holidayPunchRequired: boolean // 法定假日是否需要打卡
}
// 考勤规则 API
export const AttendRuleApi = {
// 查询考勤规则分页
getAttendRulePage: async (params: any) => {
return await request.get({ url: `/hrm/attend-rule/page`, params })
},
// 查询考勤规则详情
getAttendRule: async (id: number) => {
return await request.get({ url: `/hrm/attend-rule/get?id=` + id })
},
// 新增考勤规则
createAttendRule: async (data: AttendRuleVO) => {
return await request.post({ url: `/hrm/attend-rule/create`, data })
},
// 修改考勤规则
updateAttendRule: async (data: AttendRuleVO) => {
return await request.put({ url: `/hrm/attend-rule/update`, data })
},
// 删除考勤规则
deleteAttendRule: async (id: number) => {
return await request.delete({ url: `/hrm/attend-rule/delete?id=` + id })
},
// 导出考勤规则 Excel
exportAttendRule: async (params) => {
return await request.download({ url: `/hrm/attend-rule/export-excel`, params })
},
// ==================== 子表(考勤班次) ====================
// 获得考勤班次列表
getAttendShiftListByRuleId: async (ruleId) => {
return await request.get({ url: `/hrm/attend-rule/attend-shift/list-by-rule-id?ruleId=` + ruleId })
},
// ==================== 子表(考勤关系) ====================
// 获得考勤关系列表
getUserAttendRelationListByRuleId: async (ruleId) => {
return await request.get({ url: `/hrm/attend-rule/user-attend-relation/list-by-rule-id?ruleId=` + ruleId })
}
}

View File

@ -0,0 +1,45 @@
import request from '@/config/axios'
// 考勤排班调度配置 VO
export interface AttendScheduleConfigVO {
id: number // 主键ID
ruleId: number // 所属考勤规则ID
scheduleType: number // 调度类型1=按天2=按周3=按月
dayIndex: number // 调度下标:日(从1开始),周(1~7),月(1~12)
shiftId: number // 班次ID为空表示休息
isWorkingDay: boolean // 是否工作日true 表示需打卡)
remarks: string // 备注说明
}
// 考勤排班调度配置 API
export const AttendScheduleConfigApi = {
// 查询考勤排班调度配置分页
getAttendScheduleConfigPage: async (params: any) => {
return await request.get({ url: `/hrm/attend-schedule-config/page`, params })
},
// 查询考勤排班调度配置详情
getAttendScheduleConfig: async (id: number) => {
return await request.get({ url: `/hrm/attend-schedule-config/get?id=` + id })
},
// 新增考勤排班调度配置
createAttendScheduleConfig: async (data: AttendScheduleConfigVO) => {
return await request.post({ url: `/hrm/attend-schedule-config/create`, data })
},
// 修改考勤排班调度配置
updateAttendScheduleConfig: async (data: AttendScheduleConfigVO) => {
return await request.put({ url: `/hrm/attend-schedule-config/update`, data })
},
// 删除考勤排班调度配置
deleteAttendScheduleConfig: async (id: number) => {
return await request.delete({ url: `/hrm/attend-schedule-config/delete?id=` + id })
},
// 导出考勤排班调度配置 Excel
exportAttendScheduleConfig: async (params) => {
return await request.download({ url: `/hrm/attend-schedule-config/export-excel`, params })
}
}

View File

@ -0,0 +1,43 @@
import request from '@/config/axios'
// 考勤班次 VO
export interface AttendShiftVO {
id: number // 主键
ruleId: number // 所属考勤规则
name: string // 班次名称
shiftType: number // 班次类型1固定班次 2轮班制三班倒
restIncluded: boolean // 是否包含休息时段
}
// 考勤班次 API
export const AttendShiftApi = {
// 查询考勤班次分页
getAttendShiftPage: async (params: any) => {
return await request.get({ url: `/hrm/attend-shift/page`, params })
},
// 查询考勤班次详情
getAttendShift: async (id: number) => {
return await request.get({ url: `/hrm/attend-shift/get?id=` + id })
},
// 新增考勤班次
createAttendShift: async (data: AttendShiftVO) => {
return await request.post({ url: `/hrm/attend-shift/create`, data })
},
// 修改考勤班次
updateAttendShift: async (data: AttendShiftVO) => {
return await request.put({ url: `/hrm/attend-shift/update`, data })
},
// 删除考勤班次
deleteAttendShift: async (id: number) => {
return await request.delete({ url: `/hrm/attend-shift/delete?id=` + id })
},
// 导出考勤班次 Excel
exportAttendShift: async (params) => {
return await request.download({ url: `/hrm/attend-shift/export-excel`, params })
}
}

View File

@ -0,0 +1,45 @@
import request from '@/config/axios'
// 考勤班次时间 VO
export interface AttendShiftTimeVO {
id: number // 主键
shiftId: number // 关联班次ID
startTime: localtime // 上班时间
endTime: localtime // 下班时间
restStartTime: localtime // 休息开始时间
restEndTime: localtime // 休息结束时间
seq: number // 时段顺序(如早班、中班、晚班)
}
// 考勤班次时间 API
export const AttendShiftTimeApi = {
// 查询考勤班次时间分页
getAttendShiftTimePage: async (params: any) => {
return await request.get({ url: `/hrm/attend-shift-time/page`, params })
},
// 查询考勤班次时间详情
getAttendShiftTime: async (id: number) => {
return await request.get({ url: `/hrm/attend-shift-time/get?id=` + id })
},
// 新增考勤班次时间
createAttendShiftTime: async (data: AttendShiftTimeVO) => {
return await request.post({ url: `/hrm/attend-shift-time/create`, data })
},
// 修改考勤班次时间
updateAttendShiftTime: async (data: AttendShiftTimeVO) => {
return await request.put({ url: `/hrm/attend-shift-time/update`, data })
},
// 删除考勤班次时间
deleteAttendShiftTime: async (id: number) => {
return await request.delete({ url: `/hrm/attend-shift-time/delete?id=` + id })
},
// 导出考勤班次时间 Excel
exportAttendShiftTime: async (params) => {
return await request.download({ url: `/hrm/attend-shift-time/export-excel`, params })
}
}

View File

@ -0,0 +1,46 @@
import request from '@/config/axios'
// 员工绩效 VO
export interface UserPerformanceVO {
id: number // 唯一主键
userId: number // 员工档案ID关联 hrm_user_infor
assessmentMonth: Date // 考核月份格式YYYY-MM
performanceLevel: number // 绩效等级
assessmentScoreTotal: number // 考核得分合计
attendanceScore: number // 考勤得分
performanceAssessmentScore: number // 业绩考核得分
behaviorAssessmentScore: number // 行为考核得分
}
// 员工绩效 API
export const UserPerformanceApi = {
// 查询员工绩效分页
getUserPerformancePage: async (params: any) => {
return await request.get({ url: `/hrm/user-performance/page`, params })
},
// 查询员工绩效详情
getUserPerformance: async (id: number) => {
return await request.get({ url: `/hrm/user-performance/get?id=` + id })
},
// 新增员工绩效
createUserPerformance: async (data: UserPerformanceVO) => {
return await request.post({ url: `/hrm/user-performance/create`, data })
},
// 修改员工绩效
updateUserPerformance: async (data: UserPerformanceVO) => {
return await request.put({ url: `/hrm/user-performance/update`, data })
},
// 删除员工绩效
deleteUserPerformance: async (id: number) => {
return await request.delete({ url: `/hrm/user-performance/delete?id=` + id })
},
// 导出员工绩效 Excel
exportUserPerformance: async (params) => {
return await request.download({ url: `/hrm/user-performance/export-excel`, params })
}
}

View File

@ -0,0 +1,44 @@
import request from '@/config/axios'
// 职位考核信息 VO
export interface PostAssessmentVO {
id: number // 主键
postId: number // 岗位关联ID
assessType: string // 考核类型
assessName: string // 考核名称
assessDetail: string // 考核详情
score: number // 分数分值
}
// 职位考核信息 API
export const PostAssessmentApi = {
// 查询职位考核信息分页
getPostAssessmentPage: async (params: any) => {
return await request.get({ url: `/system/post-assessment/page`, params })
},
// 查询职位考核信息详情
getPostAssessment: async (id: number) => {
return await request.get({ url: `/system/post-assessment/get?id=` + id })
},
// 新增职位考核信息
createPostAssessment: async (data: PostAssessmentVO) => {
return await request.post({ url: `/system/post-assessment/create`, data })
},
// 修改职位考核信息
updatePostAssessment: async (data: PostAssessmentVO) => {
return await request.put({ url: `/system/post-assessment/update`, data })
},
// 删除职位考核信息
deletePostAssessment: async (id: number) => {
return await request.delete({ url: `/system/post-assessment/delete?id=` + id })
},
// 导出职位考核信息 Excel
exportPostAssessment: async (params) => {
return await request.download({ url: `/system/post-assessment/export-excel`, params })
}
}

View File

@ -0,0 +1,42 @@
import request from '@/config/axios'
// 任职条件 VO
export interface PostRequirementVO {
id: number // 唯一主键
postId: number // 岗位关联ID
requirementName: string // 名称
qualificationDescription: string // 资格说明
}
// 任职条件 API
export const PostRequirementApi = {
// 查询任职条件分页
getPostRequirementPage: async (params: any) => {
return await request.get({ url: `/system/post-requirement/page`, params })
},
// 查询任职条件详情
getPostRequirement: async (id: number) => {
return await request.get({ url: `/system/post-requirement/get?id=` + id })
},
// 新增任职条件
createPostRequirement: async (data: PostRequirementVO) => {
return await request.post({ url: `/system/post-requirement/create`, data })
},
// 修改任职条件
updatePostRequirement: async (data: PostRequirementVO) => {
return await request.put({ url: `/system/post-requirement/update`, data })
},
// 删除任职条件
deletePostRequirement: async (id: number) => {
return await request.delete({ url: `/system/post-requirement/delete?id=` + id })
},
// 导出任职条件 Excel
exportPostRequirement: async (params) => {
return await request.download({ url: `/system/post-requirement/export-excel`, params })
}
}

View File

@ -0,0 +1,43 @@
import request from '@/config/axios'
// 岗位职责 VO
export interface PostResponsibilityVO {
id: number // 唯一主键
postId: number // 岗位关联ID
responsibility: string // 职责
task: string // 任务
timeAllocation: string // 时间分配
}
// 岗位职责 API
export const PostResponsibilityApi = {
// 查询岗位职责分页
getPostResponsibilityPage: async (params: any) => {
return await request.get({ url: `/system/post-responsibility/page`, params })
},
// 查询岗位职责详情
getPostResponsibility: async (id: number) => {
return await request.get({ url: `/system/post-responsibility/get?id=` + id })
},
// 新增岗位职责
createPostResponsibility: async (data: PostResponsibilityVO) => {
return await request.post({ url: `/system/post-responsibility/create`, data })
},
// 修改岗位职责
updatePostResponsibility: async (data: PostResponsibilityVO) => {
return await request.put({ url: `/system/post-responsibility/update`, data })
},
// 删除岗位职责
deletePostResponsibility: async (id: number) => {
return await request.delete({ url: `/system/post-responsibility/delete?id=` + id })
},
// 导出岗位职责 Excel
exportPostResponsibility: async (params) => {
return await request.download({ url: `/system/post-responsibility/export-excel`, params })
}
}

View File

@ -0,0 +1,154 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="员工ID" prop="userId">
<el-input v-model="formData.userId" placeholder="请输入员工ID" />
</el-form-item>
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="formData.deptId" placeholder="请输入部门ID" />
</el-form-item>
<el-form-item label="岗位ID" prop="postId">
<el-input v-model="formData.postId" placeholder="请输入岗位ID" />
</el-form-item>
<el-form-item label="打卡状态(正常、迟到、早退、缺卡等)" prop="clockStatus">
<el-select v-model="formData.clockStatus" placeholder="请选择打卡状态(正常、迟到、早退、缺卡等)">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HRM_ CLOCK_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="打卡类型(正常上下班、加班)" prop="clockType">
<el-select v-model="formData.clockType" placeholder="请选择打卡类型(正常上下班、加班)">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HRM_CLOCK_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="打卡开始时间(上班打卡)" prop="clockInTime">
<el-date-picker
v-model="formData.clockInTime"
type="date"
value-format="x"
placeholder="选择打卡开始时间(上班打卡)"
/>
</el-form-item>
<el-form-item label="打卡结束时间(下班打卡)" prop="clockOutTime">
<el-date-picker
v-model="formData.clockOutTime"
type="date"
value-format="x"
placeholder="选择打卡结束时间(下班打卡)"
/>
</el-form-item>
<el-form-item label="日出勤时长(小时)" prop="attendanceDuration">
<el-input v-model="formData.attendanceDuration" placeholder="请输入日出勤时长(小时)" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { AttendRecordApi, AttendRecordVO } from '@/api/hrm/attendrecord'
/** 考勤记录 表单 */
defineOptions({ name: 'AttendRecordForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
userId: undefined,
deptId: undefined,
postId: undefined,
clockStatus: undefined,
clockType: undefined,
clockInTime: undefined,
clockOutTime: undefined,
attendanceDuration: undefined
})
const formRules = reactive({
userId: [{ required: true, message: '员工ID不能为空', trigger: 'blur' }],
clockStatus: [{ required: true, message: '打卡状态(正常、迟到、早退、缺卡等)不能为空', trigger: 'change' }],
clockType: [{ required: true, message: '打卡类型(正常上下班、加班)不能为空', trigger: 'change' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await AttendRecordApi.getAttendRecord(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as AttendRecordVO
if (formType.value === 'create') {
await AttendRecordApi.createAttendRecord(data)
message.success(t('common.createSuccess'))
} else {
await AttendRecordApi.updateAttendRecord(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
userId: undefined,
deptId: undefined,
postId: undefined,
clockStatus: undefined,
clockType: undefined,
clockInTime: undefined,
clockOutTime: undefined,
attendanceDuration: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,301 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="员工ID" prop="userId">
<el-input
v-model="queryParams.userId"
placeholder="请输入员工ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="部门ID" prop="deptId">
<el-input
v-model="queryParams.deptId"
placeholder="请输入部门ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="岗位ID" prop="postId">
<el-input
v-model="queryParams.postId"
placeholder="请输入岗位ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="打卡状态(正常、迟到、早退、缺卡等)" prop="clockStatus">
<el-select
v-model="queryParams.clockStatus"
placeholder="请选择打卡状态(正常、迟到、早退、缺卡等)"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HRM_ CLOCK_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="打卡类型(正常上下班、加班)" prop="clockType">
<el-select
v-model="queryParams.clockType"
placeholder="请选择打卡类型(正常上下班、加班)"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HRM_CLOCK_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="打卡开始时间(上班打卡)" prop="clockInTime">
<el-date-picker
v-model="queryParams.clockInTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="打卡结束时间(下班打卡)" prop="clockOutTime">
<el-date-picker
v-model="queryParams.clockOutTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="日出勤时长(小时)" prop="attendanceDuration">
<el-input
v-model="queryParams.attendanceDuration"
placeholder="请输入日出勤时长(小时)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['hrm:attend-record:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['hrm:attend-record:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键ID" align="center" prop="id" />
<el-table-column label="员工ID" align="center" prop="userId" />
<el-table-column label="部门ID" align="center" prop="deptId" />
<el-table-column label="岗位ID" align="center" prop="postId" />
<el-table-column label="打卡状态(正常、迟到、早退、缺卡等)" align="center" prop="clockStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HRM_ CLOCK_STATUS" :value="scope.row.clockStatus" />
</template>
</el-table-column>
<el-table-column label="打卡类型(正常上下班、加班)" align="center" prop="clockType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HRM_CLOCK_TYPE" :value="scope.row.clockType" />
</template>
</el-table-column>
<el-table-column
label="打卡开始时间(上班打卡)"
align="center"
prop="clockInTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="打卡结束时间(下班打卡)"
align="center"
prop="clockOutTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="日出勤时长(小时)" align="center" prop="attendanceDuration" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['hrm:attend-record:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['hrm:attend-record:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<AttendRecordForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { AttendRecordApi, AttendRecordVO } from '@/api/hrm/attendrecord'
import AttendRecordForm from './AttendRecordForm.vue'
/** 考勤记录 列表 */
defineOptions({ name: 'AttendRecord' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<AttendRecordVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
userId: undefined,
deptId: undefined,
postId: undefined,
clockStatus: undefined,
clockType: undefined,
clockInTime: [],
clockOutTime: [],
attendanceDuration: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await AttendRecordApi.getAttendRecordPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await AttendRecordApi.deleteAttendRecord(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await AttendRecordApi.exportAttendRecord(queryParams)
download.excel(data, '考勤记录.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,168 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="规则名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入规则名称" />
</el-form-item>
<el-form-item label="是否允许加班" prop="isOvertimeAllowed">
<el-radio-group v-model="formData.isOvertimeAllowed">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="下班多少分钟后算加班" prop="overtimeStartAfter">
<el-input v-model="formData.overtimeStartAfter" placeholder="请输入下班多少分钟后算加班" />
</el-form-item>
<el-form-item label="休息日打卡规则1交替一次 2交替多次" prop="restDayMode">
<el-select v-model="formData.restDayMode" placeholder="请选择休息日打卡规则1交替一次 2交替多次">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_REST_DAY_MODE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="法定假日是否需要打卡" prop="holidayPunchRequired">
<el-radio-group v-model="formData.holidayPunchRequired">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="考勤班次" name="attendShift">
<AttendShiftForm ref="attendShiftFormRef" :rule-id="formData.id" />
</el-tab-pane>
<el-tab-pane label="考勤关系" name="userAttendRelation">
<UserAttendRelationForm ref="userAttendRelationFormRef" :rule-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { AttendRuleApi, AttendRuleVO } from '@/api/hrm/attendrule'
import AttendShiftForm from './components/AttendShiftForm.vue'
import UserAttendRelationForm from './components/UserAttendRelationForm.vue'
/** 考勤规则 表单 */
defineOptions({ name: 'AttendRuleForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
isOvertimeAllowed: undefined,
overtimeStartAfter: undefined,
restDayMode: undefined,
holidayPunchRequired: undefined
})
const formRules = reactive({
name: [{ required: true, message: '规则名称不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 子表的表单 */
const subTabsName = ref('attendShift')
const attendShiftFormRef = ref()
const userAttendRelationFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await AttendRuleApi.getAttendRule(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
try {
await attendShiftFormRef.value.validate()
} catch (e) {
subTabsName.value = 'attendShift'
return
}
try {
await userAttendRelationFormRef.value.validate()
} catch (e) {
subTabsName.value = 'userAttendRelation'
return
}
//
formLoading.value = true
try {
const data = formData.value as unknown as AttendRuleVO
//
data.attendShifts = attendShiftFormRef.value.getData()
data.userAttendRelations = userAttendRelationFormRef.value.getData()
if (formType.value === 'create') {
await AttendRuleApi.createAttendRule(data)
message.success(t('common.createSuccess'))
} else {
await AttendRuleApi.updateAttendRule(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
isOvertimeAllowed: undefined,
overtimeStartAfter: undefined,
restDayMode: undefined,
holidayPunchRequired: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,123 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="班次名称" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
<el-input v-model="row.name" placeholder="请输入班次名称" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="班次类型1固定班次 2轮班制三班倒" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.shiftType`" :rules="formRules.shiftType" class="mb-0px!">
<el-select v-model="row.shiftType" placeholder="请选择班次类型1固定班次 2轮班制三班倒">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_SHIFT_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="是否包含休息时段" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.restIncluded`" :rules="formRules.restIncluded" class="mb-0px!">
<el-radio-group v-model="row.restIncluded">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加考勤班次</el-button>
</el-row>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { AttendRuleApi } from '@/api/hrm/attendrule'
const props = defineProps<{
ruleId: undefined //
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
ruleId: [{ required: true, message: '所属考勤规则不能为空', trigger: 'blur' }],
name: [{ required: true, message: '班次名称不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.ruleId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await AttendRuleApi.getAttendShiftListByRuleId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
ruleId: undefined,
name: undefined,
shiftType: undefined,
restIncluded: undefined
}
row.ruleId = props.ruleId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,123 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="员工ID" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.userId`" :rules="formRules.userId" class="mb-0px!">
<el-input v-model="row.userId" placeholder="请输入员工ID" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="部门ID" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.deptId`" :rules="formRules.deptId" class="mb-0px!">
<el-input v-model="row.deptId" placeholder="请输入部门ID" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="岗位ID" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.postId`" :rules="formRules.postId" class="mb-0px!">
<el-input v-model="row.postId" placeholder="请输入岗位ID" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="绑定类型1员工 2部门 3岗位" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.bindType`" :rules="formRules.bindType" class="mb-0px!">
<el-select v-model="row.bindType" placeholder="请选择绑定类型1员工 2部门 3岗位">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_BIND_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加考勤关系</el-button>
</el-row>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { AttendRuleApi } from '@/api/hrm/attendrule'
const props = defineProps<{
ruleId: undefined //
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
ruleId: [{ required: true, message: '绑定的规则不能为空', trigger: 'blur' }],
bindType: [{ required: true, message: '绑定类型1员工 2部门 3岗位不能为空', trigger: 'change' }]
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.ruleId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await AttendRuleApi.getUserAttendRelationListByRuleId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
ruleId: undefined,
userId: undefined,
deptId: undefined,
postId: undefined,
bindType: undefined
}
row.ruleId = props.ruleId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,262 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="规则名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入规则名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否允许加班" prop="isOvertimeAllowed">
<el-select
v-model="queryParams.isOvertimeAllowed"
placeholder="请选择是否允许加班"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="下班多少分钟后算加班" prop="overtimeStartAfter">
<el-input
v-model="queryParams.overtimeStartAfter"
placeholder="请输入下班多少分钟后算加班"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="休息日打卡规则1交替一次 2交替多次" prop="restDayMode">
<el-select
v-model="queryParams.restDayMode"
placeholder="请选择休息日打卡规则1交替一次 2交替多次"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_REST_DAY_MODE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="法定假日是否需要打卡" prop="holidayPunchRequired">
<el-select
v-model="queryParams.holidayPunchRequired"
placeholder="请选择法定假日是否需要打卡"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['hrm:attend-rule:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['hrm:attend-rule:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="规则名称" align="center" prop="name" />
<el-table-column label="是否允许加班" align="center" prop="isOvertimeAllowed">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isOvertimeAllowed" />
</template>
</el-table-column>
<el-table-column label="下班多少分钟后算加班" align="center" prop="overtimeStartAfter" />
<el-table-column label="休息日打卡规则1交替一次 2交替多次" align="center" prop="restDayMode">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HRM_REST_DAY_MODE" :value="scope.row.restDayMode" />
</template>
</el-table-column>
<el-table-column label="法定假日是否需要打卡" align="center" prop="holidayPunchRequired">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.holidayPunchRequired" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['hrm:attend-rule:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['hrm:attend-rule:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<AttendRuleForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { AttendRuleApi, AttendRuleVO } from '@/api/hrm/attendrule'
import AttendRuleForm from './AttendRuleForm.vue'
/** 考勤规则 列表 */
defineOptions({ name: 'AttendRule' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<AttendRuleVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: undefined,
isOvertimeAllowed: undefined,
overtimeStartAfter: undefined,
restDayMode: undefined,
holidayPunchRequired: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await AttendRuleApi.getAttendRulePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await AttendRuleApi.deleteAttendRule(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await AttendRuleApi.exportAttendRule(queryParams)
download.excel(data, '考勤规则.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,124 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="所属考勤规则ID" prop="ruleId">
<el-input v-model="formData.ruleId" placeholder="请输入所属考勤规则ID" />
</el-form-item>
<el-form-item label="调度类型1=按天2=按周3=按月" prop="scheduleType">
<el-select v-model="formData.scheduleType" placeholder="请选择调度类型1=按天2=按周3=按月">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="调度下标:日(从1开始),周(1~7),月(1~12)" prop="dayIndex">
<el-input v-model="formData.dayIndex" placeholder="请输入调度下标:日(从1开始),周(1~7),月(1~12)" />
</el-form-item>
<el-form-item label="班次ID为空表示休息" prop="shiftId">
<el-input v-model="formData.shiftId" placeholder="请输入班次ID为空表示休息" />
</el-form-item>
<el-form-item label="是否工作日true 表示需打卡)" prop="isWorkingDay">
<el-radio-group v-model="formData.isWorkingDay">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注说明" prop="remarks">
<el-input v-model="formData.remarks" placeholder="请输入备注说明" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { AttendScheduleConfigApi, AttendScheduleConfigVO } from '@/api/hrm/attendscheduleconfig'
/** 考勤排班调度配置 表单 */
defineOptions({ name: 'AttendScheduleConfigForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
ruleId: undefined,
scheduleType: undefined,
dayIndex: undefined,
shiftId: undefined,
isWorkingDay: undefined,
remarks: undefined
})
const formRules = reactive({
ruleId: [{ required: true, message: '所属考勤规则ID不能为空', trigger: 'blur' }],
scheduleType: [{ required: true, message: '调度类型1=按天2=按周3=按月不能为空', trigger: 'change' }],
dayIndex: [{ required: true, message: '调度下标:日(从1开始),周(1~7),月(1~12)不能为空', trigger: 'blur' }],
isWorkingDay: [{ required: true, message: '是否工作日true 表示需打卡)不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await AttendScheduleConfigApi.getAttendScheduleConfig(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as AttendScheduleConfigVO
if (formType.value === 'create') {
await AttendScheduleConfigApi.createAttendScheduleConfig(data)
message.success(t('common.createSuccess'))
} else {
await AttendScheduleConfigApi.updateAttendScheduleConfig(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
ruleId: undefined,
scheduleType: undefined,
dayIndex: undefined,
shiftId: undefined,
isWorkingDay: undefined,
remarks: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,244 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="所属考勤规则ID" prop="ruleId">
<el-input
v-model="queryParams.ruleId"
placeholder="请输入所属考勤规则ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="调度类型1=按天2=按周3=按月" prop="scheduleType">
<el-select
v-model="queryParams.scheduleType"
placeholder="请选择调度类型1=按天2=按周3=按月"
clearable
class="!w-240px"
>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="调度下标:日(从1开始),周(1~7),月(1~12)" prop="dayIndex">
<el-input
v-model="queryParams.dayIndex"
placeholder="请输入调度下标:日(从1开始),周(1~7),月(1~12)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="班次ID为空表示休息" prop="shiftId">
<el-input
v-model="queryParams.shiftId"
placeholder="请输入班次ID为空表示休息"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否工作日true 表示需打卡)" prop="isWorkingDay">
<el-select
v-model="queryParams.isWorkingDay"
placeholder="请选择是否工作日true 表示需打卡)"
clearable
class="!w-240px"
>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="备注说明" prop="remarks">
<el-input
v-model="queryParams.remarks"
placeholder="请输入备注说明"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['hrm:attend-schedule-config:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['hrm:attend-schedule-config:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键ID" align="center" prop="id" />
<el-table-column label="所属考勤规则ID" align="center" prop="ruleId" />
<el-table-column label="调度类型1=按天2=按周3=按月" align="center" prop="scheduleType" />
<el-table-column label="调度下标:日(从1开始),周(1~7),月(1~12)" align="center" prop="dayIndex" />
<el-table-column label="班次ID为空表示休息" align="center" prop="shiftId" />
<el-table-column label="是否工作日true 表示需打卡)" align="center" prop="isWorkingDay" />
<el-table-column label="备注说明" align="center" prop="remarks" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['hrm:attend-schedule-config:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['hrm:attend-schedule-config:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<AttendScheduleConfigForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { AttendScheduleConfigApi, AttendScheduleConfigVO } from '@/api/hrm/attendscheduleconfig'
import AttendScheduleConfigForm from './AttendScheduleConfigForm.vue'
/** 考勤排班调度配置 列表 */
defineOptions({ name: 'AttendScheduleConfig' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<AttendScheduleConfigVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
ruleId: undefined,
scheduleType: undefined,
dayIndex: undefined,
shiftId: undefined,
isWorkingDay: undefined,
remarks: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await AttendScheduleConfigApi.getAttendScheduleConfigPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await AttendScheduleConfigApi.deleteAttendScheduleConfig(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await AttendScheduleConfigApi.exportAttendScheduleConfig(queryParams)
download.excel(data, '考勤排班调度配置.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,124 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="所属考勤规则" prop="ruleId">
<el-input v-model="formData.ruleId" placeholder="请输入所属考勤规则" />
</el-form-item>
<el-form-item label="班次名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入班次名称" />
</el-form-item>
<el-form-item label="班次类型1固定班次 2轮班制三班倒" prop="shiftType">
<el-select v-model="formData.shiftType" placeholder="请选择班次类型1固定班次 2轮班制三班倒">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_SHIFT_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否包含休息时段" prop="restIncluded">
<el-radio-group v-model="formData.restIncluded">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { AttendShiftApi, AttendShiftVO } from '@/api/hrm/attendshift'
/** 考勤班次 表单 */
defineOptions({ name: 'AttendShiftForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
ruleId: undefined,
name: undefined,
shiftType: undefined,
restIncluded: undefined
})
const formRules = reactive({
ruleId: [{ required: true, message: '所属考勤规则不能为空', trigger: 'blur' }],
name: [{ required: true, message: '班次名称不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await AttendShiftApi.getAttendShift(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as AttendShiftVO
if (formType.value === 'create') {
await AttendShiftApi.createAttendShift(data)
message.success(t('common.createSuccess'))
} else {
await AttendShiftApi.updateAttendShift(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
ruleId: undefined,
name: undefined,
shiftType: undefined,
restIncluded: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,241 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="所属考勤规则" prop="ruleId">
<el-input
v-model="queryParams.ruleId"
placeholder="请输入所属考勤规则"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="班次名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入班次名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="班次类型1固定班次 2轮班制三班倒" prop="shiftType">
<el-select
v-model="queryParams.shiftType"
placeholder="请选择班次类型1固定班次 2轮班制三班倒"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_SHIFT_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否包含休息时段" prop="restIncluded">
<el-select
v-model="queryParams.restIncluded"
placeholder="请选择是否包含休息时段"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['hrm:attend-shift:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['hrm:attend-shift:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="所属考勤规则" align="center" prop="ruleId" />
<el-table-column label="班次名称" align="center" prop="name" />
<el-table-column label="班次类型1固定班次 2轮班制三班倒" align="center" prop="shiftType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HRM_SHIFT_TYPE" :value="scope.row.shiftType" />
</template>
</el-table-column>
<el-table-column label="是否包含休息时段" align="center" prop="restIncluded">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.restIncluded" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['hrm:attend-shift:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['hrm:attend-shift:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<AttendShiftForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { AttendShiftApi, AttendShiftVO } from '@/api/hrm/attendshift'
import AttendShiftForm from './AttendShiftForm.vue'
/** 考勤班次 列表 */
defineOptions({ name: 'AttendShift' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<AttendShiftVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
ruleId: undefined,
name: undefined,
shiftType: undefined,
restIncluded: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await AttendShiftApi.getAttendShiftPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await AttendShiftApi.deleteAttendShift(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await AttendShiftApi.exportAttendShift(queryParams)
download.excel(data, '考勤班次.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,139 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="关联班次ID" prop="shiftId">
<el-input v-model="formData.shiftId" placeholder="请输入关联班次ID" />
</el-form-item>
<el-form-item label="上班时间" prop="startTime">
<el-date-picker
v-model="formData.startTime"
type="date"
value-format="x"
placeholder="选择上班时间"
/>
</el-form-item>
<el-form-item label="下班时间" prop="endTime">
<el-date-picker
v-model="formData.endTime"
type="date"
value-format="x"
placeholder="选择下班时间"
/>
</el-form-item>
<el-form-item label="休息开始时间" prop="restStartTime">
<el-date-picker
v-model="formData.restStartTime"
type="date"
value-format="x"
placeholder="选择休息开始时间"
/>
</el-form-item>
<el-form-item label="休息结束时间" prop="restEndTime">
<el-date-picker
v-model="formData.restEndTime"
type="date"
value-format="x"
placeholder="选择休息结束时间"
/>
</el-form-item>
<el-form-item label="时段顺序(如早班、中班、晚班)" prop="seq">
<el-input v-model="formData.seq" placeholder="请输入时段顺序(如早班、中班、晚班)" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { AttendShiftTimeApi, AttendShiftTimeVO } from '@/api/hrm/attendshifttime'
/** 考勤班次时间 表单 */
defineOptions({ name: 'AttendShiftTimeForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
shiftId: undefined,
startTime: undefined,
endTime: undefined,
restStartTime: undefined,
restEndTime: undefined,
seq: undefined
})
const formRules = reactive({
shiftId: [{ required: true, message: '关联班次ID不能为空', trigger: 'blur' }],
startTime: [{ required: true, message: '上班时间不能为空', trigger: 'blur' }],
endTime: [{ required: true, message: '下班时间不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await AttendShiftTimeApi.getAttendShiftTime(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as AttendShiftTimeVO
if (formType.value === 'create') {
await AttendShiftTimeApi.createAttendShiftTime(data)
message.success(t('common.createSuccess'))
} else {
await AttendShiftTimeApi.updateAttendShiftTime(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
shiftId: undefined,
startTime: undefined,
endTime: undefined,
restStartTime: undefined,
restEndTime: undefined,
seq: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,250 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="关联班次ID" prop="shiftId">
<el-input
v-model="queryParams.shiftId"
placeholder="请输入关联班次ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="上班时间" prop="startTime">
<el-date-picker
v-model="queryParams.startTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="下班时间" prop="endTime">
<el-date-picker
v-model="queryParams.endTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="休息开始时间" prop="restStartTime">
<el-date-picker
v-model="queryParams.restStartTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="休息结束时间" prop="restEndTime">
<el-date-picker
v-model="queryParams.restEndTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="时段顺序(如早班、中班、晚班)" prop="seq">
<el-input
v-model="queryParams.seq"
placeholder="请输入时段顺序(如早班、中班、晚班)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['hrm:attend-shift-time:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['hrm:attend-shift-time:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="关联班次ID" align="center" prop="shiftId" />
<el-table-column label="上班时间" align="center" prop="startTime" />
<el-table-column label="下班时间" align="center" prop="endTime" />
<el-table-column label="休息开始时间" align="center" prop="restStartTime" />
<el-table-column label="休息结束时间" align="center" prop="restEndTime" />
<el-table-column label="时段顺序(如早班、中班、晚班)" align="center" prop="seq" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['hrm:attend-shift-time:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['hrm:attend-shift-time:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<AttendShiftTimeForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { AttendShiftTimeApi, AttendShiftTimeVO } from '@/api/hrm/attendshifttime'
import AttendShiftTimeForm from './AttendShiftTimeForm.vue'
/** 考勤班次时间 列表 */
defineOptions({ name: 'AttendShiftTime' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<AttendShiftTimeVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
shiftId: undefined,
startTime: [],
endTime: [],
restStartTime: [],
restEndTime: [],
seq: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await AttendShiftTimeApi.getAttendShiftTimePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await AttendShiftTimeApi.deleteAttendShiftTime(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await AttendShiftTimeApi.exportAttendShiftTime(queryParams)
download.excel(data, '考勤班次时间.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,135 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="员工档案ID关联 hrm_user_infor" prop="userId">
<el-input v-model="formData.userId" placeholder="请输入员工档案ID关联 hrm_user_infor" />
</el-form-item>
<el-form-item label="考核月份格式YYYY-MM" prop="assessmentMonth">
<el-input v-model="formData.assessmentMonth" placeholder="请输入考核月份格式YYYY-MM" />
</el-form-item>
<el-form-item label="绩效等级" prop="performanceLevel">
<el-select v-model="formData.performanceLevel" placeholder="请选择绩效等级">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_PERFORMANCE_LEVEL)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="考核得分合计" prop="assessmentScoreTotal">
<el-input v-model="formData.assessmentScoreTotal" placeholder="请输入考核得分合计" />
</el-form-item>
<el-form-item label="考勤得分" prop="attendanceScore">
<el-input v-model="formData.attendanceScore" placeholder="请输入考勤得分" />
</el-form-item>
<el-form-item label="业绩考核得分" prop="performanceAssessmentScore">
<el-input v-model="formData.performanceAssessmentScore" placeholder="请输入业绩考核得分" />
</el-form-item>
<el-form-item label="行为考核得分" prop="behaviorAssessmentScore">
<el-input v-model="formData.behaviorAssessmentScore" placeholder="请输入行为考核得分" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { UserPerformanceApi, UserPerformanceVO } from '@/api/hrm/userperformance'
/** 员工绩效 表单 */
defineOptions({ name: 'UserPerformanceForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
userId: undefined,
assessmentMonth: undefined,
performanceLevel: undefined,
assessmentScoreTotal: undefined,
attendanceScore: undefined,
performanceAssessmentScore: undefined,
behaviorAssessmentScore: undefined
})
const formRules = reactive({
assessmentMonth: [{ required: true, message: '考核月份格式YYYY-MM不能为空', trigger: 'blur' }],
performanceLevel: [{ required: true, message: '绩效等级不能为空', trigger: 'change' }],
assessmentScoreTotal: [{ required: true, message: '考核得分合计不能为空', trigger: 'blur' }],
attendanceScore: [{ required: true, message: '考勤得分不能为空', trigger: 'blur' }],
performanceAssessmentScore: [{ required: true, message: '业绩考核得分不能为空', trigger: 'blur' }],
behaviorAssessmentScore: [{ required: true, message: '行为考核得分不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await UserPerformanceApi.getUserPerformance(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as UserPerformanceVO
if (formType.value === 'create') {
await UserPerformanceApi.createUserPerformance(data)
message.success(t('common.createSuccess'))
} else {
await UserPerformanceApi.updateUserPerformance(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
userId: undefined,
assessmentMonth: undefined,
performanceLevel: undefined,
assessmentScoreTotal: undefined,
attendanceScore: undefined,
performanceAssessmentScore: undefined,
behaviorAssessmentScore: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,264 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="员工档案ID关联 hrm_user_infor" prop="userId">
<el-input
v-model="queryParams.userId"
placeholder="请输入员工档案ID关联 hrm_user_infor"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="考核月份格式YYYY-MM" prop="assessmentMonth">
<el-input
v-model="queryParams.assessmentMonth"
placeholder="请输入考核月份格式YYYY-MM"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="绩效等级" prop="performanceLevel">
<el-select
v-model="queryParams.performanceLevel"
placeholder="请选择绩效等级"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HRM_PERFORMANCE_LEVEL)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="考核得分合计" prop="assessmentScoreTotal">
<el-input
v-model="queryParams.assessmentScoreTotal"
placeholder="请输入考核得分合计"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="考勤得分" prop="attendanceScore">
<el-input
v-model="queryParams.attendanceScore"
placeholder="请输入考勤得分"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="业绩考核得分" prop="performanceAssessmentScore">
<el-input
v-model="queryParams.performanceAssessmentScore"
placeholder="请输入业绩考核得分"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="行为考核得分" prop="behaviorAssessmentScore">
<el-input
v-model="queryParams.behaviorAssessmentScore"
placeholder="请输入行为考核得分"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['hrm:user-performance:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['hrm:user-performance:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="唯一主键" align="center" prop="id" />
<el-table-column label="员工档案ID关联 hrm_user_infor" align="center" prop="userId" />
<el-table-column label="考核月份格式YYYY-MM" align="center" prop="assessmentMonth" />
<el-table-column label="绩效等级" align="center" prop="performanceLevel">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HRM_PERFORMANCE_LEVEL" :value="scope.row.performanceLevel" />
</template>
</el-table-column>
<el-table-column label="考核得分合计" align="center" prop="assessmentScoreTotal" />
<el-table-column label="考勤得分" align="center" prop="attendanceScore" />
<el-table-column label="业绩考核得分" align="center" prop="performanceAssessmentScore" />
<el-table-column label="行为考核得分" align="center" prop="behaviorAssessmentScore" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['hrm:user-performance:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['hrm:user-performance:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<UserPerformanceForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { UserPerformanceApi, UserPerformanceVO } from '@/api/hrm/userperformance'
import UserPerformanceForm from './UserPerformanceForm.vue'
/** 员工绩效 列表 */
defineOptions({ name: 'UserPerformance' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<UserPerformanceVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
userId: undefined,
assessmentMonth: undefined,
performanceLevel: undefined,
assessmentScoreTotal: undefined,
attendanceScore: undefined,
performanceAssessmentScore: undefined,
behaviorAssessmentScore: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await UserPerformanceApi.getUserPerformancePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await UserPerformanceApi.deleteUserPerformance(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await UserPerformanceApi.exportUserPerformance(queryParams)
download.excel(data, '员工绩效.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,121 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="岗位关联ID" prop="postId">
<el-input v-model="formData.postId" placeholder="请输入岗位关联ID" />
</el-form-item>
<el-form-item label="考核类型" prop="assessType">
<el-select v-model="formData.assessType" placeholder="请选择考核类型">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HRM_ASSESS_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="考核名称" prop="assessName">
<el-input v-model="formData.assessName" placeholder="请输入考核名称" />
</el-form-item>
<el-form-item label="考核详情" prop="assessDetail">
<el-input v-model="formData.assessDetail" placeholder="请输入考核详情" />
</el-form-item>
<el-form-item label="分数分值" prop="score">
<el-input v-model="formData.score" placeholder="请输入分数分值" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { PostAssessmentApi, PostAssessmentVO } from '@/api/system/postassessment'
/** 职位考核信息 表单 */
defineOptions({ name: 'PostAssessmentForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
postId: undefined,
assessType: undefined,
assessName: undefined,
assessDetail: undefined,
score: undefined
})
const formRules = reactive({
postId: [{ required: true, message: '岗位关联ID不能为空', trigger: 'blur' }],
assessName: [{ required: true, message: '考核名称不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await PostAssessmentApi.getPostAssessment(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as PostAssessmentVO
if (formType.value === 'create') {
await PostAssessmentApi.createPostAssessment(data)
message.success(t('common.createSuccess'))
} else {
await PostAssessmentApi.updatePostAssessment(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
postId: undefined,
assessType: undefined,
assessName: undefined,
assessDetail: undefined,
score: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,222 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="岗位关联ID" prop="postId">
<el-input
v-model="queryParams.postId"
placeholder="请输入岗位关联ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="考核类型" prop="assessType">
<el-select
v-model="queryParams.assessType"
placeholder="请选择考核类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HRM_ASSESS_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="考核名称" prop="assessName">
<el-input
v-model="queryParams.assessName"
placeholder="请输入考核名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="考核详情" prop="assessDetail">
<el-input
v-model="queryParams.assessDetail"
placeholder="请输入考核详情"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="分数分值" prop="score">
<el-input
v-model="queryParams.score"
placeholder="请输入分数分值"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['system:post-assessment:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['system:post-assessment:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="岗位关联ID" align="center" prop="postId" />
<el-table-column label="考核类型" align="center" prop="assessType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.HRM_ASSESS_TYPE" :value="scope.row.assessType" />
</template>
</el-table-column>
<el-table-column label="考核名称" align="center" prop="assessName" />
<el-table-column label="考核详情" align="center" prop="assessDetail" />
<el-table-column label="分数分值" align="center" prop="score" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['system:post-assessment:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['system:post-assessment:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<PostAssessmentForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import download from '@/utils/download'
import { PostAssessmentApi, PostAssessmentVO } from '@/api/system/postassessment'
import PostAssessmentForm from './PostAssessmentForm.vue'
/** 职位考核信息 列表 */
defineOptions({ name: 'PostAssessment' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<PostAssessmentVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
postId: undefined,
assessType: undefined,
assessName: undefined,
assessDetail: undefined,
score: undefined
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await PostAssessmentApi.getPostAssessmentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await PostAssessmentApi.deletePostAssessment(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await PostAssessmentApi.exportPostAssessment(queryParams)
download.excel(data, '职位考核信息.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,103 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="岗位关联ID" prop="postId">
<el-input v-model="formData.postId" placeholder="请输入岗位关联ID" />
</el-form-item>
<el-form-item label="名称" prop="requirementName">
<el-input v-model="formData.requirementName" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="资格说明" prop="qualificationDescription">
<Editor v-model="formData.qualificationDescription" height="150px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { PostRequirementApi, PostRequirementVO } from '@/api/system/postrequirement'
/** 任职条件 表单 */
defineOptions({ name: 'PostRequirementForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
postId: undefined,
requirementName: undefined,
qualificationDescription: undefined
})
const formRules = reactive({
postId: [{ required: true, message: '岗位关联ID不能为空', trigger: 'blur' }],
requirementName: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await PostRequirementApi.getPostRequirement(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as PostRequirementVO
if (formType.value === 'create') {
await PostRequirementApi.createPostRequirement(data)
message.success(t('common.createSuccess'))
} else {
await PostRequirementApi.updatePostRequirement(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
postId: undefined,
requirementName: undefined,
qualificationDescription: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,180 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="岗位关联ID" prop="postId">
<el-input
v-model="queryParams.postId"
placeholder="请输入岗位关联ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="名称" prop="requirementName">
<el-input
v-model="queryParams.requirementName"
placeholder="请输入名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['system:post-requirement:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['system:post-requirement:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="唯一主键" align="center" prop="id" />
<el-table-column label="岗位关联ID" align="center" prop="postId" />
<el-table-column label="名称" align="center" prop="requirementName" />
<el-table-column label="资格说明" align="center" prop="qualificationDescription" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['system:post-requirement:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['system:post-requirement:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<PostRequirementForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import download from '@/utils/download'
import { PostRequirementApi, PostRequirementVO } from '@/api/system/postrequirement'
import PostRequirementForm from './PostRequirementForm.vue'
/** 任职条件 列表 */
defineOptions({ name: 'PostRequirement' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<PostRequirementVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
postId: undefined,
requirementName: undefined,
qualificationDescription: undefined
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await PostRequirementApi.getPostRequirementPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await PostRequirementApi.deletePostRequirement(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await PostRequirementApi.exportPostRequirement(queryParams)
download.excel(data, '任职条件.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,109 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="岗位关联ID" prop="postId">
<el-input v-model="formData.postId" placeholder="请输入岗位关联ID" />
</el-form-item>
<el-form-item label="职责" prop="responsibility">
<el-input v-model="formData.responsibility" placeholder="请输入职责" />
</el-form-item>
<el-form-item label="任务" prop="task">
<el-input v-model="formData.task" placeholder="请输入任务" />
</el-form-item>
<el-form-item label="时间分配" prop="timeAllocation">
<el-input v-model="formData.timeAllocation" placeholder="请输入时间分配" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { PostResponsibilityApi, PostResponsibilityVO } from '@/api/system/postresponsibility'
/** 岗位职责 表单 */
defineOptions({ name: 'PostResponsibilityForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
postId: undefined,
responsibility: undefined,
task: undefined,
timeAllocation: undefined
})
const formRules = reactive({
postId: [{ required: true, message: '岗位关联ID不能为空', trigger: 'blur' }],
responsibility: [{ required: true, message: '职责不能为空', trigger: 'blur' }],
task: [{ required: true, message: '任务不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await PostResponsibilityApi.getPostResponsibility(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as PostResponsibilityVO
if (formType.value === 'create') {
await PostResponsibilityApi.createPostResponsibility(data)
message.success(t('common.createSuccess'))
} else {
await PostResponsibilityApi.updatePostResponsibility(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
postId: undefined,
responsibility: undefined,
task: undefined,
timeAllocation: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,200 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="岗位关联ID" prop="postId">
<el-input
v-model="queryParams.postId"
placeholder="请输入岗位关联ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="职责" prop="responsibility">
<el-input
v-model="queryParams.responsibility"
placeholder="请输入职责"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="任务" prop="task">
<el-input
v-model="queryParams.task"
placeholder="请输入任务"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="时间分配" prop="timeAllocation">
<el-input
v-model="queryParams.timeAllocation"
placeholder="请输入时间分配"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['system:post-responsibility:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['system:post-responsibility:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="唯一主键" align="center" prop="id" />
<el-table-column label="岗位关联ID" align="center" prop="postId" />
<el-table-column label="职责" align="center" prop="responsibility" />
<el-table-column label="任务" align="center" prop="task" />
<el-table-column label="时间分配" align="center" prop="timeAllocation" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['system:post-responsibility:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['system:post-responsibility:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<PostResponsibilityForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import download from '@/utils/download'
import { PostResponsibilityApi, PostResponsibilityVO } from '@/api/system/postresponsibility'
import PostResponsibilityForm from './PostResponsibilityForm.vue'
/** 岗位职责 列表 */
defineOptions({ name: 'PostResponsibility' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<PostResponsibilityVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
postId: undefined,
responsibility: undefined,
task: undefined,
timeAllocation: undefined
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await PostResponsibilityApi.getPostResponsibilityPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await PostResponsibilityApi.deletePostResponsibility(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await PostResponsibilityApi.exportPostResponsibility(queryParams)
download.excel(data, '岗位职责.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>