|
|
@@ -8,30 +8,27 @@
|
|
|
</div>
|
|
|
<div class="task-list">
|
|
|
<div class="list-filter">
|
|
|
- <div class="filter-item" :class="{ active: activeIndex === 0 }" @click="handleActiveFilter(0)">
|
|
|
- {{ t("workExecute.pending") }}({{ taskCounts[0] || 0 }})
|
|
|
- </div>
|
|
|
- <div class="filter-item" :class="{ active: activeIndex === 2 }" @click="handleActiveFilter(2)">
|
|
|
- {{ t("workExecute.accepted") }}({{ taskCounts[2] || 0 }})
|
|
|
- </div>
|
|
|
- <div class="filter-item" :class="{ active: activeIndex === 3 }" @click="handleActiveFilter(3)">
|
|
|
- {{ t("workExecute.executing") }}({{ taskCounts[3] || 0 }})
|
|
|
- </div>
|
|
|
- <div class="filter-item" :class="{ active: activeIndex === 4 }" @click="handleActiveFilter(3)">
|
|
|
- {{ t("workExecute.completed") }}({{ taskCounts[4] || 0 }})
|
|
|
+ <div
|
|
|
+ v-for="item in filterTabs"
|
|
|
+ :key="item.value"
|
|
|
+ class="filter-item"
|
|
|
+ :class="{ active: activeIndex === item.value }"
|
|
|
+ @click="handleActiveFilter(item.value)"
|
|
|
+ >
|
|
|
+ {{ t(item.labelKey) }}({{ taskCounts[item.value] || 0 }})
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="list-box">
|
|
|
<div class="list-header">
|
|
|
<div class="select-group">
|
|
|
<el-select class="select-item" v-model="selectParma.farmWorkTypeId" :placeholder="t('workExecute.farmWorkType')"
|
|
|
- @change="getSimpleList">
|
|
|
+ @change="getRegionRecordData">
|
|
|
<el-option v-for="item in farmWorkTypeList" :key="item.id"
|
|
|
:label="item.id === 0 ? t('workExecute.all') : item.name"
|
|
|
:value="item.id" />
|
|
|
</el-select>
|
|
|
<el-select class="select-item" v-model="selectParma.districtCode" :placeholder="t('workExecute.farmFilter')"
|
|
|
- @change="getSimpleList">
|
|
|
+ @change="getRegionRecordData">
|
|
|
<el-option v-for="item in districtList" :key="item.code" :label="item.name"
|
|
|
:value="item.code" />
|
|
|
</el-select>
|
|
|
@@ -41,31 +38,39 @@
|
|
|
<!-- 任务列表 -->
|
|
|
<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="isTimeoutItem(index) ? 'timeout-item' : ''" @click="handleItem(item, index)">
|
|
|
- <div class="item-title">
|
|
|
+ :class="[
|
|
|
+ isAcceptOvertime(item) ? 'timeout-item' : '',
|
|
|
+ locale === 'en' ? 'task-item--en' : '',
|
|
|
+ ]" @click="handleItem(item, index)">
|
|
|
+ <div class="item-title" :class="{ 'item-title--en': locale === 'en' }">
|
|
|
<img class="task-icon" src="@/assets/img/home/task.png" alt="">
|
|
|
- <span class="title-text">{{ item.operation?.name }}</span>
|
|
|
- <span class="task-status" :class="`task-status--${item.operation?.type}`">{{
|
|
|
- item.operation?.typeName }}</span>
|
|
|
+ <div class="item-title-main">
|
|
|
+ <span class="title-text">{{ item?.operation?.name }}</span>
|
|
|
+ <span class="task-status" :class="`task-status--${getWorkType(item.operation?.type)}`">{{
|
|
|
+ item.operation?.type }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <span class="task-tag timeout" v-if="isTimeoutItem(index)">
|
|
|
+ <span class="task-tag timeout" v-if="isAcceptOvertime(item)">
|
|
|
<el-icon>
|
|
|
<WarningFilled />
|
|
|
</el-icon>
|
|
|
- {{ getTimeoutText() }}
|
|
|
+ {{ t("workExecute.acceptTimeout") }}
|
|
|
</span>
|
|
|
- <span class="task-tag" v-else>
|
|
|
+ <span class="task-tag" v-else :class="`task-tag--${getStatusTagClass()}`">
|
|
|
+ <el-icon v-if="activeStatus === '已完成'" class="task-tag__icon">
|
|
|
+ <CircleCheck />
|
|
|
+ </el-icon>
|
|
|
{{ getStatusLabel(activeStatus) }}
|
|
|
</span>
|
|
|
<div class="item-content">
|
|
|
<div class="item-info">
|
|
|
<div class="info-item">
|
|
|
<div class="info-name">{{ t("workExecute.responsible") }}</div><span class="val-text">
|
|
|
- 某某某、某某某</span>
|
|
|
+ {{ item.operation?.executor }}</span>
|
|
|
</div>
|
|
|
<div class="info-item" v-if="mode !== 'review'">
|
|
|
<div class="info-name">{{ t("workExecute.farmWorkDetail") }}</div><span class="val-text">
|
|
|
- {{ item.operation?.drug }}</span>
|
|
|
+ {{ item.operation?.work_detail }}</span>
|
|
|
</div>
|
|
|
<div class="info-item">
|
|
|
<div class="info-name">{{ t("workExecute.farmSituation") }}</div><span class="val-text">
|
|
|
@@ -94,6 +99,25 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
+ <div
|
|
|
+ v-if="activeStatus === '已完成'"
|
|
|
+ class="execute-photos"
|
|
|
+ @click.stop
|
|
|
+ >
|
|
|
+ <div class="execute-photos__wrap">
|
|
|
+ <span class="execute-photos__label">{{ t('workExecute.executePhotos') }}</span>
|
|
|
+ <div class="execute-photos__list">
|
|
|
+ <div
|
|
|
+ v-for="(photo, photoIndex) in getExecutePhotoList(item)"
|
|
|
+ :key="photoIndex"
|
|
|
+ class="execute-photos__item"
|
|
|
+ >
|
|
|
+ <img :src="photo" alt="" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div class="unqualified-reason" v-if="activeStatus === '未达标'">
|
|
|
{{ t("workExecute.unqualifiedReason") }}{{ item.operation?.reason || t("workExecute.defaultUnqualifiedReason") }}
|
|
|
</div>
|
|
|
@@ -112,44 +136,46 @@
|
|
|
|
|
|
<div class="task-footer">
|
|
|
<div class="farm-info">{{ t("workExecute.fromFarm") }}</div>
|
|
|
- <div class="btn-group" v-if="getItemStatusButtons(index).length">
|
|
|
- <div v-for="btn in getItemStatusButtons(index)" :key="btn.label" class="edit-btn"
|
|
|
+ <div class="btn-group" v-if="getItemStatusButtons(item).length">
|
|
|
+ <div v-for="btn in getItemStatusButtons(item)" :key="btn.label" class="edit-btn"
|
|
|
:class="btn.type" @click.stop="handleStatusBtn(btn, item, index)">
|
|
|
{{ btn.label }}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
</div>
|
|
|
-
|
|
|
<div class="empty-tip" v-if="!loading && taskList.length === 0">{{ t("workExecute.noData") }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <!-- <upload-execute ref="uploadExecuteRef" :onlyShare="onlyShare" @uploadSuccess="handleUploadSuccess" /> -->
|
|
|
- <!-- 服务报价单 -->
|
|
|
- <!-- <price-sheet-popup :key="activeIndex" ref="priceSheetPopupRef"></price-sheet-popup> -->
|
|
|
- <!-- 新增:激活上传弹窗 -->
|
|
|
- <!-- <active-upload-popup ref="activeUploadPopupRef" @handleUploadSuccess="handleUploadSuccess"></active-upload-popup> -->
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import { computed, nextTick, onActivated, onMounted, ref, watch } from "vue";
|
|
|
-import { useRoute } from "vue-router";
|
|
|
import { useStore } from "vuex";
|
|
|
import IndexMap from "./index";
|
|
|
import { useRouter } from "vue-router";
|
|
|
-import { WarningFilled } from "@element-plus/icons-vue";
|
|
|
+import { WarningFilled, CircleCheck } from "@element-plus/icons-vue";
|
|
|
import { ElMessage } from "element-plus";
|
|
|
import config from "@/api/config.js";
|
|
|
import customCalendar from "./components/calendar.vue";
|
|
|
import { useI18n } from "@/i18n";
|
|
|
-
|
|
|
-const { t } = useI18n();
|
|
|
+import executePhotoPlaceholder1 from "@/assets/img/common/sd-1.jpg";
|
|
|
+import executePhotoPlaceholder2 from "@/assets/img/common/sd-2.jpg";
|
|
|
+import executePhotoPlaceholder3 from "@/assets/img/common/sd-3.jpg";
|
|
|
+import executePhotoPlaceholder4 from "@/assets/img/common/sd-4.jpg";
|
|
|
+
|
|
|
+const EXECUTE_PHOTO_PLACEHOLDERS = [
|
|
|
+ executePhotoPlaceholder1,
|
|
|
+ executePhotoPlaceholder2,
|
|
|
+ executePhotoPlaceholder3,
|
|
|
+ executePhotoPlaceholder4,
|
|
|
+];
|
|
|
+
|
|
|
+const { t, locale } = useI18n();
|
|
|
const store = useStore();
|
|
|
const router = useRouter();
|
|
|
-const route = useRoute();
|
|
|
const indexMap = new IndexMap();
|
|
|
const mapContainer = ref(null);
|
|
|
const tabBarHeight = computed(() => store.state.home.tabBarHeight);
|
|
|
@@ -158,89 +184,21 @@ const selectParma = ref({
|
|
|
districtCode: null,
|
|
|
});
|
|
|
|
|
|
-// 任务列表数据(用于显示,可能被筛选)
|
|
|
-const taskList = ref([
|
|
|
- {
|
|
|
- time: "Fri, 22 May 2026 00:00:00 GMT",
|
|
|
- geohash_sample: "ws0gs49ns213",
|
|
|
- farmName: "冬季清园",
|
|
|
- typeName: "荔枝",
|
|
|
- userType: 1,
|
|
|
- address: "广东省广州市从化区太平镇凤凰路88号",
|
|
|
- farmPoint: "POINT(113.61652616170711 23.58399613872042)",
|
|
|
- sourceData: {
|
|
|
- currentPhenologyName: "花芽分化",
|
|
|
- currentPhenologyStartDate: "2026-01-15",
|
|
|
- daysUntilNext: 3,
|
|
|
- },
|
|
|
- operation: {
|
|
|
- name: "冬季清园",
|
|
|
- type: "1",
|
|
|
- typeName: "标准类",
|
|
|
- work_reason: "近期气温回升,需及时清理园内枯枝落叶,减少病虫越冬基数",
|
|
|
- drug: "石硫合剂 500倍液",
|
|
|
- machine_code: "DJI-T40-001",
|
|
|
- work_id: 5001,
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- time: "Mon, 26 May 2026 00:00:00 GMT",
|
|
|
- geohash_sample: "ws0gefxm68u5",
|
|
|
- farmName: "施肥促花",
|
|
|
- typeName: "柑橘",
|
|
|
- userType: 2,
|
|
|
- address: "广东省肇庆市德庆县官圩镇果园示范区",
|
|
|
- farmPoint: "POINT(113.62757101477101 23.590796948574365)",
|
|
|
- sourceData: {
|
|
|
- currentPhenologyName: "开花期",
|
|
|
- currentPhenologyStartDate: "2026-02-20",
|
|
|
- daysUntilNext: 12,
|
|
|
- },
|
|
|
- operation: {
|
|
|
- name: "施肥促花",
|
|
|
- type: "2",
|
|
|
- typeName: "感知类",
|
|
|
- work_reason: "花芽分化期养分需求增加,需补充磷钾肥",
|
|
|
- drug: "磷酸二氢钾 0.3%",
|
|
|
- machine_code: "DJI-T50-003",
|
|
|
- work_id: 5002,
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- time: "Wed, 28 May 2026 00:00:00 GMT",
|
|
|
- geohash_sample: "ws0gefzjqqqw",
|
|
|
- farmId: 1003,
|
|
|
- farmName: "病虫害防治",
|
|
|
- typeName: "水稻",
|
|
|
- userType: 1,
|
|
|
- address: "广东省清远市清城区龙塘镇农业科技园",
|
|
|
- farmPoint: "POINT(113.62240816252164 23.59499176519138)",
|
|
|
- sourceData: {
|
|
|
- currentPhenologyName: "分蘖期",
|
|
|
- currentPhenologyStartDate: "2026-03-01",
|
|
|
- daysUntilNext: 8,
|
|
|
- },
|
|
|
- operation: {
|
|
|
- name: "病虫害防治",
|
|
|
- type: "1",
|
|
|
- typeName: "复核类",
|
|
|
- work_reason: "监测到蚜虫活动增多,建议及时喷药防治",
|
|
|
- drug: "吡虫啉 1500倍液",
|
|
|
- machine_code: "DJI-T40-002",
|
|
|
- work_id: 5003,
|
|
|
- },
|
|
|
- },
|
|
|
-]);
|
|
|
+const taskList = ref([])
|
|
|
+
|
|
|
const mode = "execute";
|
|
|
const activeStatus = ref("待接受");
|
|
|
|
|
|
const STATUS_BTN_MAP = {
|
|
|
待接受: [
|
|
|
- { labelKey: "workExecute.redispatch", type: "normal", action: "redispatch" },
|
|
|
- { labelKey: "workExecute.remindAccept", type: "primary", action: "remindAccept" },
|
|
|
+ { labelKey: "workExecute.modifyInfo", type: "normal", action: "redispatch" },
|
|
|
+ { labelKey: "workExecute.acceptTask", type: "primary", action: "remindAccept" },
|
|
|
+ ],
|
|
|
+ 已接受: [
|
|
|
+ { labelKey: "workExecute.modifyInfo", type: "normal", action: "redispatch" },
|
|
|
+ { labelKey: "workExecute.startExecute", type: "primary-blue", action: "startExecute" },
|
|
|
],
|
|
|
- 已接受: [{ labelKey: "workExecute.remindExecute", type: "primary", action: "remindExecute" }],
|
|
|
- 执行中: [{ labelKey: "workExecute.remindComplete", type: "primary", action: "remindComplete" }],
|
|
|
+ 执行中: [{ labelKey: "workExecute.markComplete", type: "primary-green", action: "markComplete" }],
|
|
|
已超时: [
|
|
|
{ labelKey: "workExecute.redispatch", type: "normal", action: "redispatch" },
|
|
|
{ labelKey: "workExecute.remindAccept", type: "primary", action: "remindAccept" },
|
|
|
@@ -259,52 +217,28 @@ const STATUS_LABEL_MAP = {
|
|
|
|
|
|
const getStatusLabel = (status) => t(STATUS_LABEL_MAP[status] || status);
|
|
|
|
|
|
-const isTimeoutItem = (index) => index === 0;
|
|
|
-
|
|
|
-const getTimeoutRemindBtn = () => {
|
|
|
- const map = {
|
|
|
- 待接受: { labelKey: "workExecute.remindAccept", type: "primary", action: "remindAccept" },
|
|
|
- 已接受: { labelKey: "workExecute.remindExecute", type: "primary", action: "remindExecute" },
|
|
|
- 执行中: { labelKey: "workExecute.remindComplete", type: "primary", action: "remindComplete" },
|
|
|
- };
|
|
|
- const btn = map[activeStatus.value];
|
|
|
- return btn ? { ...btn, label: t(btn.labelKey) } : null;
|
|
|
+const STATUS_TAG_CLASS_MAP = {
|
|
|
+ 待接受: "pending",
|
|
|
+ 已接受: "accepted",
|
|
|
+ 执行中: "executing",
|
|
|
+ 已完成: "completed",
|
|
|
};
|
|
|
|
|
|
+const getStatusTagClass = () => STATUS_TAG_CLASS_MAP[activeStatus.value] || "pending";
|
|
|
+
|
|
|
+const isAcceptOvertime = (item) => Number(item?.operation?.is_aovertime) === 1;
|
|
|
+
|
|
|
const mapStatusButtons = (buttons) =>
|
|
|
buttons.map((btn) => ({
|
|
|
...btn,
|
|
|
label: t(btn.labelKey),
|
|
|
}));
|
|
|
|
|
|
-const getItemStatusButtons = (index) => {
|
|
|
- const baseButtons = mapStatusButtons(STATUS_BTN_MAP[activeStatus.value] || []);
|
|
|
- if (!isTimeoutItem(index)) {
|
|
|
- return baseButtons;
|
|
|
- }
|
|
|
- if (activeStatus.value === "待接受") {
|
|
|
- return baseButtons;
|
|
|
- }
|
|
|
- const remindBtn = getTimeoutRemindBtn();
|
|
|
- if (remindBtn) {
|
|
|
- return [
|
|
|
- { label: t("workExecute.redispatch"), type: "normal", action: "redispatch" },
|
|
|
- remindBtn,
|
|
|
- ];
|
|
|
+const getItemStatusButtons = (item) => {
|
|
|
+ if (isAcceptOvertime(item)) {
|
|
|
+ return [];
|
|
|
}
|
|
|
- return [
|
|
|
- { label: t("workExecute.redispatch"), type: "normal", action: "redispatch" },
|
|
|
- ...baseButtons,
|
|
|
- ];
|
|
|
-};
|
|
|
-
|
|
|
-const getTimeoutText = () => {
|
|
|
- const map = {
|
|
|
- 待接受: "workExecute.acceptTimeout",
|
|
|
- 已接受: "workExecute.executeTimeout",
|
|
|
- 执行中: "workExecute.completeTimeout",
|
|
|
- };
|
|
|
- return t(map[activeStatus.value] || "workExecute.timeout");
|
|
|
+ return mapStatusButtons(STATUS_BTN_MAP[activeStatus.value] || []);
|
|
|
};
|
|
|
|
|
|
const formatGMTToYMD = (gmtString) => {
|
|
|
@@ -317,14 +251,56 @@ const getWorkImageUrl = (image) => {
|
|
|
return config.base_img_url3 + image.cloud_filename;
|
|
|
};
|
|
|
|
|
|
+const resolveExecutePhotoUrl = (src) => {
|
|
|
+ if (!src) return "";
|
|
|
+ if (typeof src === "object" && src.cloud_filename) {
|
|
|
+ return config.base_img_url3 + src.cloud_filename;
|
|
|
+ }
|
|
|
+ if (typeof src === "string") {
|
|
|
+ if (src.startsWith("http")) return src;
|
|
|
+ return config.base_img_url2 + src;
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+};
|
|
|
+
|
|
|
+const getExecutePhotoList = (item) => {
|
|
|
+ const operation = item?.operation || {};
|
|
|
+ const raw =
|
|
|
+ operation.execute_evidence ??
|
|
|
+ operation.executeEvidence ??
|
|
|
+ item.execute_evidence ??
|
|
|
+ item.executeEvidence;
|
|
|
+
|
|
|
+ let photos = [];
|
|
|
+
|
|
|
+ if (raw) {
|
|
|
+ if (Array.isArray(raw)) {
|
|
|
+ photos = raw.map(resolveExecutePhotoUrl).filter(Boolean);
|
|
|
+ } else if (typeof raw === "string") {
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(raw);
|
|
|
+ if (Array.isArray(parsed)) {
|
|
|
+ photos = parsed.map(resolveExecutePhotoUrl).filter(Boolean);
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ const url = resolveExecutePhotoUrl(raw);
|
|
|
+ if (url) photos = [url];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (photos.length ? photos : EXECUTE_PHOTO_PLACEHOLDERS).slice(0, 4);
|
|
|
+};
|
|
|
+
|
|
|
const handleItem = (item, index) => {
|
|
|
+ const statusStr = item.operation?.is_aovertime ? '接受超时' : activeStatus.value;
|
|
|
+ const status = item.operation?.is_aovertime ? 1 : activeIndex.value;
|
|
|
router.push({
|
|
|
path: "/agri_record_detail",
|
|
|
query: {
|
|
|
- miniJson: JSON.stringify({
|
|
|
- id: item.operation?.work_id,
|
|
|
- status: activeStatus.value,
|
|
|
- }),
|
|
|
+ id: item.operation?.work_id,
|
|
|
+ status,
|
|
|
+ statusStr,
|
|
|
},
|
|
|
});
|
|
|
};
|
|
|
@@ -368,21 +344,15 @@ const handleDateSelect = (date) => {
|
|
|
};
|
|
|
// 各状态任务数量
|
|
|
const taskCounts = ref([0, 0, 0]);
|
|
|
+const filterTabs = [
|
|
|
+ { value: 0, labelKey: "workExecute.pending" },
|
|
|
+ { value: 2, labelKey: "workExecute.accepted" },
|
|
|
+ { value: 1, labelKey: "workExecute.executing" },
|
|
|
+ { value: 3, labelKey: "workExecute.completed" },
|
|
|
+];
|
|
|
// 当前选中的筛选索引
|
|
|
-const activeIndex = ref(2);
|
|
|
-const noData = ref(false);
|
|
|
+const activeIndex = ref(0);
|
|
|
const loading = ref(false);
|
|
|
-// 分页相关
|
|
|
-const page = ref(0);
|
|
|
-const limit = ref(10);
|
|
|
-const loadingMore = ref(false);
|
|
|
-const finished = ref(false);
|
|
|
-
|
|
|
-// 查询未来农事预警
|
|
|
-const getFutureFarmWorkWarning = async (item) => {
|
|
|
- const res = await VE_API.home.listFutureFarmWorkWarning({ farmId: item.farmId });
|
|
|
- item.timelineList = res.data || [];
|
|
|
-};
|
|
|
|
|
|
const cityCode = ref("");
|
|
|
//根据城市的坐标返回区县列表
|
|
|
@@ -401,8 +371,6 @@ const mapPoint = ref(null);
|
|
|
|
|
|
onMounted(() => {
|
|
|
mapPoint.value = store.state.home.miniUserLocationPoint;
|
|
|
- fullTaskList.value = [...taskList.value];
|
|
|
- // getDistrictListByCity();
|
|
|
resetAndLoad();
|
|
|
getFarmWorkTypeList();
|
|
|
syncCalendarData();
|
|
|
@@ -415,9 +383,7 @@ onMounted(() => {
|
|
|
});
|
|
|
|
|
|
onActivated(() => {
|
|
|
- if (route.query.noReload) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ getRegionRecordData();
|
|
|
// 确保地图已初始化,使用 nextTick 等待 DOM 更新
|
|
|
nextTick(() => {
|
|
|
// 检查地图实例是否已初始化
|
|
|
@@ -458,124 +424,50 @@ onActivated(() => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
-// 监听 activeIndex 变化,重新加载数据
|
|
|
-watch(activeIndex, () => {
|
|
|
- resetAndLoad();
|
|
|
-});
|
|
|
-
|
|
|
-// 加载列表数据(支持分页)
|
|
|
-async function getSimpleList(isLoadMore = false) {
|
|
|
- if (!isLoadMore) {
|
|
|
- // 重置分页
|
|
|
- page.value = 0;
|
|
|
- finished.value = false;
|
|
|
- // taskList.value = [];
|
|
|
- loading.value = true;
|
|
|
- } else {
|
|
|
- loadingMore.value = true;
|
|
|
- }
|
|
|
-
|
|
|
+const getRegionRecordData = async () => {
|
|
|
const params = {
|
|
|
- ...selectParma.value,
|
|
|
- page: page.value,
|
|
|
- limit: limit.value,
|
|
|
- flowStatus: 5,
|
|
|
+ // farm_id: store.state.home.miniUserFarmId,
|
|
|
+ farm_id: '320',
|
|
|
+ time: '2026-06-23',
|
|
|
+ work_operation_type: activeIndex.value,
|
|
|
};
|
|
|
-
|
|
|
- try {
|
|
|
- const { data } = await VE_API.home.listUnansweredFarms(params);
|
|
|
-
|
|
|
- if (data && data.length > 0) {
|
|
|
- // 为每个item初始化timelineList
|
|
|
- const newItems = data.map((item) => {
|
|
|
- let sourceData = item?.latestPhenologyProgressBroadcast?.sourceData;
|
|
|
- if (sourceData) {
|
|
|
- try {
|
|
|
- sourceData = JSON.parse(sourceData);
|
|
|
- } catch (e) {
|
|
|
- console.error("解析sourceData失败:", e);
|
|
|
- sourceData = null;
|
|
|
- }
|
|
|
- }
|
|
|
- return {
|
|
|
- ...item,
|
|
|
- sourceData,
|
|
|
- timelineList: [],
|
|
|
- };
|
|
|
- });
|
|
|
-
|
|
|
- // 串行请求,为每个农场获取时间轴数据
|
|
|
- for (let i = 0; i < newItems.length; i++) {
|
|
|
- await getFutureFarmWorkWarning(newItems[i]);
|
|
|
- }
|
|
|
-
|
|
|
- // 追加数据
|
|
|
- // const newTaskList = [...taskList.value, ...newItems];
|
|
|
- // taskList.value = newTaskList.filter(item => item.timelineList.length > 0);
|
|
|
-
|
|
|
- // 更新分页
|
|
|
- page.value += 1;
|
|
|
-
|
|
|
- // 判断是否还有更多数据
|
|
|
- if (data.length < limit.value) {
|
|
|
- finished.value = true;
|
|
|
- }
|
|
|
-
|
|
|
- // 更新地图数据
|
|
|
- indexMap.initData(taskList.value, '', 'farmPoint');
|
|
|
- } else {
|
|
|
- finished.value = true;
|
|
|
- if (taskList.value.length === 0) {
|
|
|
- noData.value = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 数据处理完成后再设置loading为false
|
|
|
- if (!isLoadMore) {
|
|
|
- loading.value = false;
|
|
|
- } else {
|
|
|
- loadingMore.value = false;
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error("获取任务列表失败:", error);
|
|
|
- if (!isLoadMore) {
|
|
|
- loading.value = false;
|
|
|
- } else {
|
|
|
- loadingMore.value = false;
|
|
|
- }
|
|
|
- finished.value = true;
|
|
|
- if (taskList.value.length === 0) {
|
|
|
- noData.value = true;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 滚动加载更多
|
|
|
-const onLoad = () => {
|
|
|
- if (!finished.value && !loadingMore.value) {
|
|
|
- getSimpleList(true);
|
|
|
+ const { code, data } = await VE_API.farm.getRegionRecord(params);
|
|
|
+ if (code === 200 && data && data.length > 0) {
|
|
|
+ taskList.value = data.filter(item => item.operation !== null);
|
|
|
+ } else {
|
|
|
+ taskList.value = [];
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 监听 activeIndex 变化,重新加载数据
|
|
|
+watch(activeIndex, () => {
|
|
|
+ resetAndLoad();
|
|
|
+});
|
|
|
+
|
|
|
// 重置并重新加载
|
|
|
const resetAndLoad = () => {
|
|
|
- getSimpleList(false);
|
|
|
+ getRegionRecordData();
|
|
|
};
|
|
|
|
|
|
function handleActiveFilter(i) {
|
|
|
activeIndex.value = i;
|
|
|
selectParma.value.districtCode = cityCode.value;
|
|
|
selectParma.value.farmWorkTypeId = null;
|
|
|
- const statusMap = { 0: "待接受", 2: "已接受", 3: "执行中" };
|
|
|
+ const statusMap = { 0: "待接受", 1: "执行中", 2: "已接受", 3: "已完成" };
|
|
|
activeStatus.value = statusMap[i] || "待接受";
|
|
|
filterDate.value = null;
|
|
|
- taskList.value = [...fullTaskList.value];
|
|
|
+ // taskList.value = [...fullTaskList.value];
|
|
|
calendarRef.value?.clearSelection();
|
|
|
syncCalendarData();
|
|
|
}
|
|
|
|
|
|
-function handleRemindCustomer(item) {
|
|
|
- // 接受
|
|
|
+const getWorkType = (type) => {
|
|
|
+ const map = {
|
|
|
+ '标准防治类': 1,
|
|
|
+ '标准施肥类': 2,
|
|
|
+ '标准调节类': 3,
|
|
|
+ }
|
|
|
+ return map[type] || type;
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
@@ -730,9 +622,14 @@ function handleRemindCustomer(item) {
|
|
|
border: 1px solid #f74e4e;
|
|
|
}
|
|
|
|
|
|
+ &--en {
|
|
|
+ padding-top: 22px;
|
|
|
+ }
|
|
|
+
|
|
|
.item-title {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
+ gap: 8px;
|
|
|
padding-bottom: 10px;
|
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
|
|
color: #1d2129;
|
|
|
@@ -740,14 +637,41 @@ function handleRemindCustomer(item) {
|
|
|
|
|
|
.task-icon {
|
|
|
width: 16px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-title-main {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--en {
|
|
|
+ align-items: flex-start;
|
|
|
+
|
|
|
+ .task-icon {
|
|
|
+ margin-top: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-title-main {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .task-status {
|
|
|
+ margin-left: 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.title-text {
|
|
|
- padding-left: 8px;
|
|
|
+ min-width: 0;
|
|
|
}
|
|
|
|
|
|
.task-status {
|
|
|
- margin-left: 8px;
|
|
|
+ margin-left: 0;
|
|
|
border-radius: 2px;
|
|
|
height: 20px;
|
|
|
line-height: 20px;
|
|
|
@@ -793,6 +717,77 @@ function handleRemindCustomer(item) {
|
|
|
align-items: center;
|
|
|
gap: 2px;
|
|
|
}
|
|
|
+
|
|
|
+ &--pending {
|
|
|
+ background: rgba(255, 149, 61, 0.1);
|
|
|
+ color: #F46E00;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--accepted {
|
|
|
+ background: rgba(33, 153, 248, 0.1);
|
|
|
+ color: #2199F8;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--executing {
|
|
|
+ background: rgba(33, 153, 248, 0.1);
|
|
|
+ color: #2199F8;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--completed {
|
|
|
+ background: rgba(74, 191, 50, 0.1);
|
|
|
+ color: #4ABF32;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 2px;
|
|
|
+
|
|
|
+ .task-tag__icon {
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .execute-photos {
|
|
|
+ margin: 8px 0 4px;
|
|
|
+
|
|
|
+ &__wrap {
|
|
|
+ background: #ebf5ff;
|
|
|
+ border: 1px solid rgba(33, 153, 248, 0.15);
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__label {
|
|
|
+ display: inline-block;
|
|
|
+ padding: 4px 10px;
|
|
|
+ background: #2199f8;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 18px;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__list {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__item {
|
|
|
+ flex: 1;
|
|
|
+ aspect-ratio: 1;
|
|
|
+ border-radius: 8px;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ img {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: cover;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.item-content {
|
|
|
@@ -895,6 +890,16 @@ function handleRemindCustomer(item) {
|
|
|
background: #FF953D;
|
|
|
color: #fff;
|
|
|
}
|
|
|
+
|
|
|
+ &.primary-blue {
|
|
|
+ background: #2199F8;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.primary-green {
|
|
|
+ background: #37C11B;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.compare-imgs {
|