pull/5/head
qsh 1 month ago
parent e4ae5e275f
commit 1778ea9fb4
  1. 40
      src/components/Editor/src/Editor.vue
  2. 42
      src/router/modules/remaining.ts
  3. 183
      src/views/Kpi/Appraise/Components/DialogAppraise.vue
  4. 69
      src/views/Kpi/Appraise/index.vue
  5. 202
      src/views/Kpi/Score/index.vue

@ -24,7 +24,27 @@ const props = defineProps({
default: () => undefined
},
readonly: propTypes.bool.def(false),
modelValue: propTypes.string.def('')
modelValue: propTypes.string.def(''),
toolbarConfig: {
type: Object,
default: () => ({
excludeKeys: [
'insertVideo', //
'insertImage', //
'insertLink', //
'codeBlock', //
'headerSelect', //
'blockquote', //
'fontFamily', //
'todo', //
'group-indent', //
'emotion', //
'undo', //
'redo', //
'fullScreen'
]
})
}
})
const emit = defineEmits(['change', 'update:modelValue'])
@ -212,24 +232,6 @@ const editorStyle = computed(() => {
}
})
const toolbarConfig = ref({
excludeKeys: [
'insertVideo', //
'insertImage', //
'insertLink', //
'codeBlock', //
'headerSelect', //
'blockquote', //
'fontFamily', //
'todo', //
'group-indent', //
'emotion', //
'undo', //
'redo', //
'fullScreen'
]
})
//
const handleChange = (editor: IDomEditor) => {
emit('change', editor)

@ -129,27 +129,27 @@ const remainingRouter: AppRouteRecordRaw[] = [
// }
// ]
// },
// {
// path: '/Basic',
// component: Layout,
// name: 'Basic',
// meta: { title: '菜单管理' },
// redirect: '/Basic/menu',
// children: [
// {
// path: 'menu',
// component: () => import('@/views/Basic/Menu/index.vue'),
// name: 'Menu',
// meta: {
// canTo: true,
// hidden: true,
// noTagsView: false,
// icon: 'ep:user',
// title: '菜单管理'
// }
// }
// ]
// },
{
path: '/Basic',
component: Layout,
name: 'Basic',
meta: { title: '菜单管理' },
redirect: '/Basic/menu',
children: [
{
path: 'menu',
component: () => import('@/views/Basic/Menu/index.vue'),
name: 'Menu',
meta: {
canTo: true,
hidden: true,
noTagsView: false,
icon: 'ep:user',
title: '菜单管理'
}
}
]
},
{
path: '/login',
component: () => import('@/views/Login/Login.vue'),

@ -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>

@ -1,9 +1,9 @@
<template>
<div>
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryFormRef" inline label-width="0">
<el-form :model="searchForm" ref="queryFormRef" inline label-width="0">
<el-form-item>
<el-input v-model="queryParams.name" placeholder="请输入考核指标" clearable />
<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>
@ -22,17 +22,29 @@
<!-- 列表 -->
<el-table v-loading="loading" :data="list" border>
<el-table-column prop="name" label="考核指标" width="180" />
<el-table-column prop="leaderUserName" label="权重%" width="90" />
<el-table-column prop="sort" label="考核内容" />
<el-table-column label="考核规则" prop="createTime" />
<el-table-column label="评分上限" prop="createTime" width="90" />
<el-table-column label="考核人数" prop="createTime" width="90" />
<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.id)"
@click="openForm('update', row)"
v-hasPermi="['kpi:appraise:update']"
>
修改
@ -48,37 +60,62 @@
</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 queryParams = reactive({
const searchForm = ref({
name: undefined,
pageNo: 1,
pageSize: 20
})
const total = ref(0)
/** 初始化 **/
onMounted(() => {
handleQuery()
})
const getList = async () => {
const getList = async (info) => {
loading.value = true
try {
const data = await DeptApi.getDeptPage(queryParams)
list.value = handleTree(data)
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 = () => {
getList()
const handleQuery = (info) => {
searchForm.value.pageNo = 1
getList(info)
}
/** 重置按钮操作 */
@ -89,8 +126,8 @@ const resetQuery = () => {
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type, id) => {
formRef.value.open(type, id)
const openForm = (type, row) => {
formRef.value.open(type, row)
}
/** 删除按钮操作 */

@ -1,7 +1,205 @@
<template>
<div> 打分 </div>
<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)
}
<script setup name="KpiScore"></script>
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…
Cancel
Save