|
|
@ -1,12 +1,14 @@ |
|
|
|
<template> |
|
|
|
<div class="analysis"> |
|
|
|
<div v-if="list.length && list.length !== 0"> |
|
|
|
<div v-for="(item, index) in list" :key="index"> |
|
|
|
<div class="content"> |
|
|
|
<div class="title"> |
|
|
|
<span style="font-size: 16px; font-weight: bold;">Q{{ index + 1 }} :{{ item.label }}({{ item.type }})</span> |
|
|
|
<div class="analysis"> |
|
|
|
<div v-if="list.length && list.length !== 0"> |
|
|
|
<div v-for="(item, index) in list" :key="index"> |
|
|
|
<div class="content"> |
|
|
|
<div class="title"> |
|
|
|
<span style="font-size: 16px; font-weight: bold" |
|
|
|
>Q{{ index + 1 }} :{{ item.label }}({{ item.type }})</span |
|
|
|
> |
|
|
|
|
|
|
|
<!-- <div> |
|
|
|
<!-- <div> |
|
|
|
<span>图表类型:</span> |
|
|
|
<el-select v-model="item.chartType" placeholder="请选择"> |
|
|
|
<el-option |
|
|
@ -17,201 +19,234 @@ |
|
|
|
/> |
|
|
|
</el-select> |
|
|
|
</div> --> |
|
|
|
</div> |
|
|
|
<!-- <line-chart |
|
|
|
</div> |
|
|
|
<!-- <line-chart |
|
|
|
class="chart" |
|
|
|
:chart-option="getCharData(item)" |
|
|
|
:width="'90vw'" |
|
|
|
/> --> |
|
|
|
<div v-if="computedCount(item.type)" class="cell-type"> |
|
|
|
<span>共收集 {{ item.detail.collectionTotal }} 条,</span> |
|
|
|
<span>有效 {{ item.detail.validTotal }} 条</span> |
|
|
|
<span v-if="item.type === 'NUMBER_INPUT'">,总计 {{ item.detail.sumTotal }} </span> |
|
|
|
<span v-if="item.type === 'SWITCH'">,开 {{ item.detail.openTotal }} 条,关 {{ item.detail.closedTotal }} 条</span> |
|
|
|
</div> |
|
|
|
<div v-else-if="item.type === 'RATE'" class="cell-rate"> |
|
|
|
<div v-for="(n, i) in item.detail.maxStarNum" :key="i" class="rate-item"> |
|
|
|
<div class="rate-item-icon"> |
|
|
|
<el-rate |
|
|
|
:value="n" |
|
|
|
disabled |
|
|
|
text-color="#ff9900" |
|
|
|
> |
|
|
|
</el-rate> |
|
|
|
</div> |
|
|
|
<div class="rate-item-num">{{ item.detail.starProfile[n] || 0 }} 次</div> |
|
|
|
</div> |
|
|
|
<div class="rate-item"> |
|
|
|
<div class="rate-item-avg">平均星数</div> |
|
|
|
<div class="rate-item-icon"> |
|
|
|
<el-rate |
|
|
|
:value="item.detail.avgStarNum" |
|
|
|
disabled |
|
|
|
text-color="#ff9900" |
|
|
|
> |
|
|
|
</el-rate> |
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-else-if="item.type === 'RADIO' || item.type === 'CHECKBOX' || item.type === 'SELECT'" class="cell-wrapper"> |
|
|
|
<div v-for="(n, i) in item.detail.options" :key="i" class="cell"> |
|
|
|
<div class="cell-label">{{ n.label }}</div> |
|
|
|
<div class="cell-value"> |
|
|
|
<div class="cell-progress"> |
|
|
|
<el-progress :stroke-width="20" :show-text="false" :percentage="computedPercent(n.currentCount, item.detail.totalCount)" /> |
|
|
|
</div> |
|
|
|
<div class="cell-percent"> |
|
|
|
{{ computedPercent(n.currentCount, item.detail.totalCount).toFixed(2) }}% |
|
|
|
</div> |
|
|
|
<div class="cell-num">{{ n.currentCount }}次</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-if="computedCount(item.type)" class="cell-type" @click="handleOpen(item)"> |
|
|
|
<span>共收集 {{ item.detail.collectionTotal }} 条,</span> |
|
|
|
<span>有效 {{ item.detail.validTotal }} 条</span> |
|
|
|
<span v-if="item.type === 'NUMBER_INPUT'" |
|
|
|
>,总计 {{ item.detail.sumTotal }} |
|
|
|
</span> |
|
|
|
<span v-if="item.type === 'SWITCH'" |
|
|
|
>,开 {{ item.detail.openTotal }} 条,关 |
|
|
|
{{ item.detail.closedTotal }} 条</span |
|
|
|
> |
|
|
|
</div> |
|
|
|
<div v-else-if="item.type === 'RATE'" class="cell-rate"> |
|
|
|
<div |
|
|
|
v-for="(n, i) in item.detail.maxStarNum" |
|
|
|
:key="i" |
|
|
|
class="rate-item" |
|
|
|
> |
|
|
|
<div class="rate-item-icon"> |
|
|
|
<el-rate :value="n" disabled text-color="#ff9900"> </el-rate> |
|
|
|
</div> |
|
|
|
<div class="rate-item-num"> |
|
|
|
{{ item.detail.starProfile[n] || 0 }} 次 |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="rate-item"> |
|
|
|
<div class="rate-item-avg">平均星数</div> |
|
|
|
<div class="rate-item-icon"> |
|
|
|
<el-rate |
|
|
|
:value="item.detail.avgStarNum" |
|
|
|
disabled |
|
|
|
text-color="#ff9900" |
|
|
|
> |
|
|
|
</el-rate> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div |
|
|
|
v-else-if=" |
|
|
|
item.type === 'RADIO' || |
|
|
|
item.type === 'CHECKBOX' || |
|
|
|
item.type === 'SELECT' |
|
|
|
" |
|
|
|
class="cell-wrapper" |
|
|
|
> |
|
|
|
<div v-for="(n, i) in item.detail.options" :key="i" class="cell"> |
|
|
|
<div class="cell-label">{{ n.label }}</div> |
|
|
|
<div class="cell-value"> |
|
|
|
<div class="cell-progress"> |
|
|
|
<el-progress |
|
|
|
:stroke-width="20" |
|
|
|
:show-text="false" |
|
|
|
:percentage="computedPercent(n.currentCount, item.detail.totalCount)" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
<el-divider /> |
|
|
|
<div class="cell-percent"> |
|
|
|
{{ computedPercent(n.currentCount, item.detail.totalCount).toFixed(2) }}% |
|
|
|
</div> |
|
|
|
<div class="cell-num">{{ n.currentCount }}次</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<data-empty v-else style="padding: 20px" desc="暂无数据分析" /> |
|
|
|
<el-divider /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<data-empty v-else style="padding: 20px" desc="暂无数据分析" /> |
|
|
|
|
|
|
|
<el-dialog :title="dialogTitle" :visible.sync="dialogTableVisible" :close-on-click-modal="false" @close="handleClose"> |
|
|
|
<el-table :data="dialogData" max-height="400" border> |
|
|
|
<el-table-column |
|
|
|
type="index" |
|
|
|
width="50"> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-for="item in dialogHeader" :key="item.formItemId" :prop="item.formItemId" :label="item.label" /> |
|
|
|
<!-- <el-table-column property="name" label="姓名" width="200"></el-table-column> |
|
|
|
<el-table-column property="address" label="地址"></el-table-column> --> |
|
|
|
</el-table> |
|
|
|
</el-dialog> |
|
|
|
|
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import LineChart from '@/components/echarts/LineChart' |
|
|
|
export default { |
|
|
|
components: { |
|
|
|
LineChart |
|
|
|
}, |
|
|
|
data() { |
|
|
|
return { |
|
|
|
barChartOptionData: { |
|
|
|
tooltip: { |
|
|
|
trigger: 'axis', |
|
|
|
backgroundColor: 'rgba(255,255,255,0.8)', // 通过设置rgba调节背景颜色与透明度 |
|
|
|
color: 'black', |
|
|
|
borderWidth: '1', |
|
|
|
borderColor: 'rgb(156,209,255)', |
|
|
|
textStyle: { |
|
|
|
color: 'black' |
|
|
|
}, |
|
|
|
axisPointer: { |
|
|
|
type: 'shadow' |
|
|
|
} |
|
|
|
}, |
|
|
|
grid: { |
|
|
|
left: '3%', |
|
|
|
right: '4%', |
|
|
|
bottom: '3%', |
|
|
|
containLabel: true |
|
|
|
}, |
|
|
|
xAxis: [ |
|
|
|
{ |
|
|
|
type: 'category', |
|
|
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
|
|
|
axisTick: { |
|
|
|
alignWithLabel: true |
|
|
|
} |
|
|
|
} |
|
|
|
], |
|
|
|
yAxis: [ |
|
|
|
{ |
|
|
|
type: 'value' |
|
|
|
} |
|
|
|
], |
|
|
|
series: [ |
|
|
|
{ |
|
|
|
name: '数量', |
|
|
|
type: 'line', |
|
|
|
barWidth: '40%', |
|
|
|
data: [10, 52, 200, 334, 390, 330, 220] |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
list: [], |
|
|
|
options: [ |
|
|
|
{ |
|
|
|
value: 'pie', |
|
|
|
label: '饼图' |
|
|
|
}, |
|
|
|
/* { |
|
|
|
components: { |
|
|
|
LineChart |
|
|
|
}, |
|
|
|
data() { |
|
|
|
return { |
|
|
|
dialogTableVisible: false, |
|
|
|
dialogTitle: '', |
|
|
|
dialogData: [], |
|
|
|
dialogHeader: [], |
|
|
|
barChartOptionData: { |
|
|
|
tooltip: { |
|
|
|
trigger: 'axis', |
|
|
|
backgroundColor: 'rgba(255,255,255,0.8)', // 通过设置rgba调节背景颜色与透明度 |
|
|
|
color: 'black', |
|
|
|
borderWidth: '1', |
|
|
|
borderColor: 'rgb(156,209,255)', |
|
|
|
textStyle: { |
|
|
|
color: 'black' |
|
|
|
}, |
|
|
|
axisPointer: { |
|
|
|
type: 'shadow' |
|
|
|
} |
|
|
|
}, |
|
|
|
grid: { |
|
|
|
left: '3%', |
|
|
|
right: '4%', |
|
|
|
bottom: '3%', |
|
|
|
containLabel: true |
|
|
|
}, |
|
|
|
xAxis: [ |
|
|
|
{ |
|
|
|
type: 'category', |
|
|
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
|
|
|
axisTick: { |
|
|
|
alignWithLabel: true |
|
|
|
} |
|
|
|
} |
|
|
|
], |
|
|
|
yAxis: [ |
|
|
|
{ |
|
|
|
type: 'value' |
|
|
|
} |
|
|
|
], |
|
|
|
series: [ |
|
|
|
{ |
|
|
|
name: '数量', |
|
|
|
type: 'line', |
|
|
|
barWidth: '40%', |
|
|
|
data: [10, 52, 200, 334, 390, 330, 220] |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
list: [], |
|
|
|
options: [ |
|
|
|
{ |
|
|
|
value: 'pie', |
|
|
|
label: '饼图' |
|
|
|
}, |
|
|
|
/* { |
|
|
|
value: "ring", |
|
|
|
label: "环形图", |
|
|
|
}, */ |
|
|
|
{ |
|
|
|
value: 'bar', |
|
|
|
label: '柱状图' |
|
|
|
}, |
|
|
|
{ |
|
|
|
value: 'line', |
|
|
|
label: '折线图' |
|
|
|
} |
|
|
|
] |
|
|
|
{ |
|
|
|
value: 'bar', |
|
|
|
label: '柱状图' |
|
|
|
}, |
|
|
|
{ |
|
|
|
value: 'line', |
|
|
|
label: '折线图' |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
this.getData() |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
getData() { |
|
|
|
// `${process.env.VUE_APP_API_ROOT_TDUCK}/user/project/report/analysis` |
|
|
|
// params: { projectKey: this.$route.query.key } |
|
|
|
this.$api |
|
|
|
.post('/data/aggregator/questionnaire/analysisreport', { |
|
|
|
projectKey: this.$route.query.key |
|
|
|
}) |
|
|
|
.then((res) => { |
|
|
|
this.list = res.data |
|
|
|
}) |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
this.getData() |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
getData() { |
|
|
|
// `${process.env.VUE_APP_API_ROOT_TDUCK}/user/project/report/analysis` |
|
|
|
// params: { projectKey: this.$route.query.key } |
|
|
|
this.$api |
|
|
|
.post('/data/aggregator/questionnaire/analysisreport', { |
|
|
|
projectKey: this.$route.query.key |
|
|
|
}) |
|
|
|
.then(res => { |
|
|
|
this.list = res.data |
|
|
|
}) |
|
|
|
getCharData(data) { |
|
|
|
const config = { |
|
|
|
tooltip: { |
|
|
|
backgroundColor: 'rgba(255,255,255,0.8)', // 通过设置rgba调节背景颜色与透明度 |
|
|
|
color: 'black', |
|
|
|
borderWidth: '1', |
|
|
|
borderColor: 'rgb(156,209,255)', |
|
|
|
textStyle: { |
|
|
|
color: 'black' |
|
|
|
} |
|
|
|
}, |
|
|
|
getCharData(data) { |
|
|
|
const config = { |
|
|
|
tooltip: { |
|
|
|
backgroundColor: 'rgba(255,255,255,0.8)', // 通过设置rgba调节背景颜色与透明度 |
|
|
|
color: 'black', |
|
|
|
borderWidth: '1', |
|
|
|
borderColor: 'rgb(156,209,255)', |
|
|
|
textStyle: { |
|
|
|
color: 'black' |
|
|
|
} |
|
|
|
}, |
|
|
|
grid: { |
|
|
|
left: '3%', |
|
|
|
right: '4%', |
|
|
|
bottom: '3%', |
|
|
|
containLabel: true |
|
|
|
}, |
|
|
|
xAxis: [ |
|
|
|
{ |
|
|
|
type: 'category', |
|
|
|
axisTick: { |
|
|
|
alignWithLabel: true |
|
|
|
} |
|
|
|
} |
|
|
|
], |
|
|
|
yAxis: [ |
|
|
|
{ |
|
|
|
type: 'value' |
|
|
|
} |
|
|
|
], |
|
|
|
series: [ |
|
|
|
{ |
|
|
|
name: '数量', |
|
|
|
type: 'pie', |
|
|
|
barWidth: '40%' |
|
|
|
} |
|
|
|
] |
|
|
|
grid: { |
|
|
|
left: '3%', |
|
|
|
right: '4%', |
|
|
|
bottom: '3%', |
|
|
|
containLabel: true |
|
|
|
}, |
|
|
|
xAxis: [ |
|
|
|
{ |
|
|
|
type: 'category', |
|
|
|
axisTick: { |
|
|
|
alignWithLabel: true |
|
|
|
} |
|
|
|
if (['bar', 'line'].includes(data.chartType)) { |
|
|
|
config.tooltip.axisPointer = { |
|
|
|
type: 'line' |
|
|
|
} |
|
|
|
config.tooltip.trigger = 'axis' |
|
|
|
config.xAxis[0].data = data.fieldName |
|
|
|
config.series[0].data = data.data |
|
|
|
config.series[0].type = data.chartType |
|
|
|
} else { |
|
|
|
// 环形图暂时不用 无法切换到饼图 |
|
|
|
/* if ("ring" === data.chartType) { |
|
|
|
} |
|
|
|
], |
|
|
|
yAxis: [ |
|
|
|
{ |
|
|
|
type: 'value' |
|
|
|
} |
|
|
|
], |
|
|
|
series: [ |
|
|
|
{ |
|
|
|
name: '数量', |
|
|
|
type: 'pie', |
|
|
|
barWidth: '40%' |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
if (['bar', 'line'].includes(data.chartType)) { |
|
|
|
config.tooltip.axisPointer = { |
|
|
|
type: 'line' |
|
|
|
} |
|
|
|
config.tooltip.trigger = 'axis' |
|
|
|
config.xAxis[0].data = data.fieldName |
|
|
|
config.series[0].data = data.data |
|
|
|
config.series[0].type = data.chartType |
|
|
|
} else { |
|
|
|
// 环形图暂时不用 无法切换到饼图 |
|
|
|
/* if ("ring" === data.chartType) { |
|
|
|
config.series[0].radius = ["40%", "70%"]; |
|
|
|
|
|
|
|
config.series[0].emphasis = { |
|
|
@ -225,22 +260,79 @@ export default { |
|
|
|
delete config.series[0].radius |
|
|
|
delete config.series[0].label |
|
|
|
} */ |
|
|
|
config.series[0].data = [] |
|
|
|
Object.keys(data.map).forEach(key => { |
|
|
|
config.series[0].data.push({ name: key, value: data.map[key] }) |
|
|
|
}) |
|
|
|
// config.series[0].data = data.map |
|
|
|
config.series[0].data = [] |
|
|
|
Object.keys(data.map).forEach((key) => { |
|
|
|
config.series[0].data.push({ name: key, value: data.map[key] }) |
|
|
|
}) |
|
|
|
// config.series[0].data = data.map |
|
|
|
} |
|
|
|
return config |
|
|
|
}, |
|
|
|
getInputList(id, type) { |
|
|
|
|
|
|
|
this.$api |
|
|
|
.post('/data/aggregator/questionnaire/itemresdetail-list', { |
|
|
|
projectKey: this.$route.query.key, |
|
|
|
formItemId: id, |
|
|
|
type |
|
|
|
}) |
|
|
|
.then((res) => { |
|
|
|
this.dialogData = res.data.map(item => { |
|
|
|
return { |
|
|
|
[id]: item |
|
|
|
} |
|
|
|
return config |
|
|
|
}, |
|
|
|
computedCount(type) { |
|
|
|
const arr = ['PROVINCE_CITY', 'NUMBER_INPUT', 'SWITCH', 'INPUT', 'TEXTAREA', 'INPUT_MAP', 'TIME', 'DATE_RANGE', 'DATE', 'TIME_RANGE'] |
|
|
|
return arr.includes(type) |
|
|
|
}, |
|
|
|
computedPercent(num, count) { |
|
|
|
return ((num * 100) / count) |
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
}, |
|
|
|
getConcatList() { |
|
|
|
|
|
|
|
this.$api |
|
|
|
.post('/data/aggregator/questionnaire/itemresdetail-concat', { |
|
|
|
projectKey: this.$route.query.key |
|
|
|
}) |
|
|
|
.then((res) => { |
|
|
|
this.dialogData = res.data.dataMap |
|
|
|
this.dialogHeader = res.data.tableHeaderList |
|
|
|
}) |
|
|
|
}, |
|
|
|
async handleOpen(item) { |
|
|
|
if (item.type === 'SWITCH' || item.type === 'NUMBER_INPUT') return false |
|
|
|
|
|
|
|
this.dialogTitle = item.label |
|
|
|
if (item.moduleType && item.moduleType === 'concat') { |
|
|
|
await this.getConcatList() |
|
|
|
} else { |
|
|
|
this.dialogHeader.push(item) |
|
|
|
await this.getInputList(item.formItemId, item.type) |
|
|
|
} |
|
|
|
|
|
|
|
this.dialogTableVisible = true |
|
|
|
}, |
|
|
|
handleClose() { |
|
|
|
this.dialogHeader = [] |
|
|
|
this.dialogTitle = '' |
|
|
|
this.dialogData = [] |
|
|
|
this.dialogTableVisible = false |
|
|
|
}, |
|
|
|
computedCount(type) { |
|
|
|
const arr = [ |
|
|
|
'PROVINCE_CITY', |
|
|
|
'NUMBER_INPUT', |
|
|
|
'SWITCH', |
|
|
|
'INPUT', |
|
|
|
'TEXTAREA', |
|
|
|
'INPUT_MAP', |
|
|
|
'TIME', |
|
|
|
'DATE_RANGE', |
|
|
|
'DATE', |
|
|
|
'TIME_RANGE' |
|
|
|
] |
|
|
|
return arr.includes(type) |
|
|
|
}, |
|
|
|
computedPercent(num, count) { |
|
|
|
return (num * 100) / count |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
@ -275,7 +367,8 @@ export default { |
|
|
|
.cell-wrapper { |
|
|
|
width: 100%; |
|
|
|
border: 1px solid #eee; |
|
|
|
.cell, .cell-value { |
|
|
|
.cell, |
|
|
|
.cell-value { |
|
|
|
widows: 100%; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
@ -289,7 +382,6 @@ export default { |
|
|
|
width: 60%; |
|
|
|
box-sizing: border-box; |
|
|
|
padding-left: 10px; |
|
|
|
|
|
|
|
} |
|
|
|
.cell-value { |
|
|
|
width: 40%; |
|
|
@ -325,6 +417,5 @@ export default { |
|
|
|
font-size: 14rpx; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
</style> |
|
|
|
|
|
|
|