Browse Source

bi大数据

newStyle
风继续吹 1 year ago
parent
commit
656f78d42e
5 changed files with 312 additions and 265 deletions
  1. +9
    -0
      src/api/modules/http.js
  2. +236
    -206
      src/page/bi/bi.vue
  3. +5
    -2
      src/page/bi/index.js
  4. +16
    -0
      src/views/ReceivingRecords/index.vue
  5. +46
    -57
      vue.config.js

+ 9
- 0
src/api/modules/http.js View File

@@ -1399,3 +1399,12 @@ export function biRankingData(data) {
})
}

// 重新转写
export function toMergeRecord(params) {
return request({
url: 'autoSR/customer/toMergeRecord',
method: 'get',
params
})
}


+ 236
- 206
src/page/bi/bi.vue View File

@@ -8,7 +8,7 @@
<div
class="nav-box-item"
v-for="(data, index) in headList"
:key="index"
:key="data.title + index"
:class="{ active: headIndex == data.title }"
@click="selectNav(data)"
v-show="data.show"
@@ -39,7 +39,7 @@
<div
class="timer-item"
v-for="(data, index) in dateSelect"
:key="index"
:key="data.title + index"
:class="{ active: dateSelectIndex == data.value }"
@click="timerClick(data.value)"
>
@@ -64,6 +64,7 @@
v-model="companyValue"
placeholder="请选择"
clearable
filterable
@change="changeCompany"
:popper-append-to-body="false"
>
@@ -86,7 +87,7 @@
>
<el-option
v-for="item in projectOptions"
:key="item.value"
:key="item.label"
:label="item.label"
:value="item.value"
>
@@ -104,7 +105,7 @@
>
<el-option
v-for="item in rankingTypeList"
:key="item.value"
:key="item.title"
:label="item.title"
:value="item.value"
:disabled="item.disabled"
@@ -121,7 +122,7 @@
>
<el-option
v-for="item in ruleTypeList"
:key="item.value"
:key="item.title"
:label="item.title"
:value="item.value"
>
@@ -136,207 +137,203 @@
</div>
</header>

<template v-if="headIndex == '实时总览'">
<!-- 中间部分 -->
<section class="bodys">
<!-- 柱状图 -->
<div class="items lside">
<div
class="item-item"
v-for="(data, index) in lsideDataList"
:key="index"
>
<titles :title="data.title">
<div class="rsidebox" slot="rside">
<div
:class="{ active: data.activeName == data.params }"
@click="
(data.activeName = data.params),
getFormatter(data.params, data.title)
"
class="asd"
>
按项目
</div>
<div
:class="{ active: data.activeName == data.params1 }"
@click="
(data.activeName = data.params1),
getFormatter(data.params1, data.title)
"
class="asd"
>
按城市
</div>
<!-- 中间部分 -->
<section v-if="headIndex == '实时总览'" class="bodys">
<!-- 柱状图 -->
<div class="items lside">
<div
class="item-item"
v-for="(data, index) in lsideDataList"
:key="data.title + index"
>
<titles :title="data.title">
<div class="rsidebox" slot="rside">
<div
:class="{ active: data.activeName == data.params }"
@click="
(data.activeName = data.params),
getFormatter(data.params, data.title)
"
class="asd"
>
按项目
</div>
</titles>
<div
:class="{ active: data.activeName == data.params1 }"
@click="
(data.activeName = data.params1),
getFormatter(data.params1, data.title)
"
class="asd"
>
按城市
</div>
</div>
</titles>

<div
v-if="data.activeName == data.params"
class="echarts"
:id="data.params"
></div>
<div
v-if="data.activeName == data.params1"
class="echarts"
:id="data.params1"
></div>
</div>
<div
v-if="data.activeName == data.params"
class="echarts"
:id="data.params"
></div>
<div
v-if="data.activeName == data.params1"
class="echarts"
:id="data.params1"
></div>
</div>
</div>

<!-- 中间展示 -->
<div class="items middle">
<!-- 第一部分 -->
<div class="items-top">
<p class="title">待处理</p>
<div class="item-box">
<!-- // background-size: 168px 168px;
<!-- 中间展示 -->
<div class="items middle">
<!-- 第一部分 -->
<div class="items-top">
<p class="title">待处理</p>
<div class="item-box">
<!-- // background-size: 168px 168px;
// background-position: center; -->
<div
class="item-box-item"
v-for="(data, index) in stayHandleList"
@click="showDialog(data)"
:key="index"
:style="{
background: `url(${data.img}) no-repeat`,
backgroundSize: '168px 168px',
backgroundPosition: 'center',
}"
>
<div class="num" :style="{ color: data.fontColor }">
{{ data.data || 0 }}
</div>
<div class="item-title">{{ data.title }}</div>
<div
class="item-box-item"
v-for="(data, index) in stayHandleList"
@click="showDialog(data)"
:key="data.img + index"
:style="{
background: `url(${data.img}) no-repeat`,
backgroundSize: '168px 168px',
backgroundPosition: 'center',
}"
>
<div class="num" :style="{ color: data.fontColor }">
{{ data.data || 0 }}
</div>
<div class="item-title">{{ data.title }}</div>
</div>
</div>
<!-- 第二部分 -->
<div class="item-btm">
</div>
<!-- 第二部分 -->
<div class="item-btm">
<img
class="jiedailiang"
src="/img/bidata/jiedailiang@2x.png"
alt=""
/>
<img class="bgdsada" src="/img/bidata/bgdsada@x2.png" alt="" />

<div class="numberoftimes">
<img
class="jiedailiang"
src="/img/bidata/jiedailiang@2x.png"
class="numberoftimes-img"
src="/img/bidata/weu@2x.png"
alt=""
/>
<img class="bgdsada" src="/img/bidata/bgdsada@x2.png" alt="" />

<div class="numberoftimes">
<img
class="numberoftimes-img"
src="/img/bidata/weu@2x.png"
alt=""
/>
<div class="numberoftimes-box">
<span class="cishu">{{ receptionCount }}</span>
<span class="ci">次</span>
</div>
<div class="numberoftimes-box">
<span class="cishu">{{ receptionCount }}</span>
<span class="ci">次</span>
</div>
</div>

<div class="ibox">
<div class="ibox">
<div
class="ibox-item"
v-for="(data, index) in jiedaiList"
@click="showDialog(data)"
:key="data.bgImg + index"
:style="{
background: `url(${data.bgImg}) no-repeat`,
backgroundSize: data.unit ? '112px 112px' : '148px 108px',
backgroundPosition: 'center',
}"
>
<div
class="ibox-item"
v-for="(data, index) in jiedaiList"
@click="showDialog(data)"
:key="index"
class="num"
:style="{
background: `url(${data.bgImg}) no-repeat`,
backgroundSize: data.unit ? '112px 112px' : '148px 108px',
backgroundPosition: 'center',
width: data.unit ? '112px' : '148px',
height: data.unit ? '112px' : '108px',
}"
>
<div
class="num"
:style="{
width: data.unit ? '112px' : '148px',
height: data.unit ? '112px' : '108px',
}"
>
{{ data.data || 0 }}{{ data.unit || "" }}
</div>
<div class="title">{{ data.title }}</div>
{{ data.data || 0 }}{{ data.unit || "" }}
</div>
</div>
</div>
<!-- 第三部分 -->
<div class="item-mi">
<div class="item-item lside">
<titles title="接待趋势"></titles>
<div class="echarts" id="tendencyData1"></div>
</div>
<div class="item-item rside">
<titles title="销讲执行趋势"></titles>
<div class="echarts" id="tendencyData2"></div>
<div class="title">{{ data.title }}</div>
</div>
</div>
</div>

<!-- 饼状图 -->
<div class="items rside">
<div
class="item-item"
v-for="(data, index) in rsideDataList"
:key="index"
>
<titles :title="data.title"></titles>
<div class="echarts" :id="data.params"></div>
<!-- 第三部分 -->
<div class="item-mi">
<div class="item-item lside">
<titles title="接待趋势"></titles>
<div class="echarts" id="tendencyData1"></div>
</div>
<div class="item-item rside">
<titles title="销讲执行趋势"></titles>
<div class="echarts" id="tendencyData2"></div>
</div>
</div>
</section>
</template>
</div>

<template v-if="headIndex == '案场排名'">
<section class="caseRanking">
<div class="head-box">
<div
class="head-box-item"
v-for="(data, index) in caseRankingList"
:key="index"
>
<div class="t">{{ data.title }}</div>

<div class="b">
<p class="lside">
<span class="resultA">{{ data.resultA }}</span>
<span class="unit">{{ data.unit }}</span>
</p>

<p class="rside">
<img
v-if="data.resultB > 0"
class="r-img"
src="/img/indexIcon/indexCardUp.png"
alt=""
/>
<img
v-if="data.resultB < 0"
class="r-img"
src="/img/indexIcon/indexCardDown.png"
alt=""
/>
<span :class="{ up: data.resultB > 0 }" v-if="data.resultB > 0"
>+{{ data.resultB }}</span
>
<span
:class="{ down: data.resultB < 0 }"
v-if="data.resultB < 0"
>{{ data.resultB }}</span
>
<!-- <span v-if="data.resultB == 0">{{ data.resultB }}</span> -->
</p>
</div>
</div>
<!-- 饼状图 -->
<div class="items rside">
<div
class="item-item"
v-for="(data, index) in rsideDataList"
:key="data.params + index"
>
<titles :title="data.title"></titles>
<div class="echarts" :id="data.params"></div>
</div>
<div class="body-box">
<div
class="body-box-item"
v-for="(data, index) in rankingEchartsBarList"
:key="index"
>
<titles :title="data.title"></titles>
<div class="echarts" :id="data.params"></div>
</div>
</section>

<section class="caseRanking" v-if="headIndex == '案场排名'">
<div class="head-boxs">
<div
class="head-box-items"
v-for="(data, index) in caseRankingList"
:key="data.title + index + data.unit"
>
<div class="t">{{ data.title }}</div>

<div class="b">
<p class="lside">
<span class="resultA">{{ data.resultA }}</span>
<span class="unit">{{ data.unit }}</span>
</p>

<p class="rside">
<img
v-if="data.resultB > 0"
class="r-img"
src="/img/indexIcon/indexCardUp.png"
alt=""
/>
<img
v-if="data.resultB < 0"
class="r-img"
src="/img/indexIcon/indexCardDown.png"
alt=""
/>
<span :class="{ up: data.resultB > 0 }" v-if="data.resultB > 0"
>+{{ data.resultB }}</span
>
<span
:class="{ down: data.resultB < 0 }"
v-if="data.resultB < 0"
>{{ data.resultB }}</span
>
<!-- <span v-if="data.resultB == 0">{{ data.resultB }}</span> -->
</p>
</div>
</div>
</section>
</template>
</div>
<div class="body-box">
<div
class="body-box-item"
v-for="(data, index) in rankingEchartsBarList"
:key="data.params + index"
>
<titles :title="data.title"></titles>
<div class="echarts" :id="data.params"></div>
</div>
</div>
</section>

<el-dialog
class="dialogtips"
@@ -360,7 +357,7 @@
>
<el-table-column
v-for="(data, index) in tableNameList"
:key="index"
:key="data.showParams + index"
:property="data.showParams"
:label="data.showTitle"
></el-table-column>
@@ -386,7 +383,6 @@ import titles from "./common/title.vue";
import * as dialogConstList from "./index";
import { mapGetters } from "vuex";


export default {
components: { titles },
data() {
@@ -466,11 +462,10 @@ export default {
return name == this.headIndex;
};
},
},

created() {
this.checkAuthority()
this.checkAuthority();
},

mounted() {
@@ -480,23 +475,26 @@ export default {
methods: {
// 检测权限
checkAuthority() {
this.headList.forEach(item => {
this.headList.forEach((item) => {
if (this.permissions[item.methods]) {
item.show = true
item.show = true;
} else {
item.show = false
item.show = false;
}
})
});
let hIndex = sessionStorage.getItem("BIHeadIndex") || "实时总览";
let obj = this.headList.find(item => item.title == hIndex)
let obj = this.headList.find((item) => item.title == hIndex);
if (obj.show) {
this.selectNav(obj)
this.selectNav(obj);
} else {
let obj1 = this.headList.find(item => item.show === true)
this.selectNav(obj1)
let obj1 = this.headList.find((item) => item.show === true);
this.selectNav(obj1);
}
},

// 清除数据
clearData() {},

// 初始化页面
initPage() {
this.biGetOrgCodeList();
@@ -514,7 +512,9 @@ export default {
// 案场排名
initCaseRanking() {
this.biTopStatisticData();
this.biRankingData();
this.$nextTick(() => {
this.biRankingData();
});
},

// 案场排名顶部对比数据
@@ -549,31 +549,61 @@ export default {
this.$api.http.biRankingData(params).then((res) => {
if (res.code == 10000) {
this.rankingEchartsBarList.forEach((ob) => {
let xAxis = res.data[ob.params].data.map((item) => {
let object = res.data[ob.params];
console.log(object, ob.params);
let xAxis = object.data.map((item) => {
return item.name;
});
let avgList = [];
let yAxis = {};
if (this.companyValue) {
avgList.push({
yAxis: res.data[ob.params].companyAvg,
yAxis: object.companyAvg,
name: "集团平均",
});
try {
if (
object.data[this.orderBy == 1 ? 0 : object.data.length - 1]
.value < object.companyAvg
) {
yAxis.max = object.companyAvg;
}
} catch (e) {
console.log(e);
}
} else {
avgList.push({
yAxis: res.data[ob.params].allAvg,
yAxis: object.allAvg,
name: "行业平均",
});
try {
if (
object.data[this.orderBy == 1 ? 0 : object.data.length - 1]
.value < object.allAvg
) {
yAxis.max = object.allAvg;
}
} catch (e) {
console.log(e);
}
}
if (ob.unit == "%") {
yAxis = {
max: 100,
};
}

this.$nextTick(() => {
this.creatBar({
id: ob.params,
xAxis: xAxis,
yAxis: yAxis,
series: [
{
type: "bar",
barMaxWidth: "10%",
barMaxWidth: "20%",
name: ob.title,
data: res.data[ob.params].data || [],
data: object.data || [],
itemStyle: {
normal: {
//柱体的颜色
@@ -1055,7 +1085,7 @@ export default {
radius: ["45%", "60%"],
labelLine: {
length: 5,
showAbove: true
showAbove: true,
},
minAngle: 5,
avoidLabelOverlap: true,
@@ -1113,7 +1143,7 @@ export default {
series: [
{
type: "bar",
barMaxWidth: "10%",
barMaxWidth: "20%",
name: name,
data: this[params],
itemStyle: {
@@ -1175,7 +1205,7 @@ export default {
series: [
{
type: "bar",
barMaxWidth: "10%",
barMaxWidth: "20%",
name: list.title,
data: this[list.params],
itemStyle: {
@@ -1224,7 +1254,7 @@ export default {
series: [
{
type: "bar",
barMaxWidth: "10%",
barMaxWidth: "20%",
name: list.title,
data: this[list.params1],
itemStyle: {
@@ -1273,6 +1303,7 @@ export default {

// 生成柱状图
creatBar(obj) {
console.log(obj, obj.id);
// 基于准备好的dom,初始化echarts实例
let myChart = echarts.init(document.getElementById(obj.id));
myChart.clear();
@@ -1318,8 +1349,8 @@ export default {
],
yAxis: [
{
...obj.yAxis,
type: "value",

nameTextStyle: {
color: "#fff",
fontSize: 12,
@@ -1579,7 +1610,6 @@ export default {

.search {
margin: 0 0 0 40px;

}

.text {
@@ -1872,7 +1902,7 @@ export default {
padding: 0 0 30px 0;
width: 100%;

.head-box {
.head-boxs {
padding: 0 16px;
width: 100%;
height: 114px;
@@ -1880,7 +1910,7 @@ export default {
grid-template-columns: repeat(8, 1fr);
grid-column-gap: 16px;

.head-box-item {
.head-box-items {
padding: 24px 28px;
background: url("/img/bidata/itemBg.png") no-repeat;
background-size: 222px;
@@ -2118,7 +2148,7 @@ export default {
}

/deep/.search .el-button--primary {
background-color: #2ED1EE !important;
background-color: #2ed1ee !important;
}
</style>
<style>


+ 5
- 2
src/page/bi/index.js View File

@@ -462,11 +462,11 @@ const rankingEchartsBarList = [
},
{
title: "违禁接待排名(top10)",
params: 'visitRecordRanking',
params: 'prohibitedRanking',
},
{
title: "复访接待排名(top10)",
params: 'prohibitedRanking',
params: 'visitRecordRanking',
},
{
title: "平均接待时长排名(top10)",
@@ -475,14 +475,17 @@ const rankingEchartsBarList = [
{
title: "平均销讲执行排名(top10)",
params: 'avgFractionRanking',
unit: '%',
},
{
title: "平均挖掘执行排名(top10)",
params: 'avgWordFractionRanking',
unit: '%',
},
{
title: "平均挖掘成功排名(top10)",
params: 'avgWordFinishFractionRanking',
unit: '%',
},
]


+ 16
- 0
src/views/ReceivingRecords/index.vue View File

@@ -372,6 +372,12 @@
@click="reWriteagain(row)"
>重新转写</el-button
>
<el-button
type="text"
v-if="rec_rewrite_show && row.mergeFlag == 1"
@click="reWriteagains(row)"
>重新合并</el-button
>
<el-button
type="text"
v-if="permissions.rec_index_delete"
@@ -824,6 +830,16 @@ export default {
this.form.language = "";
}
},
reWriteagains(row) {
this.$api.http.toMergeRecord({id: row.id}).then(res => {
console.log(res)
if (res.code == 10000) {
this.$message.success(res.message)
} else {
this.$message.error(res.message)
}
})
},
// 获取销讲业务
getMarketingBusiness() {
this.$api.http


+ 46
- 57
vue.config.js View File

@@ -3,60 +3,49 @@
* https://cli.vuejs.org/zh/config/
*/

const url = process.env.VUE_APP_BASE_API // 配置.env文件通过运行命令启动不同调试环境
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = ['js', 'css']
module.exports = {
lintOnSave: true,
productionSourceMap: false,
chainWebpack: config => {
const entry = config.entry('app')
entry
.add('babel-polyfill')
.end()
entry
.add('classlist-polyfill')
.end()
},
css: {
// 忽略 CSS order 顺序警告
extract: { ignoreOrder: true }
},
configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
// 仅在生产环境下启用该配置
return {
performance: {
// 打包后最大文件大小限制
maxAssetSize: 1024000
},
plugins: [
new CompressionWebpackPlugin({
// filename: '[path].gz[query]',
// algorithm: 'gzip',
// test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
// threshold: 1024, // 只有大小大于该值的资源会被处理,当前配置为对于超过1k的数据进行处理,不足1k的可能会越压缩越大
// minRatio: 0.99, // 只有压缩率小于这个值的资源才会被处理
// deleteOriginalAssets: true // 删除原文件
})
]
}
}
},
// 配置转发代理
devServer: {
open: true,
disableHostCheck: true,
port: 8080,
proxy: {
'/': {
target: url,
ws: false, // 需要websocket 开启
pathRewrite: {
'^/': '/'
}
},
// 3.5 以后不需要再配置
}
}
}
const url = process.env.VUE_APP_BASE_API // 配置.env文件通过运行命令启动不同调试环境
const productionGzipExtensions = ['js', 'css']
module.exports = {
lintOnSave: true,
productionSourceMap: false,
chainWebpack: config => {
const entry = config.entry('app')
entry
.add('babel-polyfill')
.end()
entry
.add('classlist-polyfill')
.end()
},
css: {
// 忽略 CSS order 顺序警告
extract: { ignoreOrder: true }
},
configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
// 仅在生产环境下启用该配置
return {
performance: {
// 打包后最大文件大小限制
maxAssetSize: 1024000
},
}
}
},
// 配置转发代理
devServer: {
open: true,
disableHostCheck: true,
port: 8080,
proxy: {
'/': {
target: url,
ws: false, // 需要websocket 开启
pathRewrite: {
'^/': '/'
}
},
// 3.5 以后不需要再配置
}
}
}

Loading…
Cancel
Save