|
|
@@ -5,15 +5,26 @@
|
|
|
image-size="80" description="暂无数据" class="empty-state" />
|
|
|
<template v-else>
|
|
|
<div v-for="(p, idx) in phenologyList" :key="`phenology-${uniqueTimestamp}-${idx}`"
|
|
|
- class="phenology-bar">
|
|
|
+ class="phenology-bar"
|
|
|
+ :class="{ 'phenology-bar--en-expand': locale === 'en' && shouldExpandEnPhenologyLabel(p, idx) }"
|
|
|
+ :style="locale === 'en' && shouldShowPhenologyBarTitle(idx) && shouldExpandEnPhenologyLabel(p, idx)
|
|
|
+ ? getEnPhenologyExpandedStyle(p.phenologyName) : undefined">
|
|
|
<div class="phenology-title" :class="{
|
|
|
'phenology-red': isPhenologyBarGrayByWorkStatus(p),
|
|
|
'phenology-blue': !isPhenologyBarGrayByWorkStatus(p),
|
|
|
- }" v-if="shouldShowPhenologyBarTitle(idx)">
|
|
|
- {{ p.phenologyName }}
|
|
|
+ 'phenology-title--en': locale === 'en',
|
|
|
+ 'phenology-title--en-expand': locale === 'en' && shouldExpandEnPhenologyLabel(p, idx),
|
|
|
+ }" :style="locale === 'en' && shouldExpandEnPhenologyLabel(p, idx)
|
|
|
+ ? getEnPhenologyExpandedStyle(p.phenologyName) : undefined"
|
|
|
+ v-if="shouldShowPhenologyBarTitle(idx)">
|
|
|
+ <span class="phenology-title__text" :class="{ 'phenology-title__text--en': locale === 'en' }">
|
|
|
+ {{ p.phenologyName }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
<div v-for="(r, rIdx) in Array.isArray(p.reproductiveList) ? p.reproductiveList : []"
|
|
|
- :key="`reproductive-${uniqueTimestamp}-${idx}-${rIdx}`" class="reproductive-item">
|
|
|
+ :key="`reproductive-${uniqueTimestamp}-${idx}-${rIdx}`" class="reproductive-item"
|
|
|
+ :style="locale === 'en' && !shouldShowPhenologyBarTitle(idx) && shouldExpandEnPhenologyLabel(p, idx, rIdx)
|
|
|
+ ? getEnPhenologyExpandedStyle(p.phenologyName) : undefined">
|
|
|
<div class="arranges">
|
|
|
<div v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList) ? r.farmWorkArrangeList : []"
|
|
|
:key="`arrange-${uniqueTimestamp}-${idx}-${rIdx}-${aIdx}`" class="arrange-card" :class="[
|
|
|
@@ -30,7 +41,7 @@
|
|
|
<div class="left-date">{{ formatDate(fw.createTime) }}</div>
|
|
|
<div class="text">
|
|
|
<span class="van-ellipsis">{{ fw.title }}</span>
|
|
|
- <div class="text-status" :style="farmWorkTypeObjColor[fw.farm_work_type]">{{ farmWorkTypeObj[fw.farm_work_type] }}</div>
|
|
|
+ <div class="text-status" v-if="farmWorkTypeObj[fw.farm_work_type]" :style="farmWorkTypeObjColor[fw.farm_work_type]">{{ farmWorkTypeObj[fw.farm_work_type] }}</div>
|
|
|
<el-icon color="#333333">
|
|
|
<ArrowRight />
|
|
|
</el-icon>
|
|
|
@@ -61,16 +72,26 @@
|
|
|
<div class="phenology-name" :class="{
|
|
|
'phenology-red': isPhenologyRowGrayByWorkStatus(r),
|
|
|
'text-blue': !isPhenologyRowGrayByWorkStatus(r),
|
|
|
- }">
|
|
|
- {{ p.phenologyName }}
|
|
|
+ 'phenology-name--en': locale === 'en',
|
|
|
+ 'phenology-name--en-expand': locale === 'en' && shouldExpandEnPhenologyLabel(p, idx, rIdx),
|
|
|
+ }" :style="locale === 'en' && shouldExpandEnPhenologyLabel(p, idx, rIdx)
|
|
|
+ ? getEnPhenologyExpandedStyle(p.phenologyName) : undefined">
|
|
|
+ <span class="phenology-name__text" :class="{ 'phenology-name__text--en': locale === 'en' }">
|
|
|
+ {{ p.phenologyName }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</template> -->
|
|
|
<template v-if="!shouldShowPhenologyBarTitle(idx)">
|
|
|
<div class="phenology-name" :class="{
|
|
|
'phenology-red': isPhenologyRowGrayByWorkStatus(r),
|
|
|
'text-blue': !isPhenologyRowGrayByWorkStatus(r),
|
|
|
- }">
|
|
|
- {{ p.phenologyName }}
|
|
|
+ 'phenology-name--en': locale === 'en',
|
|
|
+ 'phenology-name--en-expand': locale === 'en' && shouldExpandEnPhenologyLabel(p, idx, rIdx),
|
|
|
+ }" :style="locale === 'en' && shouldExpandEnPhenologyLabel(p, idx, rIdx)
|
|
|
+ ? getEnPhenologyExpandedStyle(p.phenologyName) : undefined">
|
|
|
+ <span class="phenology-name__text" :class="{ 'phenology-name__text--en': locale === 'en' }">
|
|
|
+ {{ p.phenologyName }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
</template>
|
|
|
</div>
|
|
|
@@ -89,6 +110,48 @@ import { useI18n } from "@/i18n";
|
|
|
|
|
|
const { locale, t } = useI18n();
|
|
|
|
|
|
+const PHENOLOGY_LABEL_FONT = "500 12px PingFang SC, -apple-system, BlinkMacSystemFont, sans-serif";
|
|
|
+const PHENOLOGY_LABEL_PADDING = 16;
|
|
|
+let measureCanvas = null;
|
|
|
+
|
|
|
+const measurePhenologyTextWidth = (text) => {
|
|
|
+ if (!text) return 0;
|
|
|
+ if (typeof document === "undefined") return String(text).length * 7;
|
|
|
+ if (!measureCanvas) measureCanvas = document.createElement("canvas");
|
|
|
+ const ctx = measureCanvas.getContext("2d");
|
|
|
+ ctx.font = PHENOLOGY_LABEL_FONT;
|
|
|
+ return ctx.measureText(String(text)).width;
|
|
|
+};
|
|
|
+
|
|
|
+const getEnLabelRequiredHeight = (text) =>
|
|
|
+ measurePhenologyTextWidth(text) + PHENOLOGY_LABEL_PADDING;
|
|
|
+
|
|
|
+const getEnPhenologyExpandedStyle = (text) => {
|
|
|
+ if (locale.value !== "en" || !text) return undefined;
|
|
|
+ return { minHeight: `${Math.ceil(getEnLabelRequiredHeight(text))}px` };
|
|
|
+};
|
|
|
+
|
|
|
+const CARD_ESTIMATED_HEIGHT = 68;
|
|
|
+
|
|
|
+const estimateReproductiveRowHeight = (r) => {
|
|
|
+ const cards = Array.isArray(r?.farmWorkArrangeList) ? r.farmWorkArrangeList : [];
|
|
|
+ return cards.length * CARD_ESTIMATED_HEIGHT + 4;
|
|
|
+};
|
|
|
+
|
|
|
+const estimatePhenologyBarHeight = (p) => {
|
|
|
+ const reps = Array.isArray(p?.reproductiveList) ? p.reproductiveList : [];
|
|
|
+ return reps.reduce((sum, r) => sum + estimateReproductiveRowHeight(r), 0);
|
|
|
+};
|
|
|
+
|
|
|
+const shouldExpandEnPhenologyLabel = (p, idx, rIdx = null) => {
|
|
|
+ if (locale.value !== "en" || !p?.phenologyName) return false;
|
|
|
+ const requiredHeight = getEnLabelRequiredHeight(p.phenologyName);
|
|
|
+ const availableHeight = shouldShowPhenologyBarTitle(idx)
|
|
|
+ ? estimatePhenologyBarHeight(p)
|
|
|
+ : estimateReproductiveRowHeight(p.reproductiveList?.[rIdx]);
|
|
|
+ return requiredHeight > availableHeight;
|
|
|
+};
|
|
|
+
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
|
|
|
|
@@ -626,6 +689,10 @@ onBeforeRouteLeave(() => {
|
|
|
box-sizing: border-box;
|
|
|
position: relative;
|
|
|
|
|
|
+ &--en-expand {
|
|
|
+ overflow: visible;
|
|
|
+ }
|
|
|
+
|
|
|
.phenology-title {
|
|
|
width: 18px;
|
|
|
top: 0;
|
|
|
@@ -654,6 +721,36 @@ onBeforeRouteLeave(() => {
|
|
|
color: #808080;
|
|
|
}
|
|
|
|
|
|
+ &--en {
|
|
|
+ overflow: visible;
|
|
|
+ word-break: normal;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--en-expand {
|
|
|
+ bottom: auto;
|
|
|
+ height: auto;
|
|
|
+ min-height: 100%;
|
|
|
+ overflow: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__text {
|
|
|
+ display: inline-block;
|
|
|
+
|
|
|
+ &--en {
|
|
|
+ writing-mode: horizontal-tb;
|
|
|
+ text-orientation: mixed;
|
|
|
+ letter-spacing: 0;
|
|
|
+ white-space: nowrap;
|
|
|
+ word-break: normal;
|
|
|
+ line-height: 1;
|
|
|
+ position: static;
|
|
|
+ transform: rotate(90deg);
|
|
|
+ transform-origin: center center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
.reproductive-item {
|
|
|
@@ -696,6 +793,37 @@ onBeforeRouteLeave(() => {
|
|
|
line-height: 16px;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
+
|
|
|
+ &--en {
|
|
|
+ overflow: visible;
|
|
|
+ word-break: normal;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--en-expand {
|
|
|
+ bottom: auto;
|
|
|
+ height: auto;
|
|
|
+ min-height: 100%;
|
|
|
+ overflow: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__text {
|
|
|
+ display: inline-block;
|
|
|
+
|
|
|
+ &--en {
|
|
|
+ writing-mode: horizontal-tb;
|
|
|
+ text-orientation: mixed;
|
|
|
+ letter-spacing: 0;
|
|
|
+ white-space: nowrap;
|
|
|
+ word-break: normal;
|
|
|
+ line-height: 1;
|
|
|
+ position: static;
|
|
|
+ transform: rotate(90deg);
|
|
|
+ transform-origin: center center;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.arranges {
|
|
|
@@ -742,7 +870,7 @@ onBeforeRouteLeave(() => {
|
|
|
.text {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- gap: 2px;
|
|
|
+ gap: 4px;
|
|
|
width: calc(100% - 90px);
|
|
|
}
|
|
|
.text-status {
|
|
|
@@ -752,6 +880,8 @@ onBeforeRouteLeave(() => {
|
|
|
padding: 0 5px;
|
|
|
font-size: 10px;
|
|
|
min-width: fit-content;
|
|
|
+ height: 16px;
|
|
|
+ line-height: 16px;
|
|
|
border: 0.5px solid rgba(33, 153, 248, 0.4);
|
|
|
}
|
|
|
}
|