feat: 新增包装测试
This commit is contained in:
@@ -7,7 +7,10 @@
|
||||
// 600=包装测试-标准(600_),601=包装测试-快速(601_),602=包装测试-配对(602_)
|
||||
export const showInsightTemplateType = [300, 301, 500, 501, 600, 601]; // 显示洞察报告 tab 的 template_type
|
||||
|
||||
// 看板类型:1=概念标准版,2=概念快测版,3=概念配对版,4=口味标准版,5=口味快测版,6=口味配对版
|
||||
// 看板类型:
|
||||
// 1=概念标准版,2=概念快测版,3=概念配对版,
|
||||
// 4=口味标准版,5=口味快测版,6=口味配对版
|
||||
// 7=包装标准版,8=包装快测版,9=包装配对版
|
||||
export const reportTypeEnum = {
|
||||
concept_standard: 1,
|
||||
concept_quick: 2,
|
||||
@@ -32,11 +35,6 @@ export const reportTypeLabelMap = {
|
||||
[reportTypeEnum.package_pair]: '包装'
|
||||
};
|
||||
|
||||
export const sectionShownTypeEnum = {
|
||||
show: 2,
|
||||
hide: 1
|
||||
};
|
||||
|
||||
// 检查是否需要显示 “洞察报告” 这个标签页
|
||||
// 仅标准版和快测版问卷显示该菜单
|
||||
export function checkShowInsightTab({ templateType } = {}) {
|
||||
@@ -59,8 +57,29 @@ export function getInsightTypeStr(templateType) {
|
||||
return labelMap[templateType] || '';
|
||||
}
|
||||
|
||||
export const sectionShownTypeEnum = {
|
||||
show: 2,
|
||||
hide: 1
|
||||
};
|
||||
|
||||
export const testItemTypeEnum = {
|
||||
newest: 1,
|
||||
standard: 0,
|
||||
|
||||
1: 'newest',
|
||||
0: 'standard'
|
||||
};
|
||||
|
||||
export const testItemTypeLabelMap = {
|
||||
[testItemTypeEnum.newest]: '新品',
|
||||
[testItemTypeEnum.standard]: '标杆'
|
||||
};
|
||||
|
||||
export const reportUpdatingMessageText = '报告更新中,不能修改';
|
||||
|
||||
export const codeList = ['概念编码', '口味编码', '包装编码'];
|
||||
export const italicCodeList = [...codeList, '样本基数'];
|
||||
|
||||
// 报告表格某些行需要显示选择框,并且可以修改,此列表为区分此功能的文字
|
||||
export const selectionList = [
|
||||
'是否通过概念行动标准',
|
||||
|
||||
@@ -5,6 +5,7 @@ import Overview from './section/Overview.vue';
|
||||
import ProjectNameAndDecisionCriteria from './section/ProjectNameAndDecisionCriteria.vue';
|
||||
import TestingConcept from './section/TestingConcept.vue';
|
||||
import TestingTaste from './section/TestingTaste.vue';
|
||||
import TestingPackage from './section/TestingPackage.vue';
|
||||
|
||||
import GroupTab from './section/GroupTab.vue';
|
||||
import CoreConclusion from './section/CoreConclusion.vue';
|
||||
@@ -43,8 +44,10 @@ const readonly = computed(() => props.readonly || false);
|
||||
const updating = computed(() => props.updating || false);
|
||||
|
||||
// 快测版报告内容和标准版基本一致,区别为快测版没有概念诊断部分
|
||||
// 看板类型:1=标准版,2=快测版,3=配对版,添加了口味,请参考下一行
|
||||
// 看板类型:1=概念标准版,2=概念快测版,3=概念配对版,4=口味标准版,5=口味快测版,6=口味配对版
|
||||
// 看板类型:
|
||||
// 1=概念标准版,2=概念快测版,3=概念配对版,
|
||||
// 4=口味标准版,5=口味快测版,6=口味配对版
|
||||
// 7=包装标准版,8=包装快测版,9=包装配对版
|
||||
const type = computed(() => +props.report?.type);
|
||||
|
||||
const testCom = computed(() => {
|
||||
@@ -57,6 +60,10 @@ const testCom = computed(() => {
|
||||
case reportTypeEnum.taste_quick:
|
||||
case reportTypeEnum.taste_pair:
|
||||
return TestingTaste;
|
||||
case reportTypeEnum.package_standard:
|
||||
case reportTypeEnum.package_quick:
|
||||
case reportTypeEnum.package_pair:
|
||||
return TestingPackage;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -69,8 +76,8 @@ const comList = computed(() => {
|
||||
|
||||
list.push(ProjectNameAndDecisionCriteria); // 项目名称及概念决策标准
|
||||
list.push(testCom.value); // 测试概念/测试口味/测试包装
|
||||
list.push(GroupTab); // tab 切换
|
||||
list.push(CoreConclusion); // 核心结论
|
||||
list.push(GroupTab); // tab 切换
|
||||
list.push(DecisionIndicators); // 决策指标
|
||||
|
||||
if (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { computed, defineEmits, defineProps, ref, watch } from 'vue';
|
||||
import { selectionList } from '../../consts';
|
||||
import { selectionList, italicCodeList } from '../../consts';
|
||||
import { sortListForTableColSpan } from '../../util';
|
||||
|
||||
const emits = defineEmits(['change']);
|
||||
@@ -74,6 +74,7 @@ const headers = computed(() => {
|
||||
text = text || '';
|
||||
}
|
||||
|
||||
let idx = index;
|
||||
let rowSpan = 0;
|
||||
const tempForEqStr = tableData.value[index - 1]?.[rowTitle.dataIndex];
|
||||
const tempForEqArr = tempForEqStr?.split?.('_')?.slice?.(0, i + 1);
|
||||
@@ -88,7 +89,11 @@ const headers = computed(() => {
|
||||
?.split?.('_')
|
||||
?.slice?.(0, i + 1)
|
||||
?.join?.('_');
|
||||
return !!(index <= recordIndex && temp && fieldForEq === temp);
|
||||
if (idx === recordIndex && temp && fieldForEq === temp) {
|
||||
idx += 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}).length;
|
||||
}
|
||||
|
||||
@@ -154,12 +159,12 @@ const columns = computed(() =>
|
||||
column.customCell = function (record) {
|
||||
const style = {};
|
||||
if (columnIndex === 0) {
|
||||
if (['概念编码', '口味编码', '样本基数'].includes(record[column.dataIndex])) {
|
||||
if (italicCodeList.includes(record[column.dataIndex])) {
|
||||
style['font-style'] = 'italic';
|
||||
}
|
||||
}
|
||||
if (columnIndex > 0) {
|
||||
if (['概念编码', '口味编码', '样本基数'].some((key) => record[column.dataIndex]?.indexOf?.(key) > -1)) {
|
||||
if (italicCodeList.some((key) => record[column.dataIndex]?.indexOf?.(key) > -1)) {
|
||||
style['font-style'] = 'italic';
|
||||
}
|
||||
}
|
||||
@@ -254,7 +259,7 @@ watch(
|
||||
const numericalColumns = flatColumns.value.map((key) => key.dataIndex).slice(1);
|
||||
|
||||
tableData.value.forEach((record) => {
|
||||
if (['概念编码', '口味编码', '样本基数'].includes(record[headers.value[0]?.dataIndex])) {
|
||||
if (italicCodeList.includes(record[headers.value[0]?.dataIndex])) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,10 +289,10 @@ const barStyle = computed(() => (record, column) => {
|
||||
});
|
||||
|
||||
function rowClassName(record) {
|
||||
// 表格中 '概念编码'、 '口味编码' 和 '样本基数' , 这几行要显示灰色
|
||||
return Object.keys(record).some((key) =>
|
||||
['概念编码', '口味编码', '样本基数'].some((item) => record[key]?.indexOf?.(item) > -1)
|
||||
)
|
||||
// 表格中 '概念编码'、 '口味编码'、 '包装编码' 和 '样本基数' , 这几行要显示灰色
|
||||
return Object.keys(record).some((key) => {
|
||||
return italicCodeList.some((item) => record[key]?.indexOf?.(item) > -1);
|
||||
})
|
||||
? 'gray-row'
|
||||
: '';
|
||||
}
|
||||
@@ -308,9 +313,11 @@ function getPopupContainer(el) {
|
||||
}
|
||||
|
||||
function cellClass(record, column, cols) {
|
||||
const columnIndex = cols.flatMap((i) => i.children || [i]).findIndex((col) => col.dataIndex === column.dataIndex);
|
||||
const columnIndex = cols
|
||||
.flatMap((i) => i.children || [i])
|
||||
.findIndex((col) => col.dataIndex === column.dataIndex);
|
||||
|
||||
const isStaticCell = ['概念编码', '口味编码', '样本基数'].some((key) => record[cols[0]?.dataIndex].indexOf(key) > -1);
|
||||
const isStaticCell = italicCodeList.some((key) => record[cols[0]?.dataIndex].indexOf(key) > -1);
|
||||
|
||||
const isStrokeCell = record[cols[0]?.dataIndex].toLowerCase().indexOf('top') > -1 && columnIndex > 0;
|
||||
|
||||
@@ -340,8 +347,7 @@ function cellClass(record, column, cols) {
|
||||
<template v-if="props.barTable" data-desc="显示条形图">
|
||||
<span
|
||||
v-if="
|
||||
[0].includes(columnIndex) ||
|
||||
['概念编码', '口味编码', '样本基数'].includes(record[headers[0]?.dataIndex])
|
||||
[0].includes(columnIndex) || italicCodeList.includes(record[headers[0]?.dataIndex])
|
||||
"
|
||||
:class="cellClass(record, column, columns)"
|
||||
>
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
<script setup>
|
||||
import { defineEmits, defineProps, ref, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons-vue';
|
||||
import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import SectionTitle from '../../components/SectionTitle.vue';
|
||||
import Section from '../../components/Section.vue';
|
||||
import SectionTitle from '../../components/SectionTitle.vue';
|
||||
import StyledTable from '../components/StyledTable.vue';
|
||||
|
||||
import { defaultSectionEmits, defaultSectionProps, reportUpdatingMessageText } from '../../consts';
|
||||
import {
|
||||
codeList,
|
||||
defaultSectionEmits,
|
||||
defaultSectionProps,
|
||||
reportUpdatingMessageText
|
||||
} from '../../consts';
|
||||
|
||||
import { getRowTitleColumnWidth } from '../../util';
|
||||
|
||||
const emits = defineEmits(defaultSectionEmits);
|
||||
const props = defineProps(defaultSectionProps);
|
||||
@@ -42,7 +49,7 @@ watch(
|
||||
canHide: true,
|
||||
visible: props.report.genderQuoteHidden === 2,
|
||||
visibleField: 'genderQuoteHidden',
|
||||
rowTitleColumnWidthList: [120, 280],
|
||||
rowTitleColumnWidthList: getRowTitleColumnWidth(gender),
|
||||
tableData: gender,
|
||||
codeStr: getTableCodeRow(gender)
|
||||
},
|
||||
@@ -52,7 +59,7 @@ watch(
|
||||
canHide: true,
|
||||
visible: props.report.ageQuotaHidden === 2,
|
||||
visibleField: 'ageQuotaHidden',
|
||||
rowTitleColumnWidthList: [120, 280],
|
||||
rowTitleColumnWidthList: getRowTitleColumnWidth(age),
|
||||
tableData: age,
|
||||
codeStr: getTableCodeRow(age)
|
||||
},
|
||||
@@ -62,7 +69,7 @@ watch(
|
||||
canHide: true,
|
||||
visible: props.report.incomeQuotaHidden === 2,
|
||||
visibleField: 'incomeQuotaHidden',
|
||||
rowTitleColumnWidthList: [160, 280],
|
||||
rowTitleColumnWidthList: getRowTitleColumnWidth(income),
|
||||
tableData: income,
|
||||
codeStr: getTableCodeRow(income)
|
||||
},
|
||||
@@ -72,7 +79,7 @@ watch(
|
||||
canHide: true,
|
||||
visible: props.report.cityLevelQuotaHidden === 2,
|
||||
visibleField: 'cityLevelQuotaHidden',
|
||||
rowTitleColumnWidthList: [120, 280],
|
||||
rowTitleColumnWidthList: getRowTitleColumnWidth(city),
|
||||
tableData: city,
|
||||
codeStr: getTableCodeRow(city)
|
||||
}
|
||||
@@ -90,7 +97,7 @@ function getTableCodeRow(tableData) {
|
||||
return '';
|
||||
}
|
||||
const codeRow = tableData.dataVOS.find((row) =>
|
||||
Object.keys(row).find((key) => ['概念编码', '口味编码'].includes(row[key]))
|
||||
Object.keys(row).find((key) => codeList.includes(row[key]))
|
||||
);
|
||||
if (!codeRow) {
|
||||
return '';
|
||||
|
||||
@@ -5,7 +5,7 @@ import SectionTitle from '../../components/SectionTitle.vue';
|
||||
import Section from '../../components/Section.vue';
|
||||
import StyledTable from '../components/StyledTable.vue';
|
||||
|
||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
||||
import { defaultSectionEmits, defaultSectionProps, codeList } from '../../consts';
|
||||
|
||||
const emits = defineEmits(defaultSectionEmits);
|
||||
const props = defineProps(defaultSectionProps);
|
||||
@@ -20,7 +20,7 @@ function getTableCodeRow(tableData) {
|
||||
return '';
|
||||
}
|
||||
const codeRow = tableData.dataVOS.find((row) =>
|
||||
Object.keys(row).find((key) => ['概念编码', '口味编码'].includes(row[key]))
|
||||
Object.keys(row).find((key) => codeList.includes(row[key]))
|
||||
);
|
||||
if (!codeRow) {
|
||||
return '';
|
||||
@@ -35,7 +35,7 @@ function getTableCodeRow(tableData) {
|
||||
<template>
|
||||
<SectionTitle>其他关键指标</SectionTitle>
|
||||
<Section class="section">
|
||||
<StyledTable :data="tableData" :row-title-column-width-list="[140, 260]" />
|
||||
<StyledTable :data="tableData" :row-title-column-width-list="[140, 280]" />
|
||||
|
||||
<div class="message">
|
||||
<span class="emphasize">{{ codeStr }}</span>
|
||||
|
||||
128
src/views/DataAnalyse/insight/report/section/TestingBase.vue
Normal file
128
src/views/DataAnalyse/insight/report/section/TestingBase.vue
Normal file
@@ -0,0 +1,128 @@
|
||||
<script setup>
|
||||
import { computed, defineEmits, defineProps } from 'vue';
|
||||
|
||||
import SectionTitle from '../../components/SectionTitle.vue';
|
||||
import Section from '../../components/Section.vue';
|
||||
|
||||
import { defaultSectionEmits, defaultSectionProps, testItemTypeEnum } from '../../consts';
|
||||
|
||||
const emits = defineEmits(defaultSectionEmits);
|
||||
const props = defineProps(defaultSectionProps);
|
||||
|
||||
const list = computed(() => {
|
||||
const result = [];
|
||||
props.report?.config?.forEach((item) => {
|
||||
const current = result.find((record) => record.group === item.group);
|
||||
if (current) {
|
||||
current.children.push(item);
|
||||
} else {
|
||||
result.push({ group: item.group, children: [item] });
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SectionTitle><slot name="name">测试</slot></SectionTitle>
|
||||
<Section class="section">
|
||||
<div v-for="(group, index) in list" :key="index" class="list scrollbar">
|
||||
<div
|
||||
v-for="item in group.children"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:class="{ [testItemTypeEnum[item.concept_type]]: true }"
|
||||
>
|
||||
<div class="name">
|
||||
<a-tooltip>
|
||||
<template #title>{{ item.concept_name || '' }}</template>
|
||||
<div class="text">{{ item.concept_name || '' }}</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
<img v-if="item.concept_url" :src="item.concept_url" alt="" class="img" />
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.section {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.list {
|
||||
overflow-x: auto;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.item {
|
||||
overflow: hidden;
|
||||
flex: none;
|
||||
width: 198px;
|
||||
height: 152px;
|
||||
margin-right: 2px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #dfe0e3;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 18px;
|
||||
}
|
||||
|
||||
&.newest .name {
|
||||
color: #70b936;
|
||||
background: rgba(112, 185, 54, 0.16);
|
||||
|
||||
&::before {
|
||||
background-color: #70b936;
|
||||
}
|
||||
}
|
||||
|
||||
&.standard .name {
|
||||
color: #ffaa00;
|
||||
background: rgba(255, 170, 0, 0.16);
|
||||
|
||||
&::before {
|
||||
background-color: #ffaa00;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
border: none;
|
||||
padding: 0 10px;
|
||||
|
||||
&::before {
|
||||
flex: none;
|
||||
display: block;
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-right: 4px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border: none;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,124 +1,18 @@
|
||||
<script setup>
|
||||
import { computed, defineEmits, defineProps } from 'vue';
|
||||
|
||||
import SectionTitle from '../../components/SectionTitle.vue';
|
||||
import Section from '../../components/Section.vue';
|
||||
import { defineEmits, defineProps } from 'vue';
|
||||
|
||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
||||
|
||||
const emits = defineEmits(defaultSectionEmits);
|
||||
const props = defineProps(defaultSectionProps);
|
||||
|
||||
const conceptTypeEnum = {
|
||||
newest: 1,
|
||||
standard: 0,
|
||||
|
||||
1: 'newest',
|
||||
0: 'standard'
|
||||
};
|
||||
|
||||
const list = computed(() => props.report?.config || []);
|
||||
import TestingBase from './TestingBase.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SectionTitle>测试概念</SectionTitle>
|
||||
<Section class="section">
|
||||
<div class="list scrollbar">
|
||||
<div
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:class="{ [conceptTypeEnum[item.concept_type]]: true }"
|
||||
>
|
||||
<div class="name">
|
||||
<a-tooltip>
|
||||
<template #title>{{ item.concept_name || '' }}</template>
|
||||
<div class="text">{{ item.concept_name || '' }}</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
<img v-if="item.concept_url" :src="item.concept_url" alt="" class="img" />
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
<TestingBase :report="props.report">
|
||||
<template #name>测试概念</template>
|
||||
</TestingBase>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.section {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.list {
|
||||
overflow-x: auto;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.item {
|
||||
overflow: hidden;
|
||||
flex: none;
|
||||
width: 198px;
|
||||
height: 152px;
|
||||
margin-right: 2px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #dfe0e3;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 18px;
|
||||
}
|
||||
|
||||
&.newest .name {
|
||||
color: #70b936;
|
||||
background: rgba(112, 185, 54, 0.16);
|
||||
|
||||
&::before {
|
||||
background-color: #70b936;
|
||||
}
|
||||
}
|
||||
|
||||
&.standard .name {
|
||||
color: #ffaa00;
|
||||
background: rgba(255, 170, 0, 0.16);
|
||||
|
||||
&::before {
|
||||
background-color: #ffaa00;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
border: none;
|
||||
padding: 0 10px;
|
||||
|
||||
&::before {
|
||||
flex: none;
|
||||
display: block;
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-right: 4px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
border: none;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<script setup>
|
||||
import { defineEmits, defineProps } from 'vue';
|
||||
|
||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
||||
|
||||
const emits = defineEmits(defaultSectionEmits);
|
||||
const props = defineProps(defaultSectionProps);
|
||||
|
||||
import TestingBase from './TestingBase.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TestingBase :report="props.report">
|
||||
<template #name>测试包装</template>
|
||||
</TestingBase>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -4,19 +4,11 @@ import { computed, defineEmits, defineProps } from 'vue';
|
||||
import SectionTitle from '../../components/SectionTitle.vue';
|
||||
import Section from '../../components/Section.vue';
|
||||
|
||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
||||
import { defaultSectionEmits, defaultSectionProps, testItemTypeEnum } from '../../consts';
|
||||
|
||||
const emits = defineEmits(defaultSectionEmits);
|
||||
const props = defineProps(defaultSectionProps);
|
||||
|
||||
const typeEnum = {
|
||||
newest: 1,
|
||||
standard: 0,
|
||||
|
||||
1: 'newest',
|
||||
0: 'standard'
|
||||
};
|
||||
|
||||
const typeLabelMap = {
|
||||
1: '新品口味',
|
||||
0: '标杆口味'
|
||||
@@ -33,7 +25,7 @@ const list = computed(() => props.report?.config || []);
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:class="{ [typeEnum[item.concept_type]]: true }"
|
||||
:class="{ [testItemTypeEnum[item.concept_type]]: true }"
|
||||
>
|
||||
<div class="code">
|
||||
{{ typeLabelMap[item.concept_type] || '' }}{{ item.concept_encode || '' }}
|
||||
|
||||
@@ -40,19 +40,19 @@ watch(
|
||||
child.question.list.forEach((group) => {
|
||||
group.options?.forEach?.((option) => {
|
||||
option.option_config.__rate__ = hotData.find((data) => {
|
||||
if (data.key !== header.key) {
|
||||
return false;
|
||||
}
|
||||
if (data.index.startsWith('Q')) {
|
||||
const [temp, questionIndex] = /Q(\d*)A(\d*)/g.exec(data.index);
|
||||
if (data.key !== header.key) {
|
||||
return false;
|
||||
}
|
||||
if (data.index.startsWith('Q')) {
|
||||
const [temp, questionIndex] = /Q(\d*)A(\d*)/g.exec(data.index);
|
||||
|
||||
if (group.relation_question_index === +questionIndex) {
|
||||
return data.index === option.option_key;
|
||||
}
|
||||
} else {
|
||||
return +data.index === +option.option_key;
|
||||
if (group.relation_question_index === +questionIndex) {
|
||||
return data.index === option.option_key;
|
||||
}
|
||||
})?.rate || 0;
|
||||
} else {
|
||||
return +data.index === +option.option_key;
|
||||
}
|
||||
})?.rate || 0;
|
||||
option.option_config.__rate__ += '%';
|
||||
});
|
||||
});
|
||||
|
||||
@@ -195,7 +195,9 @@ function downloadHotAreaImage() {
|
||||
ctx.fillStyle = '#FFFFFF';
|
||||
ctx.roundRect(
|
||||
textLeft - 4,
|
||||
textTop - (textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent) * 0.5 - 6,
|
||||
textTop
|
||||
- (textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent) * 0.5
|
||||
- 6,
|
||||
textMetrics.width + 8,
|
||||
textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent + 8,
|
||||
4
|
||||
|
||||
@@ -4,6 +4,8 @@ import { computed, defineProps } from 'vue';
|
||||
import Section from '../../../components/Section.vue';
|
||||
import StyledTable from '../../components/StyledTable.vue';
|
||||
|
||||
import { codeList } from '../../../consts';
|
||||
|
||||
const props = defineProps({
|
||||
report: { type: Object, default: () => Object.assign({}) }
|
||||
});
|
||||
@@ -16,7 +18,7 @@ function getTableCodeRow(tableData) {
|
||||
return '';
|
||||
}
|
||||
const codeRow = tableData.dataVOS.find((row) =>
|
||||
Object.keys(row).find((key) => ['概念编码', '口味编码'].includes(row[key]))
|
||||
Object.keys(row).find((key) => codeList.includes(row[key]))
|
||||
);
|
||||
if (!codeRow) {
|
||||
return '';
|
||||
|
||||
@@ -56,3 +56,51 @@ export function sortListForTableColSpan(options = {}) {
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算表格行的表头的宽度
|
||||
* @param data
|
||||
* @param data.headerVOS {array} 表格的列的表头
|
||||
* @param data.dataVOS {array} 表格的数据
|
||||
* @returns {*|[]|number[]|undefined}
|
||||
*/
|
||||
export function getRowTitleColumnWidth(data) {
|
||||
if (!data) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const header = data.headerVOS || [];
|
||||
const tableData = data.dataVOS || [];
|
||||
|
||||
const rowTitleIndex = header[0]?.dataIndex;
|
||||
|
||||
if (!rowTitleIndex) {
|
||||
return [280, 280];
|
||||
}
|
||||
|
||||
const widthList = tableData.map((item) => {
|
||||
const rowTitleList = item[rowTitleIndex].split('_');
|
||||
|
||||
if (rowTitleList.length > 1) {
|
||||
return rowTitleList.map((str) => str.length * 14 + 36);
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
return widthList.reduce((prev, curr) => {
|
||||
if (!prev?.length) {
|
||||
return curr;
|
||||
}
|
||||
if (!curr?.length) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
curr.forEach((currWidth, index) => {
|
||||
prev[index] = Math.max(currWidth, prev[index], 120);
|
||||
prev[index] = Math.ceil(prev[index] * 0.1) * 10;
|
||||
});
|
||||
|
||||
return prev;
|
||||
}, []);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user