feat: 新增包装测试
This commit is contained in:
@@ -7,7 +7,10 @@
|
|||||||
// 600=包装测试-标准(600_),601=包装测试-快速(601_),602=包装测试-配对(602_)
|
// 600=包装测试-标准(600_),601=包装测试-快速(601_),602=包装测试-配对(602_)
|
||||||
export const showInsightTemplateType = [300, 301, 500, 501, 600, 601]; // 显示洞察报告 tab 的 template_type
|
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 = {
|
export const reportTypeEnum = {
|
||||||
concept_standard: 1,
|
concept_standard: 1,
|
||||||
concept_quick: 2,
|
concept_quick: 2,
|
||||||
@@ -32,11 +35,6 @@ export const reportTypeLabelMap = {
|
|||||||
[reportTypeEnum.package_pair]: '包装'
|
[reportTypeEnum.package_pair]: '包装'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sectionShownTypeEnum = {
|
|
||||||
show: 2,
|
|
||||||
hide: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
// 检查是否需要显示 “洞察报告” 这个标签页
|
// 检查是否需要显示 “洞察报告” 这个标签页
|
||||||
// 仅标准版和快测版问卷显示该菜单
|
// 仅标准版和快测版问卷显示该菜单
|
||||||
export function checkShowInsightTab({ templateType } = {}) {
|
export function checkShowInsightTab({ templateType } = {}) {
|
||||||
@@ -59,8 +57,29 @@ export function getInsightTypeStr(templateType) {
|
|||||||
return labelMap[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 reportUpdatingMessageText = '报告更新中,不能修改';
|
||||||
|
|
||||||
|
export const codeList = ['概念编码', '口味编码', '包装编码'];
|
||||||
|
export const italicCodeList = [...codeList, '样本基数'];
|
||||||
|
|
||||||
// 报告表格某些行需要显示选择框,并且可以修改,此列表为区分此功能的文字
|
// 报告表格某些行需要显示选择框,并且可以修改,此列表为区分此功能的文字
|
||||||
export const selectionList = [
|
export const selectionList = [
|
||||||
'是否通过概念行动标准',
|
'是否通过概念行动标准',
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Overview from './section/Overview.vue';
|
|||||||
import ProjectNameAndDecisionCriteria from './section/ProjectNameAndDecisionCriteria.vue';
|
import ProjectNameAndDecisionCriteria from './section/ProjectNameAndDecisionCriteria.vue';
|
||||||
import TestingConcept from './section/TestingConcept.vue';
|
import TestingConcept from './section/TestingConcept.vue';
|
||||||
import TestingTaste from './section/TestingTaste.vue';
|
import TestingTaste from './section/TestingTaste.vue';
|
||||||
|
import TestingPackage from './section/TestingPackage.vue';
|
||||||
|
|
||||||
import GroupTab from './section/GroupTab.vue';
|
import GroupTab from './section/GroupTab.vue';
|
||||||
import CoreConclusion from './section/CoreConclusion.vue';
|
import CoreConclusion from './section/CoreConclusion.vue';
|
||||||
@@ -43,8 +44,10 @@ const readonly = computed(() => props.readonly || false);
|
|||||||
const updating = computed(() => props.updating || 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 type = computed(() => +props.report?.type);
|
||||||
|
|
||||||
const testCom = computed(() => {
|
const testCom = computed(() => {
|
||||||
@@ -57,6 +60,10 @@ const testCom = computed(() => {
|
|||||||
case reportTypeEnum.taste_quick:
|
case reportTypeEnum.taste_quick:
|
||||||
case reportTypeEnum.taste_pair:
|
case reportTypeEnum.taste_pair:
|
||||||
return TestingTaste;
|
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(ProjectNameAndDecisionCriteria); // 项目名称及概念决策标准
|
||||||
list.push(testCom.value); // 测试概念/测试口味/测试包装
|
list.push(testCom.value); // 测试概念/测试口味/测试包装
|
||||||
list.push(GroupTab); // tab 切换
|
|
||||||
list.push(CoreConclusion); // 核心结论
|
list.push(CoreConclusion); // 核心结论
|
||||||
|
list.push(GroupTab); // tab 切换
|
||||||
list.push(DecisionIndicators); // 决策指标
|
list.push(DecisionIndicators); // 决策指标
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, defineEmits, defineProps, ref, watch } from 'vue';
|
import { computed, defineEmits, defineProps, ref, watch } from 'vue';
|
||||||
import { selectionList } from '../../consts';
|
import { selectionList, italicCodeList } from '../../consts';
|
||||||
import { sortListForTableColSpan } from '../../util';
|
import { sortListForTableColSpan } from '../../util';
|
||||||
|
|
||||||
const emits = defineEmits(['change']);
|
const emits = defineEmits(['change']);
|
||||||
@@ -74,6 +74,7 @@ const headers = computed(() => {
|
|||||||
text = text || '';
|
text = text || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let idx = index;
|
||||||
let rowSpan = 0;
|
let rowSpan = 0;
|
||||||
const tempForEqStr = tableData.value[index - 1]?.[rowTitle.dataIndex];
|
const tempForEqStr = tableData.value[index - 1]?.[rowTitle.dataIndex];
|
||||||
const tempForEqArr = tempForEqStr?.split?.('_')?.slice?.(0, i + 1);
|
const tempForEqArr = tempForEqStr?.split?.('_')?.slice?.(0, i + 1);
|
||||||
@@ -88,7 +89,11 @@ const headers = computed(() => {
|
|||||||
?.split?.('_')
|
?.split?.('_')
|
||||||
?.slice?.(0, i + 1)
|
?.slice?.(0, i + 1)
|
||||||
?.join?.('_');
|
?.join?.('_');
|
||||||
return !!(index <= recordIndex && temp && fieldForEq === temp);
|
if (idx === recordIndex && temp && fieldForEq === temp) {
|
||||||
|
idx += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}).length;
|
}).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +159,12 @@ const columns = computed(() =>
|
|||||||
column.customCell = function (record) {
|
column.customCell = function (record) {
|
||||||
const style = {};
|
const style = {};
|
||||||
if (columnIndex === 0) {
|
if (columnIndex === 0) {
|
||||||
if (['概念编码', '口味编码', '样本基数'].includes(record[column.dataIndex])) {
|
if (italicCodeList.includes(record[column.dataIndex])) {
|
||||||
style['font-style'] = 'italic';
|
style['font-style'] = 'italic';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (columnIndex > 0) {
|
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';
|
style['font-style'] = 'italic';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,7 +259,7 @@ watch(
|
|||||||
const numericalColumns = flatColumns.value.map((key) => key.dataIndex).slice(1);
|
const numericalColumns = flatColumns.value.map((key) => key.dataIndex).slice(1);
|
||||||
|
|
||||||
tableData.value.forEach((record) => {
|
tableData.value.forEach((record) => {
|
||||||
if (['概念编码', '口味编码', '样本基数'].includes(record[headers.value[0]?.dataIndex])) {
|
if (italicCodeList.includes(record[headers.value[0]?.dataIndex])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,10 +289,10 @@ const barStyle = computed(() => (record, column) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function rowClassName(record) {
|
function rowClassName(record) {
|
||||||
// 表格中 '概念编码'、 '口味编码' 和 '样本基数' , 这几行要显示灰色
|
// 表格中 '概念编码'、 '口味编码'、 '包装编码' 和 '样本基数' , 这几行要显示灰色
|
||||||
return Object.keys(record).some((key) =>
|
return Object.keys(record).some((key) => {
|
||||||
['概念编码', '口味编码', '样本基数'].some((item) => record[key]?.indexOf?.(item) > -1)
|
return italicCodeList.some((item) => record[key]?.indexOf?.(item) > -1);
|
||||||
)
|
})
|
||||||
? 'gray-row'
|
? 'gray-row'
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
@@ -308,9 +313,11 @@ function getPopupContainer(el) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cellClass(record, column, cols) {
|
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;
|
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="显示条形图">
|
<template v-if="props.barTable" data-desc="显示条形图">
|
||||||
<span
|
<span
|
||||||
v-if="
|
v-if="
|
||||||
[0].includes(columnIndex) ||
|
[0].includes(columnIndex) || italicCodeList.includes(record[headers[0]?.dataIndex])
|
||||||
['概念编码', '口味编码', '样本基数'].includes(record[headers[0]?.dataIndex])
|
|
||||||
"
|
"
|
||||||
:class="cellClass(record, column, columns)"
|
:class="cellClass(record, column, columns)"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { defineEmits, defineProps, ref, watch } from 'vue';
|
import { defineEmits, defineProps, ref, watch } from 'vue';
|
||||||
import { message } from 'ant-design-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 Section from '../../components/Section.vue';
|
||||||
|
import SectionTitle from '../../components/SectionTitle.vue';
|
||||||
import StyledTable from '../components/StyledTable.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 emits = defineEmits(defaultSectionEmits);
|
||||||
const props = defineProps(defaultSectionProps);
|
const props = defineProps(defaultSectionProps);
|
||||||
@@ -42,7 +49,7 @@ watch(
|
|||||||
canHide: true,
|
canHide: true,
|
||||||
visible: props.report.genderQuoteHidden === 2,
|
visible: props.report.genderQuoteHidden === 2,
|
||||||
visibleField: 'genderQuoteHidden',
|
visibleField: 'genderQuoteHidden',
|
||||||
rowTitleColumnWidthList: [120, 280],
|
rowTitleColumnWidthList: getRowTitleColumnWidth(gender),
|
||||||
tableData: gender,
|
tableData: gender,
|
||||||
codeStr: getTableCodeRow(gender)
|
codeStr: getTableCodeRow(gender)
|
||||||
},
|
},
|
||||||
@@ -52,7 +59,7 @@ watch(
|
|||||||
canHide: true,
|
canHide: true,
|
||||||
visible: props.report.ageQuotaHidden === 2,
|
visible: props.report.ageQuotaHidden === 2,
|
||||||
visibleField: 'ageQuotaHidden',
|
visibleField: 'ageQuotaHidden',
|
||||||
rowTitleColumnWidthList: [120, 280],
|
rowTitleColumnWidthList: getRowTitleColumnWidth(age),
|
||||||
tableData: age,
|
tableData: age,
|
||||||
codeStr: getTableCodeRow(age)
|
codeStr: getTableCodeRow(age)
|
||||||
},
|
},
|
||||||
@@ -62,7 +69,7 @@ watch(
|
|||||||
canHide: true,
|
canHide: true,
|
||||||
visible: props.report.incomeQuotaHidden === 2,
|
visible: props.report.incomeQuotaHidden === 2,
|
||||||
visibleField: 'incomeQuotaHidden',
|
visibleField: 'incomeQuotaHidden',
|
||||||
rowTitleColumnWidthList: [160, 280],
|
rowTitleColumnWidthList: getRowTitleColumnWidth(income),
|
||||||
tableData: income,
|
tableData: income,
|
||||||
codeStr: getTableCodeRow(income)
|
codeStr: getTableCodeRow(income)
|
||||||
},
|
},
|
||||||
@@ -72,7 +79,7 @@ watch(
|
|||||||
canHide: true,
|
canHide: true,
|
||||||
visible: props.report.cityLevelQuotaHidden === 2,
|
visible: props.report.cityLevelQuotaHidden === 2,
|
||||||
visibleField: 'cityLevelQuotaHidden',
|
visibleField: 'cityLevelQuotaHidden',
|
||||||
rowTitleColumnWidthList: [120, 280],
|
rowTitleColumnWidthList: getRowTitleColumnWidth(city),
|
||||||
tableData: city,
|
tableData: city,
|
||||||
codeStr: getTableCodeRow(city)
|
codeStr: getTableCodeRow(city)
|
||||||
}
|
}
|
||||||
@@ -90,7 +97,7 @@ function getTableCodeRow(tableData) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const codeRow = tableData.dataVOS.find((row) =>
|
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) {
|
if (!codeRow) {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import SectionTitle from '../../components/SectionTitle.vue';
|
|||||||
import Section from '../../components/Section.vue';
|
import Section from '../../components/Section.vue';
|
||||||
import StyledTable from '../components/StyledTable.vue';
|
import StyledTable from '../components/StyledTable.vue';
|
||||||
|
|
||||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
import { defaultSectionEmits, defaultSectionProps, codeList } from '../../consts';
|
||||||
|
|
||||||
const emits = defineEmits(defaultSectionEmits);
|
const emits = defineEmits(defaultSectionEmits);
|
||||||
const props = defineProps(defaultSectionProps);
|
const props = defineProps(defaultSectionProps);
|
||||||
@@ -20,7 +20,7 @@ function getTableCodeRow(tableData) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const codeRow = tableData.dataVOS.find((row) =>
|
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) {
|
if (!codeRow) {
|
||||||
return '';
|
return '';
|
||||||
@@ -35,7 +35,7 @@ function getTableCodeRow(tableData) {
|
|||||||
<template>
|
<template>
|
||||||
<SectionTitle>其他关键指标</SectionTitle>
|
<SectionTitle>其他关键指标</SectionTitle>
|
||||||
<Section class="section">
|
<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">
|
<div class="message">
|
||||||
<span class="emphasize">{{ codeStr }}</span>
|
<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>
|
<script setup>
|
||||||
import { computed, defineEmits, defineProps } from 'vue';
|
import { defineEmits, defineProps } from 'vue';
|
||||||
|
|
||||||
import SectionTitle from '../../components/SectionTitle.vue';
|
|
||||||
import Section from '../../components/Section.vue';
|
|
||||||
|
|
||||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
||||||
|
|
||||||
const emits = defineEmits(defaultSectionEmits);
|
const emits = defineEmits(defaultSectionEmits);
|
||||||
const props = defineProps(defaultSectionProps);
|
const props = defineProps(defaultSectionProps);
|
||||||
|
|
||||||
const conceptTypeEnum = {
|
import TestingBase from './TestingBase.vue';
|
||||||
newest: 1,
|
|
||||||
standard: 0,
|
|
||||||
|
|
||||||
1: 'newest',
|
|
||||||
0: 'standard'
|
|
||||||
};
|
|
||||||
|
|
||||||
const list = computed(() => props.report?.config || []);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<SectionTitle>测试概念</SectionTitle>
|
<TestingBase :report="props.report">
|
||||||
<Section class="section">
|
<template #name>测试概念</template>
|
||||||
<div class="list scrollbar">
|
</TestingBase>
|
||||||
<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>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss"></style>
|
||||||
.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>
|
|
||||||
|
|||||||
@@ -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 SectionTitle from '../../components/SectionTitle.vue';
|
||||||
import Section from '../../components/Section.vue';
|
import Section from '../../components/Section.vue';
|
||||||
|
|
||||||
import { defaultSectionEmits, defaultSectionProps } from '../../consts';
|
import { defaultSectionEmits, defaultSectionProps, testItemTypeEnum } from '../../consts';
|
||||||
|
|
||||||
const emits = defineEmits(defaultSectionEmits);
|
const emits = defineEmits(defaultSectionEmits);
|
||||||
const props = defineProps(defaultSectionProps);
|
const props = defineProps(defaultSectionProps);
|
||||||
|
|
||||||
const typeEnum = {
|
|
||||||
newest: 1,
|
|
||||||
standard: 0,
|
|
||||||
|
|
||||||
1: 'newest',
|
|
||||||
0: 'standard'
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeLabelMap = {
|
const typeLabelMap = {
|
||||||
1: '新品口味',
|
1: '新品口味',
|
||||||
0: '标杆口味'
|
0: '标杆口味'
|
||||||
@@ -33,7 +25,7 @@ const list = computed(() => props.report?.config || []);
|
|||||||
v-for="item in list"
|
v-for="item in list"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="item"
|
class="item"
|
||||||
:class="{ [typeEnum[item.concept_type]]: true }"
|
:class="{ [testItemTypeEnum[item.concept_type]]: true }"
|
||||||
>
|
>
|
||||||
<div class="code">
|
<div class="code">
|
||||||
{{ typeLabelMap[item.concept_type] || '' }}{{ item.concept_encode || '' }}
|
{{ typeLabelMap[item.concept_type] || '' }}{{ item.concept_encode || '' }}
|
||||||
|
|||||||
@@ -195,7 +195,9 @@ function downloadHotAreaImage() {
|
|||||||
ctx.fillStyle = '#FFFFFF';
|
ctx.fillStyle = '#FFFFFF';
|
||||||
ctx.roundRect(
|
ctx.roundRect(
|
||||||
textLeft - 4,
|
textLeft - 4,
|
||||||
textTop - (textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent) * 0.5 - 6,
|
textTop
|
||||||
|
- (textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent) * 0.5
|
||||||
|
- 6,
|
||||||
textMetrics.width + 8,
|
textMetrics.width + 8,
|
||||||
textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent + 8,
|
textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent + 8,
|
||||||
4
|
4
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { computed, defineProps } from 'vue';
|
|||||||
import Section from '../../../components/Section.vue';
|
import Section from '../../../components/Section.vue';
|
||||||
import StyledTable from '../../components/StyledTable.vue';
|
import StyledTable from '../../components/StyledTable.vue';
|
||||||
|
|
||||||
|
import { codeList } from '../../../consts';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
report: { type: Object, default: () => Object.assign({}) }
|
report: { type: Object, default: () => Object.assign({}) }
|
||||||
});
|
});
|
||||||
@@ -16,7 +18,7 @@ function getTableCodeRow(tableData) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const codeRow = tableData.dataVOS.find((row) =>
|
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) {
|
if (!codeRow) {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -56,3 +56,51 @@ export function sortListForTableColSpan(options = {}) {
|
|||||||
|
|
||||||
return list;
|
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