阅片融合分组区分颜色
continuous-integration/drone/push Build is passing Details

main
wangxiaoshuang 2025-11-28 16:30:29 +08:00
parent 17f738aa5d
commit ba6cb87648
2 changed files with 60 additions and 34 deletions

View File

@ -223,40 +223,67 @@ export async function readEntry(entry) {
return files; return files;
} }
// 使用FNV-1a哈希算法确保相同GUID产生相同结果
function fnv1aHash(str) {
const FNV_OFFSET_BASIS = 2166136261;
const FNV_PRIME = 16777619;
let hash = FNV_OFFSET_BASIS;
for (let i = 0; i < str.length; i++) {
hash ^= str.charCodeAt(i);
hash = (hash * FNV_PRIME) >>> 0; // 使用无符号右移确保结果为无符号32位整数
}
return hash;
}
// RGB转十六进制 // RGB转十六进制
function rgbToHex(r, g, b) { function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
} }
// HSL转RGB函数
function hslToRgb(h, s, l) {
let r, g, b;
if (s === 0) {
r = g = b = l; // 灰色
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return { r, g, b };
}
export function guidToColor(guid) { export function guidToColor(guid) {
// 移除GUID中的连字符和花括号如果有 // 移除GUID中的连字符和花括号如果有
const cleanGuid = guid.replace(/[{}()-]/g, ''); let cleanGuid = guid.replace(/[{}()-]/g, '');
// 计算GUID的哈希值
const hash = fnv1aHash(cleanGuid);
// 使用GUID的前6个字符作为颜色基础确保一致性 // 使用哈希值生成HLS颜色确保高区分度
const colorBase = cleanGuid.substring(0, 6); // 将哈希值映射到0-1之间
const h = (hash & 0xFFFF) / 0xFFFF; // 使用前16位作为色相
// 将每个字符转换为数字并映射到0-255范围 const s = ((hash >> 16) & 0xFF) / 0xFF * 0.6 + 0.4; // 饱和度在0.4-1.0之间
let r = 0, g = 0, b = 0; const l = ((hash >> 24) & 0xFF) / 0xFF * 0.4 + 0.4; // 亮度在0.3-0.7之间,避免太暗或太亮
for (let i = 0; i < 6; i++) {
const charCode = colorBase.charCodeAt(i);
if (i < 2) {
r = (r * 16 + (charCode % 16)) % 256;
} else if (i < 4) {
g = (g * 16 + (charCode % 16)) % 256;
} else {
b = (b * 16 + (charCode % 16)) % 256;
}
}
// 确保颜色有足够的饱和度(避免生成过于灰暗的颜色)
if (r + g + b < 100) {
r = Math.min(255, r + 100);
g = Math.min(255, g + 50);
} else if (r + g + b > 600) {
r = Math.max(0, r - 100);
b = Math.max(0, b - 50);
}
// 返回RGB对象 // 返回RGB对象
return rgbToHex(r, g, b); let rgb = hslToRgb(h, s, l);
let obj = {
r: Math.round(rgb.r * 255),
g: Math.round(rgb.g * 255),
b: Math.round(rgb.b * 255)
}
let str = rgbToHex(obj.r, obj.g, obj.b)
return str;
} }

View File

@ -86,14 +86,14 @@
:content="`${$t('trials:reading:message:fused')}${item.TableQuestions.Answers[i].SplitOrMergeLesionName}`" :content="`${$t('trials:reading:message:fused')}${item.TableQuestions.Answers[i].SplitOrMergeLesionName}`"
placement="bottom"> placement="bottom">
<div <div
v-if="item.TableQuestions.Answers[i].SplitOrMergeType === '1' || item.TableQuestions.Answers[i].SplitOrMergeType === '3'" v-if="item.TableQuestions.Answers[i].SplitOrMergeType === '1' || item.TableQuestions.Answers[i].SplitOrMergeType === '3'">
@click="acvd(item.TableQuestions.Answers[i])"> <span class="login-cycle"
<span class="login-cycle" /> :style="`background-color:${$GuidToColor(item.TableQuestions.Answers[i].MergeRowId)}`" />
</div> </div>
</el-tooltip> </el-tooltip>
<div v-if="item.TableQuestions.Answers[i].SplitOrMergeType === '4'" <div v-if="item.TableQuestions.Answers[i].SplitOrMergeType === '4'">
@click="acvd(item.TableQuestions.Answers[i])"> <span class="login-cycle"
<span class="login-cycle" /> :style="`background-color:${$GuidToColor(item.TableQuestions.Answers[i].RowId)}`" />
</div> </div>
<el-tooltip v-if="!!item.TableQuestions.Answers[i].lesionPart" class="item" effect="dark" <el-tooltip v-if="!!item.TableQuestions.Answers[i].lesionPart" class="item" effect="dark"
:content="item.TableQuestions.Answers[i].lesionPart" placement="bottom"> :content="item.TableQuestions.Answers[i].lesionPart" placement="bottom">
@ -337,7 +337,6 @@ export default {
DicomEvent.$off('refreshQuestions') DicomEvent.$off('refreshQuestions')
}, },
methods: { methods: {
acvd(item) { console.log(item) },
handleReadingChart(e) { handleReadingChart(e) {
this.$emit('handleReadingChart', e) this.$emit('handleReadingChart', e)
}, },