V1.1.1 业绩功能
This commit is contained in:
parent
845d5f3240
commit
093e81ca31
61
src/api/crm/crmachievement/index.ts
Normal file
61
src/api/crm/crmachievement/index.ts
Normal 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 })
|
||||
}
|
||||
}
|
@ -152,7 +152,7 @@ export default {
|
||||
router: {
|
||||
login: '登录',
|
||||
socialLogin: '社交登录',
|
||||
home: '待办事项',
|
||||
home: '控制台',
|
||||
analysis: '分析页',
|
||||
workplace: '工作台'
|
||||
},
|
||||
|
@ -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 () => {
|
||||
|
254
src/views/Home/components/echart/index.vue
Normal file
254
src/views/Home/components/echart/index.vue
Normal 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>
|
@ -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
251
src/views/Home/wait.vue
Normal 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>
|
205
src/views/crm/crmachievement/AchievementForm.vue
Normal file
205
src/views/crm/crmachievement/AchievementForm.vue
Normal 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) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
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>
|
214
src/views/crm/crmachievement/AchievementForm2.vue
Normal file
214
src/views/crm/crmachievement/AchievementForm2.vue
Normal 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) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
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>
|
1021
src/views/crm/crmachievement/index.vue
Normal file
1021
src/views/crm/crmachievement/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user