533 lines
14 KiB
Vue
533 lines
14 KiB
Vue
<template>
|
||
<div class="lc-container">
|
||
<div class="overview">
|
||
<div class="left">
|
||
<div class="top">
|
||
<div class="fit">
|
||
<img :src="require('@/assets/img/mxd/rate.png')"
|
||
alt=""
|
||
style="width: 12px; height: 12px">
|
||
<span class="text">Fit排名</span>
|
||
</div>
|
||
<div class="rate">
|
||
<img v-if="tabIndex === 1"
|
||
:src="require('@/assets/img/mxd/rate1.png')"
|
||
alt=""
|
||
class="rate">
|
||
<img v-if="tabIndex === 2"
|
||
:src="require('@/assets/img/mxd/rate2.png')"
|
||
alt=""
|
||
class="rate">
|
||
<img v-if="tabIndex === 3"
|
||
:src="require('@/assets/img/mxd/rate3.png')"
|
||
alt=""
|
||
class="rate">
|
||
<img v-if="tabIndex === 4"
|
||
:src="require('@/assets/img/mxd/rate4.png')"
|
||
alt=""
|
||
class="rate">
|
||
<img v-if="tabIndex === 5"
|
||
:src="require('@/assets/img/mxd/rate5.png')"
|
||
alt=""
|
||
class="rate">
|
||
</div>
|
||
</div>
|
||
<div class="content">
|
||
<div class="amount"
|
||
v-if="info && info.fit">
|
||
<div v-if="typeof info.fit === 'string'">
|
||
{{ info.fit }}
|
||
</div>
|
||
<div v-else>
|
||
<span style="font-size: 62px">{{ fitInteger }}</span>.{{ fitDecimal }}
|
||
</div>
|
||
</div>
|
||
<div class="desc">贝叶斯信息准则</div>
|
||
</div>
|
||
</div>
|
||
<div class="middle"></div>
|
||
<div class="right">
|
||
<div class="fit">
|
||
<img :src="require('@/assets/img/mxd/rateround.png')"
|
||
alt=""
|
||
style="width: 18px; height: 18px">
|
||
<span class="text">分组人数占比</span>
|
||
</div>
|
||
<piechart ref="chart"
|
||
:data="fitChartData"></piechart>
|
||
<div class="download-chart-data"
|
||
@click="download('pie')">
|
||
<i class="iconfont icon-xiazai"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="divider"></div>
|
||
<div class="bar-chart-section">
|
||
<div class="title"
|
||
style="padding: 20px 8px;background: #fff">
|
||
<subTitle>
|
||
总效用值(Zero-centered)图表
|
||
<div class="download-bar-chart-data"
|
||
@click="download('bar')">
|
||
<i class="iconfont icon-xiazai"></i>
|
||
</div>
|
||
</subTitle>
|
||
|
||
</div>
|
||
<div class="bar-container">
|
||
<barchart ref="barChart"
|
||
key="barChart"
|
||
:data="barData"></barchart>
|
||
</div>
|
||
<div class="bar-container2">
|
||
<barchart2 ref="barChart2"
|
||
key="barChart2"
|
||
:data="barData"></barchart2>
|
||
</div>
|
||
</div>
|
||
<div class="divider"></div>
|
||
<div style="padding: 20px 8px;background: #fff">
|
||
<subTitle>选项重要性(Zero-Centered)</subTitle>
|
||
</div>
|
||
<div class="table-container">
|
||
<a-table :data-source="d2"
|
||
:columns="c2"
|
||
:pagination="false"
|
||
:scroll="{ y: 500, x: 800 }"
|
||
rowKey="option_index">
|
||
<template v-for="(col,index) in c2"
|
||
:key="index"
|
||
#[col.key]="data">
|
||
<div v-if="col.dataIndex === 'sort'">
|
||
<div v-if="data.text.value=='1'"
|
||
style="color:rgb(175,52,52)">
|
||
{{ data.text.value }}</div>
|
||
<div v-if="data.text.value=='2'"
|
||
style="color:rgb(223,160,124)">
|
||
{{ data.text.value }}</div>
|
||
<div v-if="data.text.value=='3'"
|
||
style="color:rgb(238,215,144)">
|
||
{{ data.text.value }}</div>
|
||
<div v-if="data.text.value!='3'&&data.text.value!='2'&&data.text.value!='1'">
|
||
{{ data.text.value }}</div>
|
||
</div>
|
||
|
||
<div v-else-if="col.dataIndex === 'option_title'">
|
||
<div class="mxd-lc-detail-table-row"
|
||
v-if="data.text.type == 0 || data.text.type == 1"
|
||
v-html="data.text.value" :style="data.index <3 ? 'color:#47c4f5' : ''"></div>
|
||
<img v-if="data.text.type == 2"
|
||
:src="data.text.value"
|
||
style="width: 40px; height: 40px" />
|
||
</div>
|
||
<div v-else>
|
||
<div v-if="data.text.value >= 0"
|
||
style="color: #52c19a">{{ data.text.value == 0? '0': data.text.value}}</div>
|
||
<div v-else
|
||
style="color: #923139">{{ data.text.value == 0? '0': data.text.value }}</div>
|
||
</div>
|
||
</template>
|
||
</a-table>
|
||
</div>
|
||
<div class="divider"></div>
|
||
<div style="padding: 20px 8px;background: #fff">
|
||
<subTitle>选项重要性(Raw)</subTitle>
|
||
</div>
|
||
<div class="table-container">
|
||
<a-table :dataSource="d1"
|
||
:columns="c1"
|
||
:pagination="false"
|
||
rowKey="option_index"
|
||
:scroll="{ y: 500, x:800 }">
|
||
|
||
<template v-for="(col,index) in c1"
|
||
:key="index"
|
||
#[col.dataIndex]=" data ">
|
||
<div v-if="col.dataIndex === 'sort'">
|
||
|
||
<div v-if="data.text.value=='1'"
|
||
style="color:rgb(175,52,52)">
|
||
{{ data.text.value }}</div>
|
||
<div v-if="data.text.value=='2'"
|
||
style="color:rgb(223,160,124)">
|
||
{{ data.text.value }}</div>
|
||
<div v-if="data.text.value=='3'"
|
||
style="color:rgb(238,215,144)">
|
||
{{ data.text.value }}</div>
|
||
<div v-if="data.text.value!='3'&&data.text.value!='2'&&data.text.value!='1'">
|
||
{{ data.text.value }}</div>
|
||
</div>
|
||
|
||
<div v-else-if="col.dataIndex === 'option_title'">
|
||
<div class="mxd-lc-detail-table-row"
|
||
v-if="data.text.type == 0 || data.text.type == 1"
|
||
v-html="data.text.value" :style="data.index <3 ? 'color:#47c4f5' : ''"></div>
|
||
<img v-if="data.text.type == 2"
|
||
:src="data.text.value"
|
||
style="width: 40px; height: 40px" />
|
||
</div>
|
||
<div v-else>
|
||
<div v-if="data.text.value >= 0"
|
||
style="color: #52c19a">{{ data.text.value == 0? '0': data.text.value}}</div>
|
||
<div v-else
|
||
style="color: #923139">{{ data.text.value == 0? '0': data.text.value }}</div>
|
||
</div>
|
||
</template>
|
||
</a-table>
|
||
</div>
|
||
</div>
|
||
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, watch, onMounted, nextTick } from 'vue'
|
||
import { useRoute } from "vue-router";
|
||
import subTitle from "@/views/DataAnalyse/components/SubTitle";
|
||
import piechart from './piechart.vue';
|
||
import barchart from "./barchart.vue";
|
||
import barchart2 from "./barchart2.vue";
|
||
import CommonApi from "@/api/common";
|
||
import createOSS from "@/utils/aliyunOssUpLoad";
|
||
import { uploadDocumentFile } from "@/api/data-analyse";
|
||
import { fract } from '@/utils/number'
|
||
const props = defineProps({
|
||
info: {
|
||
type: Object,
|
||
default: () => { }
|
||
},
|
||
title: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
tabIndex: {
|
||
type: Number,
|
||
},
|
||
question_data: {
|
||
type: Object,
|
||
default: () => { }
|
||
}
|
||
})
|
||
|
||
const route = useRoute()
|
||
const sn = route.query.sn
|
||
const d1 = ref([])
|
||
const c1 = ref([])
|
||
const d2 = ref([])
|
||
const c2 = ref([])
|
||
const el = ref(null)
|
||
const fitChartData = ref()
|
||
const fit = ref('')
|
||
const fitInteger = ref('')
|
||
const fitDecimal = ref('')
|
||
const chart = ref(null)
|
||
const barData = ref([])
|
||
const barChart = ref(null)
|
||
const barChart2 = ref(null)
|
||
|
||
function dataURLtoFile (dataurl, filename) {
|
||
if (dataurl) {
|
||
let arr = dataurl.split(','),
|
||
mime = arr[0].match(/:(.*?);/)[1],
|
||
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
||
while (n--) {
|
||
u8arr[n] = bstr.charCodeAt(n);
|
||
}
|
||
return new File([u8arr], filename, { type: mime });
|
||
}
|
||
}
|
||
|
||
function downloadFile (name, url) {
|
||
const elink = document.createElement("a");
|
||
elink.download = (name || "统计图") + '.png';
|
||
elink.style.display = "none";
|
||
elink.href = url;
|
||
document.body.appendChild(elink);
|
||
elink.click();
|
||
URL.revokeObjectURL(elink.href); // 释放URL 对象
|
||
document.body.removeChild(elink);
|
||
}
|
||
async function download (type) {
|
||
const yy = new Date().getFullYear()
|
||
const MM = (new Date().getMonth() + 1) < 10 ? '0' + (new Date().getMonth() + 1) : (new Date().getMonth() + 1)
|
||
const dd = new Date().getDate() < 10 ? '0' + new Date().getDate() : new Date().getDate()
|
||
const HH = new Date().getHours() < 10 ? '0' + new Date().getHours() : new Date().getHours()
|
||
const mm = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes()
|
||
var time = `${yy}${MM}${dd}${HH}${mm}`
|
||
let base64;
|
||
if (type === 'pie') {
|
||
base64 = chart.value.chart.ImageUrl
|
||
var file = dataURLtoFile(base64, `${props.question_data}MXD分组人数占比图表${time}`)
|
||
} else {
|
||
console.log(barChart2)
|
||
base64 = barChart2.value.chart.ImageUrl
|
||
var file = dataURLtoFile(base64, `${props.question_data}MXD总效用值(Zero-Centered)图表${time}`)
|
||
}
|
||
|
||
const name = `${file.name}.jpg`
|
||
downloadFile(name, base64)
|
||
const { data } = await CommonApi.getOssInfo();
|
||
const result = await createOSS({
|
||
file,
|
||
bucket: data.Bucket,
|
||
region: data.Region,
|
||
stsToken: data.SecurityToken,
|
||
accessKeyId: data.AccessKeyId,
|
||
accessKeySecret: data.AccessKeySecret,
|
||
name: `MXD/${sn}/${new Date().getTime()}/${name}`,
|
||
success_action_status: 200,
|
||
});
|
||
const urlData = [
|
||
{
|
||
name,
|
||
url: `${data.Host}${result}`,
|
||
size: file.size
|
||
}
|
||
]
|
||
uploadDocumentFile({
|
||
url: JSON.stringify(urlData),
|
||
parent_sn: sn,
|
||
import_type: 6, //图表分析
|
||
})
|
||
}
|
||
|
||
watch(() => props.info, (info) => {
|
||
const data = JSON.parse(JSON.stringify(info.zero_data.data))
|
||
if (!info) return
|
||
fitChartData.value = info.fit_chart
|
||
if (typeof info.fit === 'string') {
|
||
fit.value = info.fit
|
||
}
|
||
if (typeof info.fit === 'number') {
|
||
const fit = info.fit + ''
|
||
const splitIndex = fit.indexOf('.')
|
||
fitInteger.value = fit.slice(0, splitIndex)
|
||
fitDecimal.value = fit.slice(splitIndex + 1)
|
||
}
|
||
const childrenlist = []
|
||
const barChartData = data.sort((a, b) => a.class_sum.value * 1 - b.class_sum.value * 1)
|
||
barData.value = barChartData;
|
||
const _c1 = [].concat(info.raw_data.columns)
|
||
c1.value = []
|
||
c1.value = _c1.map((item,index) => {
|
||
if (item?.children) {
|
||
item.children.map((e,index) => { e.dataIndex = e.key;e.index =index; childrenlist.push(e.key) })
|
||
}
|
||
if (item?.children) {
|
||
item.children.map((e,index) => { e.dataIndex = e.key;e.index =index;childrenlist.push(e.key) })
|
||
} else {
|
||
item.slots = { customRender: item.key }
|
||
item.dataIndex = item.key
|
||
item.fixed = item.key === 'sort' ? 'left' : null
|
||
// childrenlist.push(item.key )
|
||
}
|
||
// }
|
||
return {
|
||
...item,
|
||
width: 200,
|
||
align: 'center'
|
||
}
|
||
})
|
||
// 处理表格data数据
|
||
debugger;
|
||
d1.value = info.raw_data.data.map((item, index) => {
|
||
for (let i in item) {
|
||
if (childrenlist.indexOf(i) > -1 && item[i].value == 0) {
|
||
item[i] ="0"
|
||
}
|
||
if (childrenlist.indexOf(i) > -1 && item[i].value) {
|
||
item[i] = item[i].value
|
||
}
|
||
}
|
||
return {
|
||
...item,
|
||
option_index: index
|
||
}
|
||
})
|
||
const childrenlist2 = []
|
||
const _c2 = [].concat(info.zero_data.columns)
|
||
c2.value = []
|
||
// 带children的key存进去
|
||
|
||
c2.value = _c2.map((item) => {
|
||
if (item?.children) {
|
||
item.children.map((e) => { e.dataIndex = e.key;childrenlist2.push(e.key) })
|
||
} else {
|
||
item.slots = { customRender: item.key }
|
||
item.dataIndex = item.key
|
||
item.fixed = item.key === 'sort' ? 'left' : null
|
||
// childrenlist2.push(item.key)
|
||
}
|
||
return {
|
||
...item,
|
||
width: 200,
|
||
align: 'center'
|
||
}
|
||
})
|
||
debugger;
|
||
d2.value = info.zero_data.data.map((item, index) => {
|
||
for (let i in item) {
|
||
if (childrenlist2.indexOf(i) > -1 && item[i].value == 0) {
|
||
item[i] ="0"
|
||
}
|
||
if (childrenlist2.indexOf(i) > -1 && item[i].value) {
|
||
item[i] = item[i].value
|
||
}
|
||
}
|
||
return {
|
||
...item,
|
||
option_index: index
|
||
}
|
||
})
|
||
}, {
|
||
immediate: true
|
||
})
|
||
|
||
onMounted(() => {
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.mxd-lc-detail-table-row {
|
||
img {
|
||
width: 40px;
|
||
height: 40px;
|
||
}
|
||
br {
|
||
display: none !important;
|
||
}
|
||
}
|
||
</style>
|
||
<style lang="scss" scoped>
|
||
.lc-container {
|
||
}
|
||
.divider {
|
||
background: #fafafa;
|
||
height: 12px;
|
||
}
|
||
.overview {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.left,
|
||
.right {
|
||
flex: 1;
|
||
box-sizing: border-box;
|
||
padding: 16px;
|
||
height: 270px;
|
||
background: #fff;
|
||
}
|
||
.middle {
|
||
width: 12px;
|
||
height: 100%;
|
||
background: transparent;
|
||
}
|
||
|
||
.right {
|
||
position: relative;
|
||
|
||
.download-chart-data {
|
||
position: absolute;
|
||
right: 0;
|
||
top: 10px;
|
||
width: 30px;
|
||
height: 30px;
|
||
|
||
.icon-xiazai {
|
||
color: #8e8e8e;
|
||
|
||
&:hover {
|
||
color: #3f85ff;
|
||
}
|
||
}
|
||
}
|
||
.fit {
|
||
.text {
|
||
color: #8c8c8c;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.left {
|
||
.top {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: 30px;
|
||
|
||
.fit {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.text {
|
||
color: #8c8c8c;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
|
||
.rate {
|
||
width: 30px;
|
||
|
||
img {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.content {
|
||
height: 170px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-direction: column;
|
||
|
||
.amount {
|
||
font-size: 40px;
|
||
color: #262626;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.desc {
|
||
color: #8c8c8c;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.bar-chart-section {
|
||
width: 100%;
|
||
background: #fff;
|
||
position: relative;
|
||
.bar-container {
|
||
height: 400px;
|
||
position: relative;
|
||
}
|
||
.bar-container2 {
|
||
height: 400px;
|
||
width: 1144px;
|
||
position: absolute;
|
||
opacity: 0;
|
||
}
|
||
}
|
||
.download-bar-chart-data {
|
||
position: absolute;
|
||
right: 0;
|
||
top: 0;
|
||
width: 30px;
|
||
height: 30px;
|
||
.icon-xiazai {
|
||
color: #8e8e8e;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
#PieChartsCompoents {
|
||
position: relative;
|
||
bottom: 30px;
|
||
margin-top: 30px;
|
||
height: 213px;
|
||
}
|
||
</style>
|