|
@@ -85,7 +85,7 @@
|
|
|
<view class="v2-p2" style="margin-top: 16px;">评分总体分布</view>
|
|
<view class="v2-p2" style="margin-top: 16px;">评分总体分布</view>
|
|
|
<view class="vb-table" :style="{'border':'1px solid '+item.bcolor}">
|
|
<view class="vb-table" :style="{'border':'1px solid '+item.bcolor}">
|
|
|
<view class="vbt-pre adfac" v-for="(ss,si) in item.scoreSpreads" :key="si">
|
|
<view class="vbt-pre adfac" v-for="(ss,si) in item.scoreSpreads" :key="si">
|
|
|
- <view class="vbtp-left adfacjc" :class="{'black':(item.title=='人际关系'||item.title=='学习'||item.title=='内部流程、系统与结构')}" :style="{'background':item.titlecolor}">{{ ss.theme||'' }}</view>
|
|
|
|
|
|
|
+ <view class="vbtp-left adfacjc" :class="{'black':(item.title=='人际关系'||item.title=='学习'||item.title=='内部流程、系统与结构')}" :style="{'background':item.titlecolor,'padding':'0 16px'}">{{ ss.theme||'' }}</view>
|
|
|
<view class="vbtp-right" :style="{'border':'1px solid '+item.bcolor}">
|
|
<view class="vbtp-right" :style="{'border':'1px solid '+item.bcolor}">
|
|
|
<view class="vbtpr-title">{{ ss.question||'' }}</view>
|
|
<view class="vbtpr-title">{{ ss.question||'' }}</view>
|
|
|
<view class="vbtpr-jd">
|
|
<view class="vbtpr-jd">
|
|
@@ -225,6 +225,9 @@
|
|
|
]
|
|
]
|
|
|
if(this.reportData&&this.reportData.dimensionAnalysis){
|
|
if(this.reportData&&this.reportData.dimensionAnalysis){
|
|
|
this.reportData.dimensionAnalysis.forEach((d,i)=>{
|
|
this.reportData.dimensionAnalysis.forEach((d,i)=>{
|
|
|
|
|
+ d.scoreSpreads.forEach(s=>{
|
|
|
|
|
+ s.theme = s.theme.replaceAll(',','').replaceAll(',','');
|
|
|
|
|
+ })
|
|
|
this.reportData.dimensionAnalysis[i] = {...d,...tempDimensionAnalysis[i]}
|
|
this.reportData.dimensionAnalysis[i] = {...d,...tempDimensionAnalysis[i]}
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
@@ -378,7 +381,7 @@
|
|
|
},
|
|
},
|
|
|
// 辅助函数:绘制单个评估项
|
|
// 辅助函数:绘制单个评估项
|
|
|
drawScoreItem(ctx, scoreItem, y, width, height, dimensionData) {
|
|
drawScoreItem(ctx, scoreItem, y, width, height, dimensionData) {
|
|
|
- const leftBoxWidth = 110;
|
|
|
|
|
|
|
+ const leftBoxWidth = 72;
|
|
|
const rightBoxX = leftBoxWidth;
|
|
const rightBoxX = leftBoxWidth;
|
|
|
const rightBoxWidth = width - leftBoxWidth;
|
|
const rightBoxWidth = width - leftBoxWidth;
|
|
|
const rightPadding = 10; // 右侧内容的通用内边距
|
|
const rightPadding = 10; // 右侧内容的通用内边距
|
|
@@ -398,12 +401,13 @@
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 绘制左侧标题文字 (要求 1)
|
|
// 绘制左侧标题文字 (要求 1)
|
|
|
|
|
+ let theme = (scoreItem.theme||'').replaceAll(',','').replaceAll(',','');
|
|
|
const isBlackLeftTitle = (dimensionData.title == '人际关系' || dimensionData.title == '学习' || dimensionData.title == '内部流程、系统与结构');
|
|
const isBlackLeftTitle = (dimensionData.title == '人际关系' || dimensionData.title == '学习' || dimensionData.title == '内部流程、系统与结构');
|
|
|
ctx.fillStyle = isBlackLeftTitle ? '#002846' : '#FFFFFF';
|
|
ctx.fillStyle = isBlackLeftTitle ? '#002846' : '#FFFFFF';
|
|
|
ctx.font = '10px sans-serif';
|
|
ctx.font = '10px sans-serif';
|
|
|
ctx.textAlign = 'center';
|
|
ctx.textAlign = 'center';
|
|
|
ctx.textBaseline = 'middle';
|
|
ctx.textBaseline = 'middle';
|
|
|
- this.drawWrappedText(ctx, scoreItem.theme, leftBoxWidth / 2, y + height / 2, 20, leftBoxWidth - 20); // 左右留10px边距
|
|
|
|
|
|
|
+ this.drawWrappedText(ctx, theme, leftBoxWidth / 2, y + height / 2, 12, leftBoxWidth - 32); // 左右留16px边距
|
|
|
|
|
|
|
|
// 2. --- 绘制右侧部分 ---
|
|
// 2. --- 绘制右侧部分 ---
|
|
|
// 绘制右侧外边框
|
|
// 绘制右侧外边框
|
|
@@ -506,22 +510,42 @@
|
|
|
ctx.fillText((scoreItem.avgScore>25?25:scoreItem.avgScore), scoreBoxX + scoreBoxWidth / 2, scoreBoxY + scoreBoxHeight / 2);
|
|
ctx.fillText((scoreItem.avgScore>25?25:scoreItem.avgScore), scoreBoxX + scoreBoxWidth / 2, scoreBoxY + scoreBoxHeight / 2);
|
|
|
},
|
|
},
|
|
|
// 辅助函数:绘制自动换行的文字
|
|
// 辅助函数:绘制自动换行的文字
|
|
|
- drawWrappedText(ctx, text, x, y, lineHeight, maxWidth) {
|
|
|
|
|
- let words = text.split('');
|
|
|
|
|
- let line = '';
|
|
|
|
|
- for (let n = 0; n < words.length; n++) {
|
|
|
|
|
- let testLine = line + words[n];
|
|
|
|
|
- let metrics = ctx.measureText(testLine);
|
|
|
|
|
- let testWidth = metrics.width;
|
|
|
|
|
- if (testWidth > maxWidth && n > 0) {
|
|
|
|
|
- ctx.fillText(line, x, y);
|
|
|
|
|
- line = words[n];
|
|
|
|
|
- y += lineHeight;
|
|
|
|
|
- } else {
|
|
|
|
|
- line = testLine;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- ctx.fillText(line, x, y);
|
|
|
|
|
|
|
+ // 辅助函数:绘制自动换行且垂直居中的文字
|
|
|
|
|
+ drawWrappedText(ctx, text, x, y_center, lineHeight, maxWidth) {
|
|
|
|
|
+ // 1. 将文本分割成多行
|
|
|
|
|
+ let words = text.split('');
|
|
|
|
|
+ let lines = [];
|
|
|
|
|
+ let currentLine = '';
|
|
|
|
|
+
|
|
|
|
|
+ for (let n = 0; n < words.length; n++) {
|
|
|
|
|
+ let testLine = currentLine + words[n];
|
|
|
|
|
+ let metrics = ctx.measureText(testLine);
|
|
|
|
|
+ let testWidth = metrics.width;
|
|
|
|
|
+ if (testWidth > maxWidth && n > 0) {
|
|
|
|
|
+ lines.push(currentLine);
|
|
|
|
|
+ currentLine = words[n];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ currentLine = testLine;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ lines.push(currentLine); // 加入最后一行
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 计算文本块的总高度
|
|
|
|
|
+ const totalTextHeight = lines.length * lineHeight;
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 计算绘制第一行文本的起始 Y 坐标
|
|
|
|
|
+ // y_center 是外部传入的容器中心点
|
|
|
|
|
+ // 我们从容器中心点上移一半文本总高度,得到文本块的顶部位置
|
|
|
|
|
+ let startY = y_center - totalTextHeight / 2;
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 逐行绘制
|
|
|
|
|
+ // ctx.textBaseline = 'middle' 是在外部设置的,所以我们绘制每一行时,
|
|
|
|
|
+ // Y坐标需要是该行所在矩形区域的垂直中心。
|
|
|
|
|
+ for (let i = 0; i < lines.length; i++) {
|
|
|
|
|
+ // 计算当前行文本的中心Y坐标
|
|
|
|
|
+ const lineY = startY + (i * lineHeight) + (lineHeight / 2);
|
|
|
|
|
+ ctx.fillText(lines[i], x, lineY);
|
|
|
|
|
+ }
|
|
|
},
|
|
},
|
|
|
// 辅助函数:解析 CSS linear-gradient 字符串
|
|
// 辅助函数:解析 CSS linear-gradient 字符串
|
|
|
parseGradient(gradientString) {
|
|
parseGradient(gradientString) {
|