<style lang="less">
@import url('../../../styles/common.less');
#tiipChartInventory{
height:100%;
display:flex;
flex-direction: column;
background: #DCE9FE;
.Head{
height:30px;
line-height: 30px;
background: #09F;
text-align: center;
color: #fff;
font-weight: bold;
margin-top:8px;
width:100px;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
.CONTENT{
display:flex;flex-wrap:wrap;padding:8px;
.iCard{
width:calc(50% - 4px);
margin:0;
margin-bottom:8px;
text-align: center;
line-height:30px;
.warehouse{
}
}
.iCard:nth-child(odd) {
margin-right:8px;
}
}
.vertical{
flex-grow: 1;
height:1px;
margin-bottom: 7px;
}
.cross{
height:auto;
}
}
</style>
<template>
<div id="tiipChartInventory">
<div>
<div class="Head">金额</div>
<div class="iCard" ref="chart">
<canvas id="myChart" width="400" height="260" style="width:100%;height:240px;"></canvas>
</div>
</div>
<div>
<div class="Head">数量</div>
<div class="CONTENT">
<div class="iCard" v-for="(item,index) in chartData" :key="index" >
<div class="warehouse" :style="{'color':colorList[index]}">{{item.sStoreName}}</div>
<div class="piece"><span style="color:#8a8a8a;">总匹数:</span>{{Number(item.nStockPieceQty).toLocaleString()}}</div>
<div class="qty"><span style="color:#8a8a8a;">总数量:</span>{{Number(item.nStockQty).toLocaleString()}}</div>
</div>
</div>
</div>
<div v-if="false">
<div class="Head">金额</div>
<div :class="[direction == 'cross' ? 'cross' : 'vertical','iCard']">
<customerTable :columns="columns" :list="list" :tableStyle="tableStyle"></customerTable>
</div>
</div>
</div>
</template>
<script>
import Util from '@/libs/util.js'
import { mapState } from 'vuex'
import customerTable from '@/components/Table'
const F2 = require('@antv/f2/lib/index')
require('@antv/f2/lib/interaction/pan')
require('@antv/f2/lib/interaction/pie-select'); // 引入饼图选中交互
const Gesture = require('@antv/f2/lib/plugin/gesture');
export default {
name: 'tiipChartInventory',
data () {
return {
myChart:null,
list:[],
columns:[
{
width:'50px',
name:'序号',
align:'center',
field:'iIden',
},
{
width:'100px',
name:'类别',
align:'center',
field:'sMaterialTypeName',
},
{
width:'100px',
name:'入库数量',
align:'center',
field:'nInQty',
},
{
width:'100px',
name:'仓库金额',
align:'center',
field:'nAmount'
},
{
width:'100px',
name:'库存数量',
align:'center',
field:'nStockQty'
},
{
width:'100px',
name:'物料编号',
align:'center',
field:'sSampleMaterialNo'
},
],
tableStyle:{
theadBgColor:'rgba(223,238,253,1)',
complexTrBgColor:'white',
singleTrBgColor:'#eef4fe',
theadTdBorder:false,
tbodyTdBorder:false,
tbodyHeight:'calc(100vh - 342px)',
tbodyTrBorderBottom:'1px solid #5cadff',
width:'550px'
},
chartData:[],
direction:'vertical',
sStoreNo:'',
colorList:[ '#FE5D4D', '#3BA4FF', '#737DDE','#0000CD','#008B45','#FFF68F','#8B814C','#8B658B' ]
}
},
computed:{
...mapState({
userId:state => state.app.userId
})
},
async mounted(){
window.d = this;
this.$store.dispatch('saveUserId',this.$route.params.userId);
window.addEventListener("resize",()=>{
setTimeout(()=>{
this.renderResize();
this.myChart.changeSize(this.$refs['chart'].offsetWidth); // 清除
this.myChart.destroy();
this.renderChart();
})
});
this.$nextTick(async ()=>{
this.renderResize();
await this.getDetail();
await this.renderChart();
})
},
methods:{
renderResize() {
// 判断横竖屏
let width = document.documentElement.clientWidth;
let height = document.documentElement.clientHeight;
if(width > height) {
this.direction = 'cross';
this.tableStyle.tbodyHeight = '100%';
}else{
this.direction = 'vertical';
this.tableStyle.tbodyHeight = 'calc(100vh - 342px)';
}
// 做页面适配
// 注意:renderResize方法执行时虚拟dom尚未渲染挂载,如果要操作vue实例,最好在this.$nextTick()里进行。
},
renderChart () {
let that = this;
const data = this.chartData;
const map = {};
data.forEach(function(obj) {
map[obj.sStoreName] = Number(obj.nAmount||0).toLocaleString() + '元';
});
this.myChart = new F2.Chart({
id: 'myChart',
pixelRatio: window.devicePixelRatio,
padding: [ 20, 'auto' ],
plugins: Gesture,
});
this.myChart.source(data, {
nAmount: {
formatter: function formatter(val) {
return val + '元';
}
}
});
this.myChart.tooltip(false)
this.myChart.coord('polar', {
transposed: true,
innerRadius: 0.7,
radius: 1
});
this.myChart.axis(false);
this.myChart.interval()
.position('a*nAmount')
.color('sStoreName', this.colorList)
.adjust('stack');
const guide = this.myChart.guide().html({
position: [ '50%', '50%' ],
html: `
<div style="width: 250px;height: 40px;text-align: center;">
<div style="font-size: 12px">总计</div>
<div style="font-size: 12px">${(this.chartData.reduce((x,y)=>{return x = x+y.nAmount},0)).toFixed(2)}万</div>
</div>
`
});
this.myChart.interaction('pie-select',{
startEvent: 'tap',
cancelable:true,
animate: {
duration: 300,
delay: 0, // 动画延迟执行的时间
easing: 'bounceOut' // 动画的缓动函数
},
onEnd:async function(e){
if(!e.hasOwnProperty('data')){
// guide.html = `<div style="width: 250px;height: 40px;text-align: center;">
// <div style="font-size: 12px">总计</div>
// <div style="font-size: 12px">${(that.chartData.reduce((x,y)=>{return x = x+y.nAmount},0)).toFixed(2)}万</div>
// </div>
// `
// guide.repaint();
return false;
}
if(that.sStoreNo != e.data.sStoreNo){
that.sStoreNo = e.data.sStoreNo;
guide.html = `
<div style="width: 250px;height: 40px;text-align: center;">
<div style="font-size: 12px">${e.data.sStoreName}</div>
<div style="font-size: 12px">${((e.data.nAmount / (that.chartData.reduce((x,y)=>{return x = x+y.nAmount},0))) * 100).toFixed(2)}%</div>
</div>
`
}else{
guide.html = `<div style="width: 250px;height: 40px;text-align: center;">
<div style="font-size: 12px">总计</div>
<div style="font-size: 12px">${(that.chartData.reduce((x,y)=>{return x = x+y.nAmount},0)).toFixed(2)}万</div>
</div>
`
that.sStoreNo = '';
}
guide.repaint();
// await that.getDetail(that.sStoreNo);
}
});
this.myChart.legend({
clickable:true,
position: 'right',
itemFormatter: function itemFormatter(val) {
return val + '(' + map[val] + ')';
},
onClick: ev => {
let data = that.chartData.filter(x=>x.sStoreName == ev.clickedItem._attrs.dataValue);
if(data.length > 0){
guide.html = `
<div style="width: 250px;height: 40px;text-align: center;">
<div style="font-size: 12px">${data[0].sStoreName}</div>
<div style="font-size: 12px">${((data[0].nAmount / (that.chartData.reduce((x,y)=>{return x = x+y.nAmount},0))) * 100).toFixed(2)}%</div>
</div>
`
guide.repaint();
}
}
});
this.myChart.render();
},
async getDetail(sStoreNo){
let data = {};
!!sStoreNo && (data.sStoreNo = sStoreNo);
let res = await this.apiGet(`${this.$url('default')}/bianalysis/stockamountinfo/`,data,'加载中');
if(res.hasOwnProperty('set1')) this.chartData = res.set1;
this.chartData.map((x,y)=>{
x.a = '1';
})
this.chartData = this.chartData.filter(x=>x.nAmount != 0);
if(res.hasOwnProperty('set2')) this.list = res.set2;
}
},
components:{
customerTable
},
}
</script>