Ver Fonte

feat:修改英文显示样式

wangsisi há 7 horas atrás
pai
commit
4ff5c71f29

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

@@ -5,15 +5,26 @@
                 image-size="80" description="暂无数据" class="empty-state" />
                 image-size="80" description="暂无数据" class="empty-state" />
             <template v-else>
             <template v-else>
                 <div v-for="(p, idx) in phenologyList" :key="`phenology-${uniqueTimestamp}-${idx}`"
                 <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="{
                     <div class="phenology-title" :class="{
                         'phenology-red': isPhenologyBarGrayByWorkStatus(p),
                         'phenology-red': isPhenologyBarGrayByWorkStatus(p),
                         'phenology-blue': !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>
                     <div v-for="(r, rIdx) in Array.isArray(p.reproductiveList) ? p.reproductiveList : []"
                     <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 class="arranges">
                             <div v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList) ? r.farmWorkArrangeList : []"
                             <div v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList) ? r.farmWorkArrangeList : []"
                                 :key="`arrange-${uniqueTimestamp}-${idx}-${rIdx}-${aIdx}`" class="arrange-card" :class="[
                                 :key="`arrange-${uniqueTimestamp}-${idx}-${rIdx}-${aIdx}`" class="arrange-card" :class="[
@@ -30,7 +41,7 @@
                                             <div class="left-date">{{ formatDate(fw.createTime) }}</div>
                                             <div class="left-date">{{ formatDate(fw.createTime) }}</div>
                                             <div class="text">
                                             <div class="text">
                                                 <span class="van-ellipsis">{{ fw.title }}</span>
                                                 <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">
                                                 <el-icon color="#333333">
                                                     <ArrowRight />
                                                     <ArrowRight />
                                                 </el-icon>
                                                 </el-icon>
@@ -61,16 +72,26 @@
                             <div class="phenology-name" :class="{
                             <div class="phenology-name" :class="{
                                 'phenology-red': isPhenologyRowGrayByWorkStatus(r),
                                 'phenology-red': isPhenologyRowGrayByWorkStatus(r),
                                 'text-blue': !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>
                             </div>
                         </template> -->
                         </template> -->
                         <template v-if="!shouldShowPhenologyBarTitle(idx)">
                         <template v-if="!shouldShowPhenologyBarTitle(idx)">
                             <div class="phenology-name" :class="{
                             <div class="phenology-name" :class="{
                                 'phenology-red': isPhenologyRowGrayByWorkStatus(r),
                                 'phenology-red': isPhenologyRowGrayByWorkStatus(r),
                                 'text-blue': !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>
                             </div>
                         </template>
                         </template>
                     </div>
                     </div>
@@ -89,6 +110,48 @@ import { useI18n } from "@/i18n";
 
 
 const { locale, t } = useI18n();
 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 router = useRouter();
 const route = useRoute();
 const route = useRoute();
 
 
@@ -626,6 +689,10 @@ onBeforeRouteLeave(() => {
         box-sizing: border-box;
         box-sizing: border-box;
         position: relative;
         position: relative;
 
 
+        &--en-expand {
+            overflow: visible;
+        }
+
         .phenology-title {
         .phenology-title {
             width: 18px;
             width: 18px;
             top: 0;
             top: 0;
@@ -654,6 +721,36 @@ onBeforeRouteLeave(() => {
                 color: #808080;
                 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 {
         .reproductive-item {
@@ -696,6 +793,37 @@ onBeforeRouteLeave(() => {
                     line-height: 16px;
                     line-height: 16px;
                     box-sizing: border-box;
                     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 {
             .arranges {
@@ -742,7 +870,7 @@ onBeforeRouteLeave(() => {
                                 .text {
                                 .text {
                                     display: flex;
                                     display: flex;
                                     align-items: center;
                                     align-items: center;
-                                    gap: 2px;
+                                    gap: 4px;
                                     width: calc(100% - 90px);
                                     width: calc(100% - 90px);
                                 }
                                 }
                                 .text-status {
                                 .text-status {
@@ -752,6 +880,8 @@ onBeforeRouteLeave(() => {
                                     padding: 0 5px;
                                     padding: 0 5px;
                                     font-size: 10px;
                                     font-size: 10px;
                                     min-width: fit-content;
                                     min-width: fit-content;
+                                    height: 16px;
+                                    line-height: 16px;
                                     border: 0.5px solid rgba(33, 153, 248, 0.4);
                                     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="upload-box">
             <div class="box-header">
             <div class="box-header">
                 <div class="upload-title">
                 <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>
             </div>
             </div>
             <uploader class="popup-uploader" :class="{ 'popup-uploader-identify': enableIdentify }" v-model="fileList"
             <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)"
                         @click="emit('reportTabClick', item)"
                     >
                     >
                         <img class="report-tab-icon" :src="getReportTabIcon(index)" alt="" />
                         <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>
                 </div>
             </div>
             </div>
@@ -133,9 +133,9 @@ const props = defineProps({
     reportTabs: {
     reportTabs: {
         type: Array,
         type: Array,
         default: () => [
         default: () => [
-            { key: "historyRisk", label: "历史气象灾害" },
-            { key: "soilImprovement", label: "土壤问题研判" },
-            { key: "rotationAdvice", label: "种植轮作建议" },
+            { key: "historyRisk" },
+            { key: "soilImprovement" },
+            { key: "rotationAdvice" },
         ],
         ],
     },
     },
     from: {
     from: {
@@ -167,6 +167,14 @@ const REPORT_TAB_ICONS = [
 
 
 const getReportTabIcon = (index) => REPORT_TAB_ICONS[index] || REPORT_TAB_ICONS[0];
 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事件
 // 定义emit事件
 const emit = defineEmits(['weatherExpanded', 'changeGarden', 'changeGardenTab', 'closeTabMask', 'reportTabClick']);
 const emit = defineEmits(['weatherExpanded', 'changeGarden', 'changeGardenTab', 'closeTabMask', 'reportTabClick']);
 const router = useRouter();
 const router = useRouter();

+ 26 - 0
src/i18n/messages.js

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

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

@@ -51,6 +51,7 @@ export const recordDetailsZh = {
         "如果区域长势不同,会降低病虫害防治功效,建议根据长势拆分区域,进行分区精细管理,达到减药减肥的目的",
         "如果区域长势不同,会降低病虫害防治功效,建议根据长势拆分区域,进行分区精细管理,达到减药减肥的目的",
     partitionManage: "分区管理",
     partitionManage: "分区管理",
     abnormalCount: "每 20 棵树中,有几棵出现了 病虫异常?",
     abnormalCount: "每 20 棵树中,有几棵出现了 病虫异常?",
+    treeUnit: "棵",
     inputPlaceholder: "请输入",
     inputPlaceholder: "请输入",
     ratioRequired: "请输入占比",
     ratioRequired: "请输入占比",
     patrolDesc: "巡园描述",
     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.",
         "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",
     partitionManage: "Zone management",
     abnormalCount: "Out of every 20 trees, how many show pest/disease abnormality?",
     abnormalCount: "Out of every 20 trees, how many show pest/disease abnormality?",
+    treeUnit: "trees",
     inputPlaceholder: "Enter",
     inputPlaceholder: "Enter",
     ratioRequired: "Please enter the ratio",
     ratioRequired: "Please enter the ratio",
     patrolDesc: "Patrol notes",
     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 class="tracking-item__issue">{{ item.first_work?.interaction_issue }}</div>
                             </div>
                             </div>
                         </div>
                         </div>
-                        <div class="tracking-item__btn">立即记录</div>
+                        <div class="tracking-item__btn">{{ $t('agriFile.recordNow') }}</div>
                     </div>
                     </div>
                     <div class="tracking-item__history" v-show="false">
                     <div class="tracking-item__history" v-show="false">
                         <div class="tracking-item__history-text">{{ item.historyText }}</div>
                         <div class="tracking-item__history-text">{{ item.historyText }}</div>
@@ -61,9 +61,12 @@
 import { computed, onActivated, ref } from "vue";
 import { computed, onActivated, ref } from "vue";
 import { useRoute, useRouter } from "vue-router";
 import { useRoute, useRouter } from "vue-router";
 import { useStore } from "vuex";
 import { useStore } from "vuex";
+import { useI18n } from "@/i18n";
 import weatherInfo from "@/components/weatherInfo.vue";
 import weatherInfo from "@/components/weatherInfo.vue";
 import gardenList from "@/components/gardenList.vue";
 import gardenList from "@/components/gardenList.vue";
 
 
+const { t } = useI18n();
+
 const store = useStore();
 const store = useStore();
 const route = useRoute();
 const route = useRoute();
 const router = useRouter();
 const router = useRouter();
@@ -195,8 +198,11 @@ onActivated(() => {
     gardenListRef.value?.refreshFarmList?.();
     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('');
 const currentPheCode = ref('');
 let fetchRequestId = 0;
 let fetchRequestId = 0;
@@ -334,6 +340,7 @@ const handleTrackingItemClick = (item) => {
             background: #fff;
             background: #fff;
             color: #FF6A6A;
             color: #FF6A6A;
             font-size: 12px;
             font-size: 12px;
+            min-width: fit-content;
         }
         }
 
 
         &__title {
         &__title {
@@ -355,6 +362,7 @@ const handleTrackingItemClick = (item) => {
             color: var(--tracking-primary);
             color: var(--tracking-primary);
             font-size: 12px;
             font-size: 12px;
             border: .5px solid var(--tracking-primary);
             border: .5px solid var(--tracking-primary);
+            min-width: max-content;
         }
         }
 
 
         &__body {
         &__body {
@@ -416,6 +424,7 @@ const handleTrackingItemClick = (item) => {
             background: var(--tracking-primary);
             background: var(--tracking-primary);
             color: #fff;
             color: #fff;
             font-size: 12px;
             font-size: 12px;
+            min-width: fit-content;
         }
         }
 
 
         &__history {
         &__history {

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

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