فهرست منبع

feat:添加农事执行多种状态

wangsisi 13 ساعت پیش
والد
کامیت
fa2de7c2ac
3فایلهای تغییر یافته به همراه96 افزوده شده و 26 حذف شده
  1. 6 2
      src/i18n/messages.js
  2. 26 6
      src/views/old_mini/agri_record_detail/index.vue
  3. 64 18
      src/views/old_mini/work_execute/index.vue

+ 6 - 2
src/i18n/messages.js

@@ -221,7 +221,9 @@ export default {
             completed: "已完成",
             timeout: "已超时",
             unqualified: "未达标",
-            acceptTimeout: "接受超时",
+            acceptTimeout: "接受异常",
+            executeAbnormal: "执行异常",
+            completeAbnormal: "完成异常",
             executeTimeout: "执行超时",
             completeTimeout: "完成超时",
             farmWorkType: "农事类型",
@@ -535,7 +537,9 @@ export default {
             completed: "Completed",
             timeout: "Timed out",
             unqualified: "Below standard",
-            acceptTimeout: "Acceptance overdue",
+            acceptTimeout: "Acceptance abnormal",
+            executeAbnormal: "Execution abnormal",
+            completeAbnormal: "Completion abnormal",
             executeTimeout: "Execution overdue",
             completeTimeout: "Completion overdue",
             farmWorkType: "Farm work type",

+ 26 - 6
src/views/old_mini/agri_record_detail/index.vue

@@ -289,7 +289,10 @@ const STATUS_BANNER_MAP = {
     已接受: 'workExecute.accepted',
     执行中: 'workExecute.executing',
     已完成: 'workExecute.completed',
-    接受超时: 'workExecute.acceptTimeout',
+    接受异常: 'workExecute.acceptTimeout',
+    执行异常: 'workExecute.executeAbnormal',
+    完成异常: 'workExecute.completeAbnormal',
+    未达标: 'workExecute.unqualified',
 };
 
 const statusBannerTitle = computed(() => {
@@ -300,7 +303,7 @@ const statusBannerTitle = computed(() => {
 
 const statusBannerTheme = computed(() => {
     const statusStr = route.query.statusStr;
-    if (statusStr === '接受超时') return 'overtime';
+    if (['接受异常', '执行异常', '完成异常', '未达标'].includes(statusStr)) return 'overtime';
     if (statusStr === '执行中') return 'executing';
     if (statusStr === '已完成') return 'completed';
     if (statusStr === '已接受') return 'accepted';
@@ -318,9 +321,26 @@ const workTagLabel = computed(() => {
     return t(`agriRecordDetail.farmWorkType.${type}`);
 });
 
-const isAcceptOvertime = computed(() =>
-    Number(workDetail.value?.is_aovertime) === 1 || route.query.statusStr === '接受超时'
-);
+const ABNORMAL_STATUS_FLAG_MAP = {
+    接受异常: ["is_aovertime"],
+    执行异常: ["is_eovertime", "is_aovertime"],
+    完成异常: ["is_covertime", "is_aovertime"],
+    未达标: ["is_anormal", "is_unqualified", "is_aovertime"],
+};
+
+const isTruthyFlag = (value) => Number(value) === 1 || value === true;
+
+const isAbnormalDetail = computed(() => {
+    const statusStr = route.query.statusStr;
+    if (["接受异常", "执行异常", "完成异常", "未达标"].includes(statusStr)) {
+        const flags = ABNORMAL_STATUS_FLAG_MAP[statusStr] || ["is_aovertime"];
+        const detail = workDetail.value || {};
+        return flags.some((field) => isTruthyFlag(detail[field]));
+    }
+    return Object.values(ABNORMAL_STATUS_FLAG_MAP).some((flags) =>
+        flags.some((field) => isTruthyFlag(workDetail.value?.[field]))
+    );
+});
 
 const isAcceptedStatus = computed(() =>
     route.query.statusStr === '已接受' || Number(route.query.status) === 2
@@ -332,7 +352,7 @@ const isCompletedStatus = computed(() =>
     route.query.statusStr === '已完成' || Number(route.query.status) === 3
 );
 
-const showBottomButtons = computed(() => !isAcceptOvertime.value && !isCompletedStatus.value);
+const showBottomButtons = computed(() => !isAbnormalDetail.value && !isCompletedStatus.value);
 
 const resolveExecutePhotoUrl = (src) => {
     if (!src) return '';

+ 64 - 18
src/views/old_mini/work_execute/index.vue

@@ -39,7 +39,7 @@
                 <div class="work-task-list" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.3)">
                     <div class="task-item" v-for="(item, index) in taskList" :key="index"
                         :class="[
-                            isAcceptOvertime(item) ? 'timeout-item' : '',
+                            isAbnormalItem(item) ? 'timeout-item' : '',
                             locale === 'en' ? 'task-item--en' : '',
                         ]" @click="handleItem(item, index)">
                         <div class="item-title" :class="{ 'item-title--en': locale === 'en' }">
@@ -50,11 +50,11 @@
                                     item.operation?.type }}</span>
                             </div>
                         </div>
-                        <span class="task-tag timeout" v-if="isAcceptOvertime(item)">
+                        <span class="task-tag timeout" v-if="isAbnormalItem(item)">
                             <el-icon>
                                 <WarningFilled />
                             </el-icon>
-                            {{ t("workExecute.acceptTimeout") }}
+                            {{ getAbnormalLabel() }}
                         </span>
                         <span class="task-tag" v-else :class="`task-tag--${getStatusTagClass()}`">
                             <el-icon v-if="activeStatus === '已完成'" class="task-tag__icon">
@@ -118,11 +118,11 @@
                             </div>
                         </div>
 
-                        <div class="unqualified-reason" v-if="activeStatus === '未达标'">
+                        <div class="unqualified-reason" v-if="isAbnormalItem(item) && activeStatus === '已完成'">
                             {{ t("workExecute.unqualifiedReason") }}{{ item.operation?.reason || t("workExecute.defaultUnqualifiedReason") }}
                         </div>
 
-                        <div class="compare-imgs" v-if="activeStatus === '未达标' && (item.beforeImage || item.afterImage)"
+                        <div class="compare-imgs" v-if="isAbnormalItem(item) && activeStatus === '已完成' && (item.beforeImage || item.afterImage)"
                             @click.stop>
                             <div class="img-tag">{{ t("workExecute.before") }}</div>
                             <div class="img-tag right-tag">{{ t("workExecute.after") }}</div>
@@ -226,7 +226,40 @@ const STATUS_TAG_CLASS_MAP = {
 
 const getStatusTagClass = () => STATUS_TAG_CLASS_MAP[activeStatus.value] || "pending";
 
-const isAcceptOvertime = (item) => Number(item?.operation?.is_aovertime) === 1;
+const STATUS_BY_TAB_VALUE = { 0: "待接受", 1: "执行中", 2: "已接受", 3: "已完成" };
+
+const isTruthyFlag = (value) => Number(value) === 1 || value === true;
+
+const ABNORMAL_FLAG_MAP = {
+    待接受: ["is_aovertime"],
+    已接受: ["is_eovertime", "is_aovertime"],
+    执行中: ["is_covertime", "is_aovertime"],
+    已完成: ["is_anormal", "is_unqualified", "is_aovertime"],
+};
+
+const isAbnormalItem = (item, status = activeStatus.value) => {
+    const operation = item?.operation || {};
+    const flags = ABNORMAL_FLAG_MAP[status] || ["is_aovertime"];
+    return flags.some((field) => isTruthyFlag(operation[field]));
+};
+
+const ABNORMAL_LABEL_KEY_MAP = {
+    待接受: "workExecute.acceptTimeout",
+    已接受: "workExecute.executeAbnormal",
+    执行中: "workExecute.completeAbnormal",
+    已完成: "workExecute.unqualified",
+};
+
+const ABNORMAL_STATUS_STR_MAP = {
+    待接受: "接受异常",
+    已接受: "执行异常",
+    执行中: "完成异常",
+    已完成: "未达标",
+};
+
+const getAbnormalLabel = () => t(ABNORMAL_LABEL_KEY_MAP[activeStatus.value] || "workExecute.acceptTimeout");
+
+const getAbnormalStatusStr = () => ABNORMAL_STATUS_STR_MAP[activeStatus.value] || "接受异常";
 
 const mapStatusButtons = (buttons) =>
     buttons.map((btn) => ({
@@ -235,7 +268,10 @@ const mapStatusButtons = (buttons) =>
     }));
 
 const getItemStatusButtons = (item) => {
-    if (isAcceptOvertime(item)) {
+    if (isAbnormalItem(item)) {
+        if (activeStatus.value === "已完成") {
+            return mapStatusButtons(STATUS_BTN_MAP["未达标"] || []);
+        }
         return [];
     }
     return mapStatusButtons(STATUS_BTN_MAP[activeStatus.value] || []);
@@ -293,8 +329,8 @@ const getExecutePhotoList = (item) => {
 };
 
 const handleItem = (item, index) => {
-    const statusStr = item.operation?.is_aovertime ? '接受超时' : activeStatus.value;
-    const status = item.operation?.is_aovertime ? 1 : activeIndex.value;
+    const statusStr = isAbnormalItem(item) ? getAbnormalStatusStr() : activeStatus.value;
+    const status = activeIndex.value;
     router.push({
         path: "/agri_record_detail",
         query: {
@@ -409,16 +445,25 @@ const getRegionRecordList = (data) => {
 };
 
 const getRegionRecordParams = (workOperationType) => ({
+    // farm_id: '320',
+    // time: '2026-06-30',
     farm_id: localStorage.getItem('selectedFarmId'),
     time: filterDate.value,
     work_operation_type: workOperationType,
-    // farm_id: '320',
-    // time: '2026-06-30',
-    // work_operation_type: workOperationType,
 });
 
 const taskListsByType = ref({ 0: [], 1: [], 2: [], 3: [] });
 
+const sortTaskListByAbnormal = (list, tabValue) => {
+    const status = STATUS_BY_TAB_VALUE[tabValue] || "待接受";
+    return [...list].sort((a, b) => {
+        const aAbnormal = isAbnormalItem(a, status) ? 1 : 0;
+        const bAbnormal = isAbnormalItem(b, status) ? 1 : 0;
+        if (bAbnormal !== aAbnormal) return bAbnormal - aAbnormal;
+        return Number(a.AO ?? 0) - Number(b.AO ?? 0);
+    });
+};
+
 const loadPageData = async () => {
     loading.value = true;
     try {
@@ -430,7 +475,7 @@ const loadPageData = async () => {
         STATUS_TAB_VALUES.forEach((type, index) => {
             const { code, data } = results[index] || {};
             const list = code === 200 ? getRegionRecordList(data) : [];
-            listsByType[type] = list;
+            listsByType[type] = sortTaskListByAbnormal(list, type);
             counts[type] = list.length;
         });
         taskListsByType.value = listsByType;
@@ -456,7 +501,7 @@ function handleActiveFilter(i) {
     selectParma.value.districtCode = cityCode.value;
     selectParma.value.farmWorkTypeId = null;
     const statusMap = { 0: "待接受", 1: "执行中", 2: "已接受", 3: "已完成" };
-    activeStatus.value = statusMap[i] || "待接受";
+    activeStatus.value = STATUS_BY_TAB_VALUE[i] || statusMap[i] || "待接受";
     syncCalendarData();
 }
 
@@ -618,7 +663,8 @@ const getWorkType = (type) => {
             position: relative;
 
             &.timeout-item {
-                border: 1px solid #f74e4e;
+                border: 1px solid #FF6A6A;
+                box-shadow: 0px 0px 4px 0px #FF6A6A66;
             }
 
             &--en {
@@ -707,11 +753,11 @@ const getWorkType = (type) => {
                 padding: 0 10px;
                 height: 25px;
                 line-height: 25px;
-                border-radius: 0 8px 0 8px;
+                border-radius: 0 7px 0 8px;
 
                 &.timeout {
-                    background: rgba(255, 106, 106, 0.1);
-                    color: #FF6A6A;
+                    background: #FF6A6A;
+                    color: #fff;
                     display: flex;
                     align-items: center;
                     gap: 2px;