浏览代码

feat:修改英文显示样式

wangsisi 7 小时之前
父节点
当前提交
4ff5c71f29

+ 140 - 10
src/components/pageComponents/ArchivesFarmTimeLine.vue

@@ -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);
                                 }
                             }

+ 2 - 2
src/components/popup/UploadProgressPopup.vue

@@ -5,8 +5,8 @@
         <div class="upload-box">
             <div class="box-header">
                 <div class="upload-title">
-                    <span>{{ t('上传照片') }}</span>
-                    <span v-if="!uploadRequired" class="optional">{{ t('(可选)') }}</span>
+                    <span>{{ t('uploadPopup.uploadPhotos') }}</span>
+                    <span v-if="!uploadRequired" class="optional">{{ t('uploadPopup.optional') }}</span>
                 </div>
             </div>
             <uploader class="popup-uploader" :class="{ 'popup-uploader-identify': enableIdentify }" v-model="fileList"

+ 12 - 4
src/components/weatherInfo.vue

@@ -71,7 +71,7 @@
                         @click="emit('reportTabClick', item)"
                     >
                         <img class="report-tab-icon" :src="getReportTabIcon(index)" alt="" />
-                        <span class="report-tab-label">{{ item.label }}</span>
+                        <span class="report-tab-label">{{ getReportTabLabel(item) }}</span>
                     </div>
                 </div>
             </div>
@@ -133,9 +133,9 @@ const props = defineProps({
     reportTabs: {
         type: Array,
         default: () => [
-            { key: "historyRisk", label: "历史气象灾害" },
-            { key: "soilImprovement", label: "土壤问题研判" },
-            { key: "rotationAdvice", label: "种植轮作建议" },
+            { key: "historyRisk" },
+            { key: "soilImprovement" },
+            { key: "rotationAdvice" },
         ],
     },
     from: {
@@ -167,6 +167,14 @@ const REPORT_TAB_ICONS = [
 
 const getReportTabIcon = (index) => REPORT_TAB_ICONS[index] || REPORT_TAB_ICONS[0];
 
+const getReportTabLabel = (item) => {
+    if (!item?.key) return item?.label || "";
+    const i18nKey = `weather.reportTab.${item.key}`;
+    const translated = t(i18nKey);
+    if (translated !== i18nKey) return translated;
+    return item.label || item.key;
+};
+
 // 定义emit事件
 const emit = defineEmits(['weatherExpanded', 'changeGarden', 'changeGardenTab', 'closeTabMask', 'reportTabClick']);
 const router = useRouter();

+ 26 - 0
src/i18n/messages.js

@@ -42,6 +42,11 @@ export default {
             selectRegion: "选择地区",
             selectCategory: "选择品类",
             sunny: "晴天",
+            reportTab: {
+                historyRisk: "历史气象灾害",
+                soilImprovement: "土壤问题研判",
+                rotationAdvice: "种植轮作建议",
+            },
         },
         garden: {
             currentFarm: "当前农场",
@@ -165,6 +170,10 @@ export default {
             recordStemBorerControl: "执行了蒂蛀虫防治农事",
             recordFlowerFruitProtect: "执行了保花保果药剂喷施农事",
             recordPreFlowerPest: "执行了花前病虫综合防治农事",
+            recordNow: "立即记录",
+            riskLevel1: "一级",
+            riskLevel2: "二级",
+            riskLevel3: "三级",
         },
         recordDetails: recordDetailsZh,
         agriRecord: {
@@ -244,6 +253,10 @@ export default {
             remindSuccess: "提醒成功!",
             redispatchMsg: "重新派发:{name}",
         },
+        uploadPopup: {
+            uploadPhotos: "上传照片",
+            optional: "(可选)",
+        },
         agriRecordDetail: {
             title: "农事详情",
             deadlinePrefix: "截止到",
@@ -343,6 +356,11 @@ export default {
             selectRegion: "Region",
             selectCategory: "Category",
             sunny: "Sunny",
+            reportTab: {
+                historyRisk: "Weather hist.",
+                soilImprovement: "Soil issues",
+                rotationAdvice: "Rotation",
+            },
         },
         garden: {
             currentFarm: "Current farm",
@@ -466,6 +484,10 @@ export default {
             recordStemBorerControl: "Stem borer control applied",
             recordFlowerFruitProtect: "Flower and fruit protection spray applied",
             recordPreFlowerPest: "Pre-bloom pest control applied",
+            recordNow: "Record Now",
+            riskLevel1: "Level 1",
+            riskLevel2: "Level 2",
+            riskLevel3: "Level 3",
         },
         recordDetails: recordDetailsEn,
         agriRecord: {
@@ -545,6 +567,10 @@ export default {
             remindSuccess: "Reminder sent!",
             redispatchMsg: "Redispatched: {name}",
         },
+        uploadPopup: {
+            uploadPhotos: "Upload photos",
+            optional: "(Optional)",
+        },
         agriRecordDetail: {
             title: "Work Details",
             deadlinePrefix: "Due by",

+ 2 - 0
src/i18n/recordDetails-messages.js

@@ -51,6 +51,7 @@ export const recordDetailsZh = {
         "如果区域长势不同,会降低病虫害防治功效,建议根据长势拆分区域,进行分区精细管理,达到减药减肥的目的",
     partitionManage: "分区管理",
     abnormalCount: "每 20 棵树中,有几棵出现了 病虫异常?",
+    treeUnit: "棵",
     inputPlaceholder: "请输入",
     ratioRequired: "请输入占比",
     patrolDesc: "巡园描述",
@@ -150,6 +151,7 @@ export const recordDetailsEn = {
         "If growth varies by area, pest control is less effective. Split zones by vigor for precision management to reduce pesticide and fertilizer use.",
     partitionManage: "Zone management",
     abnormalCount: "Out of every 20 trees, how many show pest/disease abnormality?",
+    treeUnit: "trees",
     inputPlaceholder: "Enter",
     ratioRequired: "Please enter the ratio",
     patrolDesc: "Patrol notes",

+ 12 - 3
src/views/old_mini/agri_file/index.vue

@@ -42,7 +42,7 @@
                                 <div class="tracking-item__issue">{{ item.first_work?.interaction_issue }}</div>
                             </div>
                         </div>
-                        <div class="tracking-item__btn">立即记录</div>
+                        <div class="tracking-item__btn">{{ $t('agriFile.recordNow') }}</div>
                     </div>
                     <div class="tracking-item__history" v-show="false">
                         <div class="tracking-item__history-text">{{ item.historyText }}</div>
@@ -61,9 +61,12 @@
 import { computed, onActivated, ref } from "vue";
 import { useRoute, useRouter } from "vue-router";
 import { useStore } from "vuex";
+import { useI18n } from "@/i18n";
 import weatherInfo from "@/components/weatherInfo.vue";
 import gardenList from "@/components/gardenList.vue";
 
+const { t } = useI18n();
+
 const store = useStore();
 const route = useRoute();
 const router = useRouter();
@@ -195,8 +198,11 @@ onActivated(() => {
     gardenListRef.value?.refreshFarmList?.();
 });
 
-const RISK_LEVEL_LABELS = { 1: "一级", 2: "二级", 3: "三级" };
-const formatRiskLevel = (level) => RISK_LEVEL_LABELS[Number(level)] ?? "";
+const RISK_LEVEL_KEYS = { 1: "agriFile.riskLevel1", 2: "agriFile.riskLevel2", 3: "agriFile.riskLevel3" };
+const formatRiskLevel = (level) => {
+    const key = RISK_LEVEL_KEYS[Number(level)];
+    return key ? t(key) : "";
+};
 
 const currentPheCode = ref('');
 let fetchRequestId = 0;
@@ -334,6 +340,7 @@ const handleTrackingItemClick = (item) => {
             background: #fff;
             color: #FF6A6A;
             font-size: 12px;
+            min-width: fit-content;
         }
 
         &__title {
@@ -355,6 +362,7 @@ const handleTrackingItemClick = (item) => {
             color: var(--tracking-primary);
             font-size: 12px;
             border: .5px solid var(--tracking-primary);
+            min-width: max-content;
         }
 
         &__body {
@@ -416,6 +424,7 @@ const handleTrackingItemClick = (item) => {
             background: var(--tracking-primary);
             color: #fff;
             font-size: 12px;
+            min-width: fit-content;
         }
 
         &__history {

+ 1 - 1
src/views/old_mini/recordDetails/index.vue

@@ -225,7 +225,7 @@
                         <el-input v-model="formData.ratio" type="number" size="large"
                             :placeholder="t('recordDetails.inputPlaceholder')">
                             <template #suffix>
-                                
+                                {{ t('recordDetails.treeUnit') }}
                             </template>
                         </el-input>
                     </div>