dev-cl
parent
82f7d4be5e
commit
17208922ad
@ -0,0 +1,183 @@ |
||||
<template> |
||||
<Dialog :title="title" v-model="show" width="800px"> |
||||
<el-form v-loading="formLoading" :model="form" ref="formRef" :rules="rules" label-width="80px"> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="24" :offset="0"> |
||||
<el-form-item label="考核指标" prop="name"> |
||||
<el-input v-model="form.name" placeholder="请输入" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="12" :offset="0"> |
||||
<el-form-item label="权重" prop="rate"> |
||||
<el-input-number v-model="form.rate" :min="0" :step="1" :controls="false" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12" :offset="0"> |
||||
<el-form-item label="评分上限" prop="maxScore"> |
||||
<el-input-number v-model="form.maxScore" :min="0" :step="1" :controls="false" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
|
||||
<el-row :gutter="20"> |
||||
<el-col :span="24" :offset="0"> |
||||
<el-form-item label="考核内容" prop="kaoheneirong"> |
||||
<Editor |
||||
v-model:modelValue="form.kaoheneirong" |
||||
height="150px" |
||||
:toolbarConfig="{ |
||||
toolbarKeys: [] |
||||
}" |
||||
style="width: 100%" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="24" :offset="0"> |
||||
<el-form-item label="考核规则" prop="kaoheguize"> |
||||
<Editor |
||||
v-model:modelValue="form.kaoheguize" |
||||
height="150px" |
||||
:toolbarConfig="{ toolbarKeys: [] }" |
||||
style="width: 100%" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="24" :offset="0"> |
||||
<el-form-item label="考核员工" prop="checkEmployees"> |
||||
<div> |
||||
<el-checkbox |
||||
v-model="checkAll" |
||||
:indeterminate="isIndeterminate" |
||||
@change="handleCheckAllChange" |
||||
> |
||||
全选 |
||||
</el-checkbox> |
||||
<el-checkbox-group v-model="form.checkEmployees" @change="handleCheckedChange"> |
||||
<el-checkbox |
||||
v-for="item in employeeOptions" |
||||
:key="item.id" |
||||
:label="item.id" |
||||
:value="item.id" |
||||
> |
||||
{{ item.name }} |
||||
</el-checkbox> |
||||
</el-checkbox-group> |
||||
</div> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<template #footer> |
||||
<span> |
||||
<el-button @click="show = false">取 消</el-button> |
||||
<el-button type="primary" :disabled="formLoading" @click="handleSave">保 存</el-button> |
||||
</span> |
||||
</template> |
||||
</Dialog> |
||||
</template> |
||||
|
||||
<script setup name="DialogAppraise"> |
||||
// import * as ResourceApi from '@/api/system/library/resource' |
||||
|
||||
const { t } = useI18n() // 国际化 |
||||
const message = useMessage() // 消息弹窗 |
||||
|
||||
const show = ref(false) |
||||
const title = ref('') |
||||
const formType = ref('create') |
||||
|
||||
const form = ref({}) |
||||
const formLoading = ref(false) |
||||
const rules = ref({ |
||||
name: { required: true, message: '标题不可为空', trigger: 'blur' }, |
||||
kaoheneirong: { required: true, message: '标题不可为空', trigger: 'blur' }, |
||||
kaoheguize: { required: true, message: '标题不可为空', trigger: 'blur' } |
||||
}) |
||||
|
||||
async function open(type, val) { |
||||
show.value = true |
||||
title.value = type == 'update' ? '修改考核项' : '新增考核项' |
||||
formType.value = type |
||||
resetForm() |
||||
if (val?.id) { |
||||
formLoading.value = true |
||||
try { |
||||
// form.value = await ResourceApi.getResource(id) |
||||
} finally { |
||||
formLoading.value = false |
||||
} |
||||
} else if (val.name) { |
||||
form.value = { ...val } |
||||
} |
||||
const checkedCount = form.value.checkEmployees?.length || 0 |
||||
isIndeterminate.value = checkedCount > 0 && checkedCount < employeeOptions.value.length |
||||
} |
||||
|
||||
function resetForm() { |
||||
form.value = { |
||||
name: '', |
||||
rate: 0, |
||||
kaoheneirong: ``, |
||||
kaoheguize: ``, |
||||
maxScore: 5, |
||||
checkEmployees: [] |
||||
} |
||||
} |
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||
|
||||
const formRef = ref() |
||||
|
||||
/** 提交表单 */ |
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||
async function handleSave() { |
||||
// 校验表单 |
||||
if (!formRef.value) return |
||||
const valid = await formRef.value.validate() |
||||
if (!valid) return |
||||
// 提交请求 |
||||
formLoading.value = true |
||||
try { |
||||
if (formType.value === 'create') { |
||||
// await ResourceApi.createResource(form.value) |
||||
message.success(t('common.createSuccess')) |
||||
} else { |
||||
// await ResourceApi.updateResource(form.value) |
||||
message.success(t('common.updateSuccess')) |
||||
} |
||||
show.value = false |
||||
// 发送操作成功的事件 |
||||
emit('success', form.value) |
||||
} finally { |
||||
formLoading.value = false |
||||
} |
||||
} |
||||
|
||||
const checkAll = ref(false) |
||||
const isIndeterminate = ref(false) |
||||
const employeeOptions = ref([ |
||||
{ id: 1, name: '武大郎' }, |
||||
{ id: 2, name: '李二郎' }, |
||||
{ id: 3, name: '拼命三郎' }, |
||||
{ id: 4, name: '杨四郎' } |
||||
]) |
||||
|
||||
function handleCheckAllChange(val) { |
||||
form.value.checkEmployees = val ? employeeOptions.value.map((it) => it.id) : [] |
||||
isIndeterminate.value = false |
||||
} |
||||
|
||||
function handleCheckedChange(value) { |
||||
const checkedCount = value.length |
||||
checkAll.value = checkedCount === employeeOptions.value.length |
||||
isIndeterminate.value = checkedCount > 0 && checkedCount < employeeOptions.value.length |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,147 @@ |
||||
<template> |
||||
<div> |
||||
<!-- 搜索工作栏 --> |
||||
<el-form :model="searchForm" ref="queryFormRef" inline label-width="0"> |
||||
<el-form-item> |
||||
<el-input v-model="searchForm.name" placeholder="请输入考核指标" clearable /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button @click="handleQuery" v-hasPermi="['kpi:appraise:search']"> 搜索</el-button> |
||||
<el-button @click="resetQuery" v-hasPermi="['kpi:appraise:reset']"> 重置</el-button> |
||||
<el-button |
||||
type="primary" |
||||
plain |
||||
@click="openForm('create')" |
||||
v-hasPermi="['kpi:appraise:add']" |
||||
> |
||||
新增 |
||||
</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<!-- 列表 --> |
||||
<el-table v-loading="loading" :data="list" border> |
||||
<el-table-column prop="name" label="考核指标" width="180" /> |
||||
<el-table-column prop="rate" label="权重%" width="90" /> |
||||
<el-table-column label="考核内容"> |
||||
<template #default="{ row }"> |
||||
<div v-dompurify-html="row.kaoheneirong"></div> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="考核规则" prop="kaoheguize"> |
||||
<template #default="{ row }"> |
||||
<div v-dompurify-html="row.kaoheguize"></div> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="评分上限" prop="maxScore" width="90" /> |
||||
<el-table-column label="考核人数" width="90"> |
||||
<template #default="{ row }"> |
||||
{{ row.checkEmployees?.length || 0 }} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" class-name="fixed-width" width="120"> |
||||
<template #default="{ row }"> |
||||
<el-button |
||||
link |
||||
type="primary" |
||||
@click="openForm('update', row)" |
||||
v-hasPermi="['kpi:appraise:update']" |
||||
> |
||||
修改 |
||||
</el-button> |
||||
<el-button |
||||
link |
||||
type="danger" |
||||
@click="handleDelete(row.id)" |
||||
v-hasPermi="['kpi:appraise:remove']" |
||||
> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<Pagination |
||||
v-model:limit="searchForm.pageSize" |
||||
v-model:page="searchForm.pageNo" |
||||
:total="total" |
||||
@pagination="getList" |
||||
/> |
||||
|
||||
<DialogAppraise ref="formRef" @success="handleQuery" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup name="KpiContent"> |
||||
import DialogAppraise from './Components/DialogAppraise.vue' |
||||
|
||||
const message = useMessage() // 消息弹窗 |
||||
const loading = ref(false) // 列表的加载中 |
||||
const list = ref() // 列表的数据 |
||||
const searchForm = ref({ |
||||
name: undefined, |
||||
pageNo: 1, |
||||
pageSize: 20 |
||||
}) |
||||
const total = ref(0) |
||||
|
||||
/** 初始化 **/ |
||||
onMounted(() => { |
||||
handleQuery() |
||||
}) |
||||
|
||||
const getList = async (info) => { |
||||
loading.value = true |
||||
try { |
||||
const data = [ |
||||
{ |
||||
name: '纳税申报', |
||||
rate: 35, |
||||
kaoheneirong: |
||||
'<p>1、每个月13号之前在柠檬云财税把上个月的财务数据录入系统出具财务报表;</p><p>2、社保和公积金及时增减人员,做好核定工作,及时申报缴纳;</p><p>3、按照税务局规定时间把自己所负责的公司增指税、附加税、所得税以及其他税种申报完成</p>', |
||||
kaoheguize: `当天处理完今日线索,连续2天未处理完,一次扣2分,最多扣5分`, |
||||
maxScore: 5, |
||||
checkEmployees: [1, 3, 4] |
||||
} |
||||
] |
||||
if (info) { |
||||
data.push(info) |
||||
} |
||||
list.value = data |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
} |
||||
|
||||
/** 搜索按钮操作 */ |
||||
const handleQuery = (info) => { |
||||
searchForm.value.pageNo = 1 |
||||
getList(info) |
||||
} |
||||
|
||||
/** 重置按钮操作 */ |
||||
const resetQuery = () => { |
||||
queryFormRef.value.resetFields() |
||||
handleQuery() |
||||
} |
||||
|
||||
/** 添加/修改操作 */ |
||||
const formRef = ref() |
||||
const openForm = (type, row) => { |
||||
formRef.value.open(type, row) |
||||
} |
||||
|
||||
/** 删除按钮操作 */ |
||||
const handleDelete = async (id) => { |
||||
try { |
||||
// 删除的二次确认 |
||||
await message.delConfirm() |
||||
// 发起删除 |
||||
await DeptApi.deleteDept(id) |
||||
message.success(t('common.delSuccess')) |
||||
// 刷新列表 |
||||
await getList() |
||||
} catch {} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,205 @@ |
||||
<template> |
||||
<div> |
||||
<!-- 搜索工作栏 --> |
||||
<el-form :model="searchForm" inline label-width="0"> |
||||
<el-form-item> |
||||
<el-date-picker |
||||
v-model="searchForm.peroid" |
||||
type="month" |
||||
format="YYYY-MM" |
||||
value-format="YYYY-MM" |
||||
:clearable="false" |
||||
style="width: 100%" |
||||
/> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button @click="getList" v-hasPermi="['kpi:score:search']"> 搜索</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
<el-tabs v-model="searchForm.employeeId" @tab-click="getList"> |
||||
<el-tab-pane |
||||
v-for="item in employeeOptions" |
||||
:key="item.id" |
||||
:label="item.name" |
||||
:name="item.id" |
||||
> |
||||
<div class="mb-10px"> |
||||
<el-tag v-if="peroidSaved" type="danger"> 当前周期已封存,不可修改当月绩效考核 </el-tag> |
||||
<el-tag v-else type="warning"> |
||||
当前周期未封存,可选择修改当月绩效考核,两秒内不操作将自动保存考核结果 |
||||
</el-tag> |
||||
</div> |
||||
|
||||
<el-table |
||||
v-loading="loading" |
||||
:data="list" |
||||
border |
||||
show-summary |
||||
:summary-method="getSummaries" |
||||
> |
||||
<el-table-column prop="name" label="考核指标" width="180" /> |
||||
<el-table-column prop="rate" label="权重%" width="90" /> |
||||
<el-table-column label="考核内容"> |
||||
<template #default="{ row }"> |
||||
<div v-dompurify-html="row.kaoheneirong"></div> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="考核规则" prop="kaoheguize"> |
||||
<template #default="{ row }"> |
||||
<div v-dompurify-html="row.kaoheguize"></div> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="评分上限" prop="maxScore" width="90" /> |
||||
<el-table-column label="考核评分" width="120"> |
||||
<template #default="{ row }"> |
||||
<div v-if="peroidSaved">{{ row.score }}</div> |
||||
<el-input-number |
||||
v-else |
||||
v-model="row.score" |
||||
:min="0" |
||||
:max="row.maxScore" |
||||
:step="1" |
||||
:controls="false" |
||||
size="small" |
||||
style="width: 100%" |
||||
@input="handleSave(row)" |
||||
/> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="评分备注" width="200"> |
||||
<template #default="{ row }"> |
||||
<div v-if="peroidSaved">{{ row.remark }}</div> |
||||
<el-input |
||||
v-else |
||||
v-model="row.remark" |
||||
type="textarea" |
||||
:rows="3" |
||||
size="small" |
||||
style="width: 100%" |
||||
@input="handleSave(row)" |
||||
/> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="加权得分" prop="jiaquandefen" width="90" /> |
||||
</el-table> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup name="KpiScore"> |
||||
import { formatDate } from '@/utils/formatTime' |
||||
|
||||
const message = useMessage() // 消息弹窗 |
||||
const loading = ref(false) // 列表的加载中 |
||||
const list = ref() // 列表的数据 |
||||
const searchForm = ref({ |
||||
peroid: undefined, |
||||
employeeId: undefined |
||||
}) |
||||
|
||||
const peroidSaved = ref(true) |
||||
|
||||
const employeeOptions = ref([ |
||||
{ id: 1, name: '武大郎' }, |
||||
{ id: 2, name: '李二郎' }, |
||||
{ id: 3, name: '拼命三郎' }, |
||||
{ id: 4, name: '杨四郎' } |
||||
// { id: 11, name: '武大郎' }, |
||||
// { id: 21, name: '李二郎' }, |
||||
// { id: 31, name: '拼命三郎' }, |
||||
// { id: 41, name: '杨四郎' }, |
||||
// { id: 12, name: '武大郎' }, |
||||
// { id: 22, name: '李二郎' }, |
||||
// { id: 32, name: '拼命三郎' }, |
||||
// { id: 42, name: '杨四郎' }, |
||||
// { id: 13, name: '武大郎' }, |
||||
// { id: 23, name: '李二郎' }, |
||||
// { id: 33, name: '拼命三郎' }, |
||||
// { id: 43, name: '杨四郎' } |
||||
]) |
||||
|
||||
onMounted(() => { |
||||
// 取上个月 |
||||
const today = new Date() |
||||
searchForm.value.peroid = formatDate( |
||||
new Date(today.getFullYear(), today.getMonth() - 1), |
||||
'YYYY-MM' |
||||
) |
||||
if (employeeOptions.value.length > 0) { |
||||
searchForm.value.employeeId = employeeOptions.value[0].id |
||||
} |
||||
|
||||
getList() |
||||
}) |
||||
|
||||
async function getList() { |
||||
if (!searchForm.value.employeeId) { |
||||
message.error('当月无待考核员工!!!') |
||||
return |
||||
} |
||||
|
||||
loading.value = true |
||||
try { |
||||
const data = [ |
||||
{ |
||||
name: '纳税申报', |
||||
rate: 40, |
||||
kaoheneirong: |
||||
'<p>1、每个月13号之前在柠檬云财税把上个月的财务数据录入系统出具财务报表;</p><p>2、社保和公积金及时增减人员,做好核定工作,及时申报缴纳;</p><p>3、按照税务局规定时间把自己所负责的公司增指税、附加税、所得税以及其他税种申报完成</p>', |
||||
kaoheguize: `当天处理完今日线索,连续2天未处理完,一次扣2分,最多扣5分`, |
||||
maxScore: 20, |
||||
score: 10, |
||||
checkEmployees: [1, 3, 4], |
||||
jiaquandefen: 4 |
||||
}, |
||||
{ |
||||
name: '数据统计', |
||||
rate: 20, |
||||
kaoheneirong: |
||||
'<p>1、每个月13号之前在柠檬云财税把上个月的财务数据录入系统出具财务报表;</p><p>2、社保和公积金及时增减人员,做好核定工作,及时申报缴纳;</p><p>3、按照税务局规定时间把自己所负责的公司增指税、附加税、所得税以及其他税种申报完成</p>', |
||||
kaoheguize: `当天处理完今日线索,连续2天未处理完,一次扣2分,最多扣5分`, |
||||
maxScore: 10, |
||||
score: 8, |
||||
checkEmployees: [1, 3, 4], |
||||
jiaquandefen: 1.6 |
||||
} |
||||
] |
||||
list.value = data |
||||
peroidSaved.value = !peroidSaved.value |
||||
} finally { |
||||
loading.value = false |
||||
} |
||||
} |
||||
|
||||
let timer = ref(null) |
||||
function handleSave() { |
||||
clearTimeout(timer.value) |
||||
timer.value = setTimeout(() => { |
||||
message.success('正在保存数据,请稍后') |
||||
}, 2000) |
||||
} |
||||
|
||||
function getSummaries({ columns, data }) { |
||||
let sums = [] |
||||
columns.forEach((column, index) => { |
||||
if (index == 0) { |
||||
sums[index] = '考核总分' |
||||
return |
||||
} |
||||
const values = data.map((item) => Number(item[column.property])) |
||||
if (!values.every((value) => Number.isNaN(value))) { |
||||
if (column.property == 'jiaquandefen') { |
||||
sums[index] = 5.6 |
||||
} else { |
||||
sums[index] = '' |
||||
} |
||||
} else { |
||||
sums[index] = '' |
||||
} |
||||
}) |
||||
return sums |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
Loading…
Reference in new issue