V1.1.1 业绩功能

This commit is contained in:
hupeng 2024-11-01 15:08:30 +08:00
parent 845d5f3240
commit 093e81ca31
9 changed files with 2101 additions and 40 deletions

View File

@ -0,0 +1,61 @@
import request from '@/config/axios'
// 业绩目标 VO
export interface AchievementVO {
id: number // id
name: string // 名称
config: number // 1销售目标2回款目标
type: number // 2部门3员工
typeId: number // 对象ID
year: number // 年
january: number // 一月
february: number // 二月
march: number // 三月
april: number // 四月
may: number // 五月
june: number // 六月
july: number // 七月
august: number // 八月
september: number // 九月
october: number // 十月
november: number // 十一月
december: number // 十二月
yeartarget: number // 年目标
}
// 业绩目标 API
export const AchievementApi = {
// 查询业绩目标分页
getAchievementPage: async (params: any) => {
return await request.get({ url: `/crm/achievement/page`, params })
},
getAchievementDept: async (params: any) => {
return await request.get({ url: `/crm/achievement/depts`, params })
},
// 查询业绩目标详情
getAchievement: async (id: number) => {
return await request.get({ url: `/crm/achievement/get?id=` + id })
},
// 新增业绩目标
createAchievement: async (data: AchievementVO) => {
return await request.post({ url: `/crm/achievement/create`, data })
},
// 修改业绩目标
updateAchievement: async (data: AchievementVO) => {
return await request.put({ url: `/crm/achievement/update`, data })
},
// 删除业绩目标
deleteAchievement: async (id: number) => {
return await request.delete({ url: `/crm/achievement/delete?id=` + id })
},
// 业绩统计
achievementCount: async (params) => {
return await request.get({ url: `/crm/achievement/count`, params })
}
}

View File

@ -152,7 +152,7 @@ export default {
router: {
login: '登录',
socialLogin: '社交登录',
home: '待办事项',
home: '控制台',
analysis: '分析页',
workplace: '工作台'
},

View File

@ -112,45 +112,28 @@
</div>
<!-- <PanelGroupT /> -->
<div class="divBox" style="background-color:#ffffff">
<el-tabs
v-model="activeName"
type="card"
class="demo-tabs"
@tab-click="handleClick"
>
<el-tab-pane name="first">
<template #label>
<span><el-badge :value="contractCheckCount" :hidden="contractCheckCount == 0">合同审批</el-badge></span>
</template>
<ContractList @get-contract-count="getContractCount" />
</el-tab-pane>
<el-tab-pane name="second">
<template #label>
<span><el-badge :value="receivablesCheckCount" :hidden="receivablesCheckCount == 0">回款审批</el-badge></span>
</template>
<ReceivablesList @get-receivables-count="getReceivablesCount" />
</el-tab-pane>
<el-tab-pane name="third">
<template #label>
<span><el-badge :value="invoiceCheckCount" :hidden="invoiceCheckCount == 0">发票审批</el-badge></span>
</template>
<InvoiceList @get-invoice-count="getInvoiceCount" />
</el-tab-pane>
</el-tabs>
<!-- <el-tabs type="border-card">
<el-tab-pane label="User" :disabled="true" />
<el-tab-pane label="Config" />
<el-tab-pane label="Role" />
<el-tab-pane label="Task" />
</el-tabs> -->
<!-- <div style="text-align:center;margin-top:10px;font-weight:bold">完成率(%)</div> -->
<EchartClock />
</div>
</div>
</template>
<script setup lang="ts">
import * as NoticeApi from '@/api/system/notice'
import PanelGroupT from './PanelGroupT.vue'
import EchartClock from './components/echart/index.vue'
import { formatTime } from '@/utils'
import { useUserStore } from '@/store/modules/user'
import avatarImg from '@/assets/imgs/avatar.gif'
import ContractList from './components/contract/index.vue'
import ReceivablesList from './components/receivables/index.vue'
import InvoiceList from './components/invoice/index.vue'
import { ContractApi } from '@/api/crm/crmcontract'
const userStore = useUserStore()
const avatar = userStore.getUser.avatar ? userStore.getUser.avatar : avatarImg
const shopId = userStore.getUser.shopId
@ -173,17 +156,7 @@ const contractCheckCount = ref(0)
const receivablesCheckCount = ref(0)
const invoiceCheckCount = ref(0)
const getContractCount = (count) => {
contractCheckCount.value = count
}
const getReceivablesCount = (count) => {
receivablesCheckCount.value = count
}
const getInvoiceCount = (count) => {
invoiceCheckCount.value = count
}
/** 查询列表 */
const getData = async () => {

View File

@ -0,0 +1,254 @@
<template>
<div>
<div style="padding:20px">
<el-menu
:default-active="queryParams.type"
style="margin-bottom:10px"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item :index="2">我的业绩</el-menu-item>
<el-menu-item :index="3">部门业绩</el-menu-item>
</el-menu>
<el-row>
<el-col :span="14">
<el-tag type="primary">业绩概况-完成率(%)</el-tag>
</el-col>
<el-col :span="10" style="text-align:right"><el-tag type="success">合同目标{{countData.contractMoney}} 合同成交{{countData.contractSuccessMoney}}</el-tag><el-tag type="danger">{{countData.receivablesMoney}} {{countData.receivablesSuccessMoney}}</el-tag></el-col>
</el-row>
</div>
<div style=" width: 50%; margin-left: auto;margin-right: auto;">
<el-form :inline="true">
<el-form-item label="年度" prop="type">
<el-date-picker
v-model="queryParams.year"
type="year"
value-format="YYYY"
/>
</el-form-item>
<el-form-item label="月份" prop="type">
<el-select
v-model="queryParams.month"
placeholder="请选择"
clearable
class="!w-240px"
@change="selectMonth()"
>
<el-option label="全年" :value="0" />
<el-option label="一月" :value="1" />
<el-option label="二月" :value="2" />
<el-option label="三月" :value="3" />
<el-option label="四月" :value="4" />
<el-option label="五月" :value="5" />
<el-option label="六月" :value="6" />
<el-option label="七月" :value="7" />
<el-option label="八月" :value="8" />
<el-option label="九月" :value="9" />
<el-option label="十月" :value="10" />
<el-option label="十一月" :value="11" />
<el-option label="十二月" :value="12" />
</el-select>
</el-form-item>
</el-form>
</div>
<Echart :height="600" :options="lineOptionsData" />
</div>
</template>
<script setup lang="ts">
import { EChartsOption } from 'echarts'
import { clockOptions } from '@/views/Home/echarts-data'
import { formatDate } from '@/utils/formatTime'
import { AchievementApi } from '@/api/crm/crmachievement'
const lineOptionsData = reactive<EChartsOption>(clockOptions) as EChartsOption
const { t } = useI18n()
const queryParams = reactive({
year: formatDate(new Date(),'YYYY'),
month:0,
type:2
})
const countData = ref({})
//const activeIndex = ref(2)
const selectMonth = () => {
getData()
}
const handleSelect = (key) => {
queryParams.type = key
getData()
}
/** 查询列表 */
const getData = async () => {
countData.value = await AchievementApi.achievementCount(queryParams)
lineOptionsData.series[0].data[0].value = countData.value.contractPer
lineOptionsData.series[0].data[1].value = countData.value.receivablesPer
}
/** 初始化 **/
onMounted(() => {
getData()
})
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.acea-row {
display: -webkit-box;
display: -moz-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-lines: multiple;
-moz-box-lines: multiple;
-o-box-lines: multiple;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
/* 辅助类 */
}
/* 上下两边居中对齐 */
.acea-row.row-between-wrapper {
-webkit-box-align: center;
-moz-box-align: center;
-o-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: justify;
-moz-box-pack: justify;
-o-box-pack: justify;
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
}
.panel-group {
margin-top: 18px;
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: #fff;
box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05);
border-color: rgba(0, 0, 0, 0.05);
.icon-people {
color: #40c9c6;
}
.icon-message {
color: #36a3f7;
}
.icon-money {
color: #f4516c;
}
.icon-shopping {
color: #34bfa3;
}
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
padding: 16px;
transition: all 0.38s ease-out;
border-radius: 6px;
}
.card-panel-icon {
float: left;
font-size: 48px;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.card-panel-text {
line-height: 18px;
color: rgba(0, 0, 0, 0.45);
font-size: 16px;
margin-bottom: 12px;
}
.card-panel-num {
font-size: 20px;
}
}
}
}
@media (max-width: 550px) {
.card-panel-description {
display: none;
}
.card-panel-icon-wrapper {
float: none !important;
width: 100%;
height: 100%;
margin: 0 !important;
.svg-icon {
display: block;
margin: 14px auto !important;
float: none !important;
}
}
}
.baseInfo {
::v-deep .el-card__header {
padding: 10px 20px !important;
}
}
.ivu-mb {
margin-bottom: 10px;
}
.up,
.el-icon-caret-top {
color: #f5222d;
font-size: 12px;
opacity: 1 !important;
}
.down,
.el-icon-caret-bottom {
color: #39c15b;
font-size: 12px;
/*opacity: 100% !important;*/
}
.content {
&-number {
font-size: 24px;
}
&-time {
font-size: 14px;
/*color: #8C8C8C;*/
}
}
.spBlock {
display: block;
}
.el-divider--horizontal{
margin: 10px 0;
}
</style>

View File

@ -2,6 +2,88 @@ import { EChartsOption } from 'echarts'
const { t } = useI18n()
const gaugeData = [
{
value: 20,
name: '合同金额',
title: {
offsetCenter: ['0%', '-33%']
},
detail: {
valueAnimation: true,
offsetCenter: ['0%', '-20%']
}
},
{
value: 40,
name: '回款金额',
title: {
offsetCenter: ['0%', '-2%']
},
detail: {
valueAnimation: true,
offsetCenter: ['0%', '10%']
}
}
]
export const clockOptions: EChartsOption = {
series: [
{
type: 'gauge',
startAngle: 90,
endAngle: -270,
pointer: {
show: false
},
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {
borderWidth: 1,
borderColor: '#464646'
}
},
axisLine: {
lineStyle: {
width: 40
}
},
splitLine: {
show: false,
distance: 0,
length: 10
},
axisTick: {
show: false
},
axisLabel: {
show: false,
distance: 50
},
data: gaugeData,
title: {
fontSize: 14,
},
detail: {
width: 50,
height: 14,
fontSize: 14,
color: 'inherit',
borderColor: 'inherit',
borderRadius: 20,
borderWidth: 1,
formatter: '{value}%'
}
}
]
}
export const lineOptions: EChartsOption = {
title: {
text: t('analysis.monthlySales'),

251
src/views/Home/wait.vue Normal file
View File

@ -0,0 +1,251 @@
<template>
<div>
<!-- <PanelGroupT /> -->
<div class="divBox" style="background-color:#ffffff">
<el-tabs
v-model="activeName"
type="card"
class="demo-tabs"
@tab-click="handleClick"
>
<el-tab-pane name="first">
<template #label>
<span><el-badge :value="contractCheckCount" :hidden="contractCheckCount == 0">合同审批</el-badge></span>
</template>
<ContractList @get-contract-count="getContractCount" />
</el-tab-pane>
<el-tab-pane name="second">
<template #label>
<span><el-badge :value="receivablesCheckCount" :hidden="receivablesCheckCount == 0">回款审批</el-badge></span>
</template>
<ReceivablesList @get-receivables-count="getReceivablesCount" />
</el-tab-pane>
<el-tab-pane name="third">
<template #label>
<span><el-badge :value="invoiceCheckCount" :hidden="invoiceCheckCount == 0">发票审批</el-badge></span>
</template>
<InvoiceList @get-invoice-count="getInvoiceCount" />
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import * as NoticeApi from '@/api/system/notice'
import PanelGroupT from './PanelGroupT.vue'
import { formatTime } from '@/utils'
import { useUserStore } from '@/store/modules/user'
import avatarImg from '@/assets/imgs/avatar.gif'
import ContractList from './components/contract/index.vue'
import ReceivablesList from './components/receivables/index.vue'
import InvoiceList from './components/invoice/index.vue'
import { ContractApi } from '@/api/crm/crmcontract'
const userStore = useUserStore()
const avatar = userStore.getUser.avatar ? userStore.getUser.avatar : avatarImg
const shopId = userStore.getUser.shopId
const countName = ref('全门店')
const { t } = useI18n()
const count = ref({
followCustomerCount: 0,
followBusinessCount: 0,
followCluesCount: 0,
contractDueCount: 0,
customerDueCount: 0,
contractReturnCount: 0,
myInvoiceCount: 0,
productCount: 0,
})
const loading = ref(true)
const notice = ref([])
const activeName = ref('first')
const contractCheckCount = ref(0)
const receivablesCheckCount = ref(0)
const invoiceCheckCount = ref(0)
const getContractCount = (count) => {
contractCheckCount.value = count
}
const getReceivablesCount = (count) => {
receivablesCheckCount.value = count
}
const getInvoiceCount = (count) => {
invoiceCheckCount.value = count
}
/** 查询列表 */
const getData = async () => {
try {
const data = await ContractApi.getIndexCount()
count.value = data
} finally {
}
}
/** 初始化 **/
onMounted(() => {
getData()
loading.value = false
})
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.acea-row {
display: -webkit-box;
display: -moz-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-lines: multiple;
-moz-box-lines: multiple;
-o-box-lines: multiple;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
/* 辅助类 */
}
/* 上下两边居中对齐 */
.acea-row.row-between-wrapper {
-webkit-box-align: center;
-moz-box-align: center;
-o-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: justify;
-moz-box-pack: justify;
-o-box-pack: justify;
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
}
.panel-group {
margin-top: 18px;
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: #fff;
box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05);
border-color: rgba(0, 0, 0, 0.05);
.icon-people {
color: #40c9c6;
}
.icon-message {
color: #36a3f7;
}
.icon-money {
color: #f4516c;
}
.icon-shopping {
color: #34bfa3;
}
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
padding: 16px;
transition: all 0.38s ease-out;
border-radius: 6px;
}
.card-panel-icon {
float: left;
font-size: 48px;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.card-panel-text {
line-height: 18px;
color: rgba(0, 0, 0, 0.45);
font-size: 16px;
margin-bottom: 12px;
}
.card-panel-num {
font-size: 20px;
}
}
}
}
@media (max-width: 550px) {
.card-panel-description {
display: none;
}
.card-panel-icon-wrapper {
float: none !important;
width: 100%;
height: 100%;
margin: 0 !important;
.svg-icon {
display: block;
margin: 14px auto !important;
float: none !important;
}
}
}
.baseInfo {
::v-deep .el-card__header {
padding: 10px 20px !important;
}
}
.ivu-mb {
margin-bottom: 10px;
}
.up,
.el-icon-caret-top {
color: #f5222d;
font-size: 12px;
opacity: 1 !important;
}
.down,
.el-icon-caret-bottom {
color: #39c15b;
font-size: 12px;
/*opacity: 100% !important;*/
}
.content {
&-number {
font-size: 24px;
}
&-time {
font-size: 14px;
/*color: #8C8C8C;*/
}
}
.spBlock {
display: block;
}
.el-divider--horizontal{
margin: 10px 0;
}
</style>

View File

@ -0,0 +1,205 @@
<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="deptId">
<el-tree-select
v-model="formData.deptId"
:data="deptList"
:props="defaultProps"
check-strictly
node-key="id"
placeholder="请选择归属部门,不选择表示全部"
/>
</el-form-item>
<el-form-item label="业绩方式" prop="config">
<el-select
v-model="formData.config"
placeholder="请选择"
>
<el-option label="合同金额" :value="1" />
<el-option label="回款金额" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="年份" prop="year">
<el-date-picker
v-model="formData.year"
type="year"
value-format="YYYY"
/>
</el-form-item>
<el-form-item label="年目标" prop="yeartarget">
<el-input v-model="formData.yeartarget" placeholder="请输入年目标">
<template #append><el-button type="primary" @click="averrage()">平均分配</el-button></template>
</el-input>
</el-form-item>
<el-form-item label="一月" prop="january">
<el-input-number style="width:100%" controls-position="right" v-model="formData.january" placeholder="请输入一月" />
</el-form-item>
<el-form-item label="二月" prop="february">
<el-input-number style="width:100%" controls-position="right" v-model="formData.february" placeholder="请输入二月" />
</el-form-item>
<el-form-item label="三月" prop="march">
<el-input-number style="width:100%" controls-position="right" v-model="formData.march" placeholder="请输入三月" />
</el-form-item>
<el-form-item label="四月" prop="april">
<el-input-number style="width:100%" controls-position="right" v-model="formData.april" placeholder="请输入四月" />
</el-form-item>
<el-form-item label="五月" prop="may">
<el-input-number style="width:100%" controls-position="right" v-model="formData.may" placeholder="请输入五月" />
</el-form-item>
<el-form-item label="六月" prop="june">
<el-input-number style="width:100%" controls-position="right" v-model="formData.june" placeholder="请输入六月" />
</el-form-item>
<el-form-item label="七月" prop="july">
<el-input-number style="width:100%" controls-position="right" v-model="formData.july" placeholder="请输入七月" />
</el-form-item>
<el-form-item label="八月" prop="august">
<el-input-number style="width:100%" controls-position="right" v-model="formData.august" placeholder="请输入八月" />
</el-form-item>
<el-form-item label="九月" prop="september">
<el-input-number style="width:100%" controls-position="right" v-model="formData.september" placeholder="请输入九月" />
</el-form-item>
<el-form-item label="十月" prop="october">
<el-input-number style="width:100%" controls-position="right" v-model="formData.october" placeholder="请输入十月" />
</el-form-item>
<el-form-item label="十一月" prop="november">
<el-input-number style="width:100%" controls-position="right" v-model="formData.november" placeholder="请输入十一月" />
</el-form-item>
<el-form-item label="十二月" prop="december">
<el-input-number style="width:100%" controls-position="right" v-model="formData.december" 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 { AchievementApi, AchievementVO } from '@/api/crm/crmachievement'
import { formatDate } from '@/utils/formatTime'
import * as DeptApi from '@/api/system/dept'
import { defaultProps, handleTree } from '@/utils/tree'
/** 业绩目标 表单 */
defineOptions({ name: 'AchievementForm' })
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,
config: undefined,
type: 3,
typeId: undefined,
year: undefined,
january: undefined,
february: undefined,
march: undefined,
april: undefined,
may: undefined,
june: undefined,
july: undefined,
august: undefined,
september: undefined,
october: undefined,
november: undefined,
december: undefined,
yeartarget: undefined
})
const formRules = reactive({
})
const deptList = ref([])
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = '团队业绩批量设置'
formType.value = type
resetForm()
deptList.value = handleTree(await DeptApi.getSimpleDeptList())
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
//const achievementRespVO = formData.value
const data = {id:formData.value.deptId ? formData.value.deptId : 0,name:'',achievementRespVO:formData.value}
console.log('data:',data)
if (formType.value === 'create') {
await AchievementApi.createAchievement(data)
message.success(t('common.createSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
const averrage = () => {
let res = formData.value.yeartarget / 12
let num = Math.round(res*100) / 100
formData.value.january = num
formData.value.february = num
formData.value.march = num
formData.value.april = num
formData.value.may = num
formData.value.june = num
formData.value.july = num
formData.value.august = num
formData.value.september = num
formData.value.october = num
formData.value.november = num
formData.value.december = num
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
config: 1,
type: 3,
typeId: undefined,
year: formatDate(new Date(),'YYYY'),
january: 0,
february: 0,
march: 0,
april: 0,
may: 0,
june: 0,
july: 0,
august: 0,
september: 0,
october: 0,
november: 0,
december: 0,
yeartarget: 0
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,214 @@
<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="deptId">
<!-- <el-tree-select
v-model="formData.deptId"
:data="deptList"
:props="defaultProps"
check-strictly
node-key="id"
placeholder="请选择归属部门,不选择表示全部"
/> -->
<el-select v-model="formData.deptId" clearable placeholder="请选择员工,不选择表示全部">
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="业绩方式" prop="config">
<el-select
v-model="formData.config"
placeholder="请选择"
>
<el-option label="合同金额" :value="1" />
<el-option label="回款金额" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="年份" prop="year">
<el-date-picker
v-model="formData.year"
type="year"
value-format="YYYY"
/>
</el-form-item>
<el-form-item label="年目标" prop="yeartarget">
<el-input v-model="formData.yeartarget" placeholder="请输入年目标">
<template #append><el-button type="primary" @click="averrage()">平均分配</el-button></template>
</el-input>
</el-form-item>
<el-form-item label="一月" prop="january">
<el-input-number style="width:100%" controls-position="right" v-model="formData.january" placeholder="请输入一月" />
</el-form-item>
<el-form-item label="二月" prop="february">
<el-input-number style="width:100%" controls-position="right" v-model="formData.february" placeholder="请输入二月" />
</el-form-item>
<el-form-item label="三月" prop="march">
<el-input-number style="width:100%" controls-position="right" v-model="formData.march" placeholder="请输入三月" />
</el-form-item>
<el-form-item label="四月" prop="april">
<el-input-number style="width:100%" controls-position="right" v-model="formData.april" placeholder="请输入四月" />
</el-form-item>
<el-form-item label="五月" prop="may">
<el-input-number style="width:100%" controls-position="right" v-model="formData.may" placeholder="请输入五月" />
</el-form-item>
<el-form-item label="六月" prop="june">
<el-input-number style="width:100%" controls-position="right" v-model="formData.june" placeholder="请输入六月" />
</el-form-item>
<el-form-item label="七月" prop="july">
<el-input-number style="width:100%" controls-position="right" v-model="formData.july" placeholder="请输入七月" />
</el-form-item>
<el-form-item label="八月" prop="august">
<el-input-number style="width:100%" controls-position="right" v-model="formData.august" placeholder="请输入八月" />
</el-form-item>
<el-form-item label="九月" prop="september">
<el-input-number style="width:100%" controls-position="right" v-model="formData.september" placeholder="请输入九月" />
</el-form-item>
<el-form-item label="十月" prop="october">
<el-input-number style="width:100%" controls-position="right" v-model="formData.october" placeholder="请输入十月" />
</el-form-item>
<el-form-item label="十一月" prop="november">
<el-input-number style="width:100%" controls-position="right" v-model="formData.november" placeholder="请输入十一月" />
</el-form-item>
<el-form-item label="十二月" prop="december">
<el-input-number style="width:100%" controls-position="right" v-model="formData.december" 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 { AchievementApi, AchievementVO } from '@/api/crm/crmachievement'
import { formatDate } from '@/utils/formatTime'
import * as DeptApi from '@/api/system/dept'
import * as UserApi from '@/api/system/user'
import { defaultProps, handleTree } from '@/utils/tree'
/** 业绩目标 表单 */
defineOptions({ name: 'AchievementForm' })
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,
config: undefined,
type: 3,
typeId: undefined,
year: undefined,
january: undefined,
february: undefined,
march: undefined,
april: undefined,
may: undefined,
june: undefined,
july: undefined,
august: undefined,
september: undefined,
october: undefined,
november: undefined,
december: undefined,
yeartarget: undefined
})
const formRules = reactive({
})
const userList = ref([])
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = '成员业绩批量设置'
formType.value = type
resetForm()
userList.value = await UserApi.getSimpleUserList()
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
//const achievementRespVO = formData.value
const data = {id:formData.value.deptId ? formData.value.deptId : 0,name:'',achievementRespVO:formData.value}
console.log('data:',data)
if (formType.value === 'create') {
await AchievementApi.createAchievement(data)
message.success(t('common.createSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
const averrage = () => {
let res = formData.value.yeartarget / 12
let num = Math.round(res*100) / 100
formData.value.january = num
formData.value.february = num
formData.value.march = num
formData.value.april = num
formData.value.may = num
formData.value.june = num
formData.value.july = num
formData.value.august = num
formData.value.september = num
formData.value.october = num
formData.value.november = num
formData.value.december = num
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
config: 1,
type: 2,
typeId: undefined,
year: formatDate(new Date(),'YYYY'),
january: 0,
february: 0,
march: 0,
april: 0,
may: 0,
june: 0,
july: 0,
august: 0,
september: 0,
october: 0,
november: 0,
december: 0,
yeartarget: 0
}
formRef.value?.resetFields()
}
</script>

File diff suppressed because it is too large Load Diff