|
@@ -0,0 +1,202 @@
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, onMounted, watch, reactive } from "vue";
|
|
|
+import {
|
|
|
+ type RequestProps,
|
|
|
+ getOverallData,
|
|
|
+ exportFile,
|
|
|
+ dateCollections
|
|
|
+} from './api';
|
|
|
+import { downloadFile } from '@/utils/tools';
|
|
|
+import { dealWithTranslation } from '@/utils/translationProcessing';
|
|
|
+import personnelSearch from '@/components/translationComponent/personnelSearch/personnelSearch.vue';
|
|
|
+import treeSelect from '@/components/translationComponent/treeSelect/treeSelect.vue';
|
|
|
+import Echarts from '@/components/ReEcharts/index.vue';
|
|
|
+import { EChartsOption } from 'echarts';
|
|
|
+import { useStore } from '@/store/index';
|
|
|
+import { storeToRefs } from 'pinia';
|
|
|
+
|
|
|
+const { userInfo } = storeToRefs(useStore());
|
|
|
+const isLoading = ref(false);
|
|
|
+const dataSource = ref([]);
|
|
|
+const form = reactive({ type: 1, date: undefined, member: '' });
|
|
|
+const chartOptions: EChartsOption = reactive({
|
|
|
+ grid: { bottom: 30 },
|
|
|
+ legend: {},
|
|
|
+ tooltip: {},
|
|
|
+ toolbox: {
|
|
|
+ show: true,
|
|
|
+ feature: {
|
|
|
+ magicType: {
|
|
|
+ show: true,
|
|
|
+ type: ['line', 'bar'] // 允许切换的图表类型
|
|
|
+ },
|
|
|
+ restore: { show: true } // 还原按钮
|
|
|
+ }
|
|
|
+ },
|
|
|
+ dataset: {
|
|
|
+ dimensions: [],
|
|
|
+ source: []
|
|
|
+ },
|
|
|
+ xAxis: { type: 'category' },
|
|
|
+ yAxis: {},
|
|
|
+ series: []
|
|
|
+});
|
|
|
+
|
|
|
+const dateOptions = [
|
|
|
+ { label: '今天', value: '1' },
|
|
|
+ { label: '昨天', value: '2' },
|
|
|
+ { label: '本周', value: '3' },
|
|
|
+ { label: '上周', value: '4' },
|
|
|
+ { label: '本月', value: '5' },
|
|
|
+ { label: '上月', value: '6' },
|
|
|
+ { label: '本季度', value: '7' },
|
|
|
+ { label: '上季度', value: '8' }
|
|
|
+];
|
|
|
+const exportLoading = ref(false);
|
|
|
+const seachLoading = ref(false);
|
|
|
+
|
|
|
+const onSubmit = async (isExport?: boolean) => {
|
|
|
+ const payload = {
|
|
|
+ startDate: form.date && dateCollections[form.date - 1].start_time,
|
|
|
+ endDate: form.date && dateCollections[form.date - 1].end_time,
|
|
|
+ exportType: form.type,
|
|
|
+ userId: form.type === 1 ? form.member : undefined,
|
|
|
+ departmentId: form.type === 1 ? undefined : form.member
|
|
|
+ } as RequestProps;
|
|
|
+
|
|
|
+ if (isExport) {
|
|
|
+ exportLoading.value = true;
|
|
|
+ const { data } = await exportFile(payload, 0);
|
|
|
+ await downloadFile(data, data?.split('/')?.[2] || '客户表');
|
|
|
+ exportLoading.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ queryOverall(payload);
|
|
|
+};
|
|
|
+
|
|
|
+const queryOverall = async (payload?: RequestProps) => {
|
|
|
+ isLoading.value = true;
|
|
|
+ seachLoading.value = true
|
|
|
+ const { data = [] } = await getOverallData(payload);
|
|
|
+ isLoading.value = false;
|
|
|
+ dataSource.value = data.map((d: any) => ({
|
|
|
+ dealRate: d.dealRate * 100,
|
|
|
+ customerDeal: d.customerDeal,
|
|
|
+ customertotal: d.customertotal,
|
|
|
+ name: form.type === 1 ? d.name : d.departmentName
|
|
|
+ }));
|
|
|
+ seachLoading.value = false
|
|
|
+
|
|
|
+ const sourceData = data.map((d: any) => {
|
|
|
+ const base = {
|
|
|
+ name: form.type === 1 ? d.name : d.departmentName,
|
|
|
+ ['成交客户数']: d.customerDeal,
|
|
|
+ ['新增客户数']: d.customertotal
|
|
|
+ };
|
|
|
+
|
|
|
+ if (form.type === 0) {
|
|
|
+ base['客户总数'] = d.earlierCusTotal;
|
|
|
+ }
|
|
|
+
|
|
|
+ return base;
|
|
|
+ });
|
|
|
+
|
|
|
+ const sourceDataTypes = sourceData.map((item: any) => ({
|
|
|
+ type: form.type === 1 ? 'userName' : 'departmentName',
|
|
|
+ id: item.name
|
|
|
+ }));
|
|
|
+
|
|
|
+ chartOptions.series = [
|
|
|
+ { type: 'bar', barWidth: 40, color: '#ffba6d' },
|
|
|
+ { type: 'bar', barWidth: 40, color: '#3f95c2' }
|
|
|
+ ];
|
|
|
+
|
|
|
+ if (form.type === 0) {
|
|
|
+ chartOptions.series.push({ type: 'bar', barWidth: 40, color: '#6dc8e1' }); // 只有按部门时才显示客户总数的柱状图
|
|
|
+ }
|
|
|
+
|
|
|
+ if (userInfo && userInfo.value.userNameNeedTranslate == 1) {
|
|
|
+ dealWithTranslation(sourceDataTypes, sourceData).then((res: any) => {
|
|
|
+ chartOptions.dataset.dimensions = ['name', '成交客户数', '新增客户数'];
|
|
|
+ if (form.type === 0) {
|
|
|
+ chartOptions.dataset.dimensions.push('客户总数'); // 只有按部门时才加入
|
|
|
+ }
|
|
|
+ chartOptions.dataset.source = res;
|
|
|
+ chartOptions.legend = {};
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ chartOptions.dataset.dimensions = ['name', '成交客户数', '新增客户数'];
|
|
|
+ if (form.type === 0) {
|
|
|
+ chartOptions.dataset.dimensions.push('客户总数');
|
|
|
+ }
|
|
|
+ chartOptions.dataset.source = sourceData;
|
|
|
+ chartOptions.legend = {};
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ onSubmit(false);
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="w-full h-full p-5 bg-white flex flex-col">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <div class="flex items-center mr-8">
|
|
|
+ <div class="mr-3 text-[14px]">时间</div>
|
|
|
+ <el-select clearable v-model="form.date" style="width: 112px">
|
|
|
+ <el-option v-for="date in dateOptions" :key="date.value" :label="date.label" :value="date.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex items-center mr-8">
|
|
|
+ <div class="mr-3 text-[14px]">分类</div>
|
|
|
+ <el-select v-model="form.type" @change="form.member = ''" style="width: 112px">
|
|
|
+ <el-option label="按部门" :value="0" />
|
|
|
+ <el-option label="按员工" :value="1" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex items-center mr-8">
|
|
|
+ <div class="mr-3 text-[14px]">{{ form.type == 1 ? '员工' : '部门' }}</div>
|
|
|
+ <template v-if="form.type == 1">
|
|
|
+ <personnel-search v-model="form.member" :size="''" placeholder="选择员工" width="240px"></personnel-search>
|
|
|
+ </template>
|
|
|
+ <template v-if="form.type == 0">
|
|
|
+ <tree-select v-model="form.member" :size="''" checkStrictly placeholder="选择部门" width="240px"></tree-select>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex items-center mr-8">
|
|
|
+ <el-button type="primary" @click="onSubmit(false)" :loading="seachLoading">搜索</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button type="primary" @click="onSubmit(true)" :loading="exportLoading">导出</el-button>
|
|
|
+ </div>
|
|
|
+ <div class="flex-1 py-4">
|
|
|
+ <Echarts :option="chartOptions"></Echarts>
|
|
|
+ </div>
|
|
|
+ <div class="h-[40vh]">
|
|
|
+ <el-table :data="dataSource" style="height: 100%" v-loading="seachLoading">
|
|
|
+ <el-table-column prop="name" label="名称" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <TextTranslation translationTypes="userName" :translationValue="scope.row.name"></TextTranslation>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="customertotal" label="新增客户数" align="center" />
|
|
|
+ <el-table-column prop="customerDeal" label="成交客户数" align="center" />
|
|
|
+ <el-table-column prop="dealRate" label="客户成交率(%)" align="center" >
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row?.dealRate.toFixed(0) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+</style>
|