-
+
+
+
+
+
+
+
+
@@ -117,7 +123,9 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { beginOfDay, defaultShortcuts, endOfDay, formatDate } from '@/utils/formatTime'
import { defaultProps, handleTree } from '@/utils/tree'
import CustomerConversionStat from './components/CustomerConversionStat.vue'
-import CustomerDealCycle from './components/CustomerDealCycle.vue'
+import CustomerDealCycleByUser from './components/CustomerDealCycleByUser.vue'
+import CustomerDealCycleByArea from './components/CustomerDealCycleByArea.vue'
+import CustomerDealCycleByProduct from './components/CustomerDealCycleByProduct.vue'
import CustomerFollowUpSummary from './components/CustomerFollowUpSummary.vue'
import CustomerFollowUpType from './components/CustomerFollowUpType.vue'
import CustomerSummary from './components/CustomerSummary.vue'
@@ -153,7 +161,9 @@ const followUpSummaryRef = ref() // 2. 客户跟进次数分析
const followUpTypeRef = ref() // 3. 客户跟进方式分析
const conversionStatRef = ref() // 4. 客户转化率分析
const customerPoolSummaryRef = ref() // 5. 客户公海分析
-const dealCycleRef = ref() // 6. 成交周期分析
+const dealCycleByUserRef = ref() // 6. 成交周期分析(按员工)
+const dealCycleByAreaRef = ref() // 7. 成交周期分析(按地区)
+const dealCycleByProductRef = ref() // 8. 成交周期分析(按产品)
/** 搜索按钮操作 */
const handleQuery = () => {
@@ -173,8 +183,14 @@ const handleQuery = () => {
case 'poolSummary': // 公海客户分析
customerPoolSummaryRef.value?.loadData?.()
break
- case 'dealCycle': // 成交周期分析
- dealCycleRef.value?.loadData?.()
+ case 'dealCycleByUser': // 成交周期分析
+ dealCycleByUserRef.value?.loadData?.()
+ break
+ case 'dealCycleByArea': // 成交周期分析
+ dealCycleByAreaRef.value?.loadData?.()
+ break
+ case 'dealCycleByProduct': // 成交周期分析
+ dealCycleByProductRef.value?.loadData?.()
break
}
}
diff --git a/src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue b/src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue
new file mode 100644
index 00000000..541d6fc4
--- /dev/null
+++ b/src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue
@@ -0,0 +1,307 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.name }}
+
+
+
+
+
+
+ {{ scope.row.customerName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/crm/statistics/funnel/components/BusinessSummary.vue b/src/views/crm/statistics/funnel/components/BusinessSummary.vue
new file mode 100644
index 00000000..942a7128
--- /dev/null
+++ b/src/views/crm/statistics/funnel/components/BusinessSummary.vue
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.name }}
+
+
+
+
+
+
+ {{ scope.row.customerName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/crm/statistics/funnel/components/FunnelBusiness.vue b/src/views/crm/statistics/funnel/components/FunnelBusiness.vue
new file mode 100644
index 00000000..9b7b08ae
--- /dev/null
+++ b/src/views/crm/statistics/funnel/components/FunnelBusiness.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+ 客户视角
+ 动态视角
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/crm/statistics/funnel/index.vue b/src/views/crm/statistics/funnel/index.vue
new file mode 100644
index 00000000..804cb49b
--- /dev/null
+++ b/src/views/crm/statistics/funnel/index.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/crm/statistics/portrait/components/CustomerAddress.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue
similarity index 86%
rename from src/views/crm/statistics/portrait/components/CustomerAddress.vue
rename to src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue
index f31c7963..513936c9 100644
--- a/src/views/crm/statistics/portrait/components/CustomerAddress.vue
+++ b/src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue
@@ -24,9 +24,9 @@ import {
CrmStatisticCustomerAreaRespVO,
StatisticsPortraitApi
} from '@/api/crm/statistics/portrait'
+import { areaReplace } from '@/utils'
-// TODO @puhui999:address 换成 area 会更合适哈,
-defineOptions({ name: 'CustomerAddress' })
+defineOptions({ name: 'PortraitCustomerArea' })
const props = defineProps<{ queryParams: any }>() // 搜索参数
// 注册地图
@@ -107,22 +107,16 @@ const loadData = async () => {
areaStatisticsList.value = areaList.map((item: CrmStatisticCustomerAreaRespVO) => {
return {
...item,
- areaName: item.areaName // TODO @puhui999:这里最好注释下原因哈
- .replace('维吾尔自治区', '')
- .replace('壮族自治区', '')
- .replace('回族自治区', '')
- .replace('自治区', '')
- .replace('省', '')
+ areaName: areaReplace(item.areaName)
}
})
- builderLeftMap()
- builderRightMap()
+ buildLeftMap()
+ buildRightMap()
loading.value = false
}
defineExpose({ loadData })
-// TODO @puhui999:builder 改成 build 更合理哈
-const builderLeftMap = () => {
+const buildLeftMap = () => {
let min = 0
let max = 0
echartsOption.series![0].data = areaStatisticsList.value.map((item) => {
@@ -134,7 +128,7 @@ const builderLeftMap = () => {
echartsOption.visualMap!['max'] = max
}
-const builderRightMap = () => {
+const buildRightMap = () => {
let min = 0
let max = 0
echartsOption2.series![0].data = areaStatisticsList.value.map((item) => {
diff --git a/src/views/crm/statistics/portrait/components/CustomerIndustry.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue
similarity index 94%
rename from src/views/crm/statistics/portrait/components/CustomerIndustry.vue
rename to src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue
index d1f3c173..d4269932 100644
--- a/src/views/crm/statistics/portrait/components/CustomerIndustry.vue
+++ b/src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue
@@ -39,10 +39,10 @@ import {
} from '@/api/crm/statistics/portrait'
import { EChartsOption } from 'echarts'
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
-import { getSumValue } from '@/utils'
+import { erpCalculatePercentage, getSumValue } from '@/utils'
import { isEmpty } from '@/utils/is'
-defineOptions({ name: 'CustomerIndustry' })
+defineOptions({ name: 'PortraitCustomerIndustry' })
const props = defineProps<{ queryParams: any }>() // 搜索参数
const loading = ref(false) // 加载中
@@ -185,8 +185,9 @@ const calculateProportion = (sourceList: CrmStatisticCustomerIndustryRespVO[]) =
const sumDealCount = getSumValue(list.map((item) => item.dealCount))
list.forEach((item) => {
item.industryPortion =
- item.customerCount === 0 ? 0 : ((item.customerCount / sumCustomerCount) * 100).toFixed(2)
- item.dealPortion = item.dealCount === 0 ? 0 : ((item.dealCount / sumDealCount) * 100).toFixed(2)
+ item.customerCount === 0 ? 0 : erpCalculatePercentage(item.customerCount, sumCustomerCount)
+ item.dealPortion =
+ item.dealCount === 0 ? 0 : erpCalculatePercentage(item.dealCount, sumDealCount)
})
}
diff --git a/src/views/crm/statistics/portrait/components/CustomerLevel.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue
similarity index 93%
rename from src/views/crm/statistics/portrait/components/CustomerLevel.vue
rename to src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue
index 2f81c0fc..653feef8 100644
--- a/src/views/crm/statistics/portrait/components/CustomerLevel.vue
+++ b/src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue
@@ -39,10 +39,10 @@ import {
} from '@/api/crm/statistics/portrait'
import { EChartsOption } from 'echarts'
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
-import { getSumValue } from '@/utils'
+import { erpCalculatePercentage, getSumValue } from '@/utils'
import { isEmpty } from '@/utils/is'
-defineOptions({ name: 'CustomerSource' })
+defineOptions({ name: 'PortraitCustomerLevel' })
const props = defineProps<{ queryParams: any }>() // 搜索参数
const loading = ref(false) // 加载中
@@ -184,10 +184,10 @@ const calculateProportion = (levelList: CrmStatisticCustomerLevelRespVO[]) => {
const sumCustomerCount = getSumValue(list.map((item) => item.customerCount))
const sumDealCount = getSumValue(list.map((item) => item.dealCount))
list.forEach((item) => {
- // TODO @puhui999:可以使用 erpCalculatePercentage 方法
item.levelPortion =
- item.customerCount === 0 ? 0 : ((item.customerCount / sumCustomerCount) * 100).toFixed(2)
- item.dealPortion = item.dealCount === 0 ? 0 : ((item.dealCount / sumDealCount) * 100).toFixed(2)
+ item.customerCount === 0 ? 0 : erpCalculatePercentage(item.customerCount, sumCustomerCount)
+ item.dealPortion =
+ item.dealCount === 0 ? 0 : erpCalculatePercentage(item.dealCount, sumDealCount)
})
}
diff --git a/src/views/crm/statistics/portrait/components/CustomerSource.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue
similarity index 94%
rename from src/views/crm/statistics/portrait/components/CustomerSource.vue
rename to src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue
index af1708fc..ade6445d 100644
--- a/src/views/crm/statistics/portrait/components/CustomerSource.vue
+++ b/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue
@@ -40,9 +40,9 @@ import {
import { EChartsOption } from 'echarts'
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
import { isEmpty } from '@/utils/is'
-import { getSumValue } from '@/utils'
+import { erpCalculatePercentage, getSumValue } from '@/utils'
-defineOptions({ name: 'CustomerSource' })
+defineOptions({ name: 'PortraitCustomerSource' })
const props = defineProps<{ queryParams: any }>() // 搜索参数
const loading = ref(false) // 加载中
@@ -185,8 +185,9 @@ const calculateProportion = (sourceList: CrmStatisticCustomerSourceRespVO[]) =>
const sumDealCount = getSumValue(list.map((item) => item.dealCount))
list.forEach((item) => {
item.sourcePortion =
- item.customerCount === 0 ? 0 : ((item.customerCount / sumCustomerCount) * 100).toFixed(2)
- item.dealPortion = item.dealCount === 0 ? 0 : ((item.dealCount / sumDealCount) * 100).toFixed(2)
+ item.customerCount === 0 ? 0 : erpCalculatePercentage(item.customerCount, sumCustomerCount)
+ item.dealPortion =
+ item.dealCount === 0 ? 0 : erpCalculatePercentage(item.dealCount, sumDealCount)
})
}
diff --git a/src/views/crm/statistics/portrait/index.vue b/src/views/crm/statistics/portrait/index.vue
index 88793837..71807e17 100644
--- a/src/views/crm/statistics/portrait/index.vue
+++ b/src/views/crm/statistics/portrait/index.vue
@@ -60,20 +60,20 @@
-
-
+
+
-
+
-
+
-
+
@@ -85,11 +85,10 @@ import * as UserApi from '@/api/system/user'
import { useUserStore } from '@/store/modules/user'
import { beginOfDay, defaultShortcuts, endOfDay, formatDate } from '@/utils/formatTime'
import { defaultProps, handleTree } from '@/utils/tree'
-// TODO @puhui999:最好命名带上模块名,如:CrmStatisticsPortrait
-import CustomerAddress from './components/CustomerAddress.vue'
-import CustomerIndustry from './components/CustomerIndustry.vue'
-import CustomerSource from './components/CustomerSource.vue'
-import CustomerLevel from './components/CustomerLevel.vue'
+import PortraitCustomerArea from './components/PortraitCustomerArea.vue'
+import PortraitCustomerIndustry from './components/PortraitCustomerIndustry.vue'
+import PortraitCustomerSource from './components/PortraitCustomerSource.vue'
+import PortraitCustomerLevel from './components/PortraitCustomerLevel.vue'
defineOptions({ name: 'CrmStatisticsPortrait' })
@@ -114,8 +113,8 @@ const userListByDeptId = computed(() =>
: []
)
-const activeTab = ref('addressRef') // 活跃标签
-const addressRef = ref() // 客户地区分布
+const activeTab = ref('areaRef') // 活跃标签
+const areaRef = ref() // 客户地区分布
const levelRef = ref() // 客户级别
const sourceRef = ref() // 客户来源
const industryRef = ref() // 客户行业
@@ -123,8 +122,8 @@ const industryRef = ref() // 客户行业
/** 搜索按钮操作 */
const handleQuery = () => {
switch (activeTab.value) {
- case 'addressRef':
- addressRef.value?.loadData?.()
+ case 'areaRef':
+ areaRef.value?.loadData?.()
break
case 'levelRef':
levelRef.value?.loadData?.()
diff --git a/src/views/infra/apiAccessLog/index.vue b/src/views/infra/apiAccessLog/index.vue
index 45110c41..570f579e 100644
--- a/src/views/infra/apiAccessLog/index.vue
+++ b/src/views/infra/apiAccessLog/index.vue
@@ -80,7 +80,7 @@
plain
@click="handleExport"
:loading="exportLoading"
- v-hasPermi="['infra:api-error-log:export']"
+ v-hasPermi="['infra:api-access-log:export']"
>
导出
diff --git a/src/views/infra/file/index.vue b/src/views/infra/file/index.vue
index 17967312..2ff33641 100644
--- a/src/views/infra/file/index.vue
+++ b/src/views/infra/file/index.vue
@@ -96,7 +96,7 @@
link
type="danger"
@click="handleDelete(scope.row.id)"
- v-hasPermi="['infra:config:delete']"
+ v-hasPermi="['infra:file:delete']"
>
删除
diff --git a/src/views/infra/fileConfig/index.vue b/src/views/infra/fileConfig/index.vue
index 3e8f38fb..a9c001a9 100644
--- a/src/views/infra/fileConfig/index.vue
+++ b/src/views/infra/fileConfig/index.vue
@@ -107,7 +107,7 @@
link
type="danger"
@click="handleDelete(scope.row.id)"
- v-hasPermi="['infra:config:delete']"
+ v-hasPermi="['infra:file-config:delete']"
>
删除
diff --git a/src/views/mall/statistics/member/index.vue b/src/views/mall/statistics/member/index.vue
index a075810d..0e1bbaf6 100644
--- a/src/views/mall/statistics/member/index.vue
+++ b/src/views/mall/statistics/member/index.vue
@@ -3,44 +3,44 @@
-
+
-
+
-
+
-
+
@@ -67,42 +67,42 @@
@@ -110,7 +110,7 @@
-
+
@@ -122,16 +122,16 @@