|
|
@@ -37,13 +37,50 @@
|
|
|
@confirm="handleShareFarm"
|
|
|
@handleClickOverlay="handleClickOverlay"
|
|
|
/>
|
|
|
+
|
|
|
+ <!-- 物候期设置弹窗 -->
|
|
|
+ <Popup
|
|
|
+ v-model:show="showPhenologySetting"
|
|
|
+ class="copy-plan-popup phenology-popup"
|
|
|
+ round
|
|
|
+ closeable
|
|
|
+ :close-on-click-overlay="false"
|
|
|
+ >
|
|
|
+ <div class="phenology-header">物候期时间设置</div>
|
|
|
+ <div class="phenology-list">
|
|
|
+ <div class="phenology-item" v-for="(item, index) in mergedReproductiveList" :key="item.id || index">
|
|
|
+ <div class="item-label">
|
|
|
+ <span class="label-text">{{ item.name }}</span>
|
|
|
+ <span>起始时间</span>
|
|
|
+ </div>
|
|
|
+ <div class="item-value">
|
|
|
+ <el-date-picker
|
|
|
+ style="width: 100%"
|
|
|
+ size="large"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ v-model="item.startDate"
|
|
|
+ :clearable="false"
|
|
|
+ :editable="false"
|
|
|
+ type="date"
|
|
|
+ placeholder="选择日期"
|
|
|
+ @change="(date) => handleStartDateChange(date, index)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="phenology-footer-tip">
|
|
|
+ <span>注:</span>
|
|
|
+ <span class="text">请从上往下按照时间顺序填写日期</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="phenology-footer" @click="handleConfirmPhenologySetting">确认设置</div>
|
|
|
+ </Popup>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import customHeader from "@/components/customHeader.vue";
|
|
|
import { onActivated, ref, onDeactivated } from "vue";
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
-import { Tab, Tabs } from "vant";
|
|
|
+import { Tab, Tabs, Popup } from "vant";
|
|
|
import FarmWorkPlanTimeline from "@/components/pageComponents/FarmWorkPlanTimeline.vue";
|
|
|
import wx from "weixin-js-sdk";
|
|
|
import tabList from "@/components/pageComponents/TabList.vue";
|
|
|
@@ -84,54 +121,125 @@ const getListMySchemes = () => {
|
|
|
const showFarmPopup = ref(false);
|
|
|
const shareData = ref({});
|
|
|
const isCreating = ref(false); // 标识是否正在创建农场
|
|
|
-const handleConfirmPlan = () => {
|
|
|
- // 如果正在创建,阻止重复点击
|
|
|
- if (isCreating.value) {
|
|
|
+
|
|
|
+// 物候期设置相关
|
|
|
+const showPhenologySetting = ref(false);
|
|
|
+const mergedReproductiveList = ref([]);
|
|
|
+const containerSpaceTimeId = ref(null);
|
|
|
+const intervalDaysArr = ref([]);
|
|
|
+const pendingFarmParams = ref(null); // 保存待创建的农场参数
|
|
|
+
|
|
|
+// 获取物候期列表
|
|
|
+const getPhenologyList = async () => {
|
|
|
+ if (!containerSpaceTimeId.value) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- // 从路由参数中获取农场数据
|
|
|
- let geomValue = route.query.geom;
|
|
|
-
|
|
|
- // 处理 geom 参数,可能是 JSON 字符串或数组
|
|
|
- if (typeof geomValue === "string") {
|
|
|
- try {
|
|
|
- // 尝试解析 JSON 字符串
|
|
|
- const parsed = JSON.parse(geomValue);
|
|
|
- if (Array.isArray(parsed)) {
|
|
|
- geomValue = parsed;
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- // 如果不是 JSON 字符串,保持原值
|
|
|
- console.warn("geom 参数解析失败,使用原值:", e);
|
|
|
+ const userInfoStr = localStorage.getItem("localUserInfo");
|
|
|
+ const userInfo = userInfoStr ? JSON.parse(userInfoStr) : {};
|
|
|
+ const params = {
|
|
|
+ containerSpaceTimeId: containerSpaceTimeId.value,
|
|
|
+ agriculturalId: userInfo?.agriculturalId,
|
|
|
+ farmId: route.query.farmId || null,
|
|
|
+ };
|
|
|
+ const res = await VE_API.monitor.listPhenology(params);
|
|
|
+ if (res.code === 0) {
|
|
|
+ // 将intervalDaysArr合并到mergedReproductiveList中
|
|
|
+ if (intervalDaysArr.value.length > 0 && res.data.length > 0) {
|
|
|
+ mergedReproductiveList.value = res.data.map((item, index) => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ intervalDays: intervalDaysArr.value[index],
|
|
|
+ };
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ mergedReproductiveList.value = res.data;
|
|
|
}
|
|
|
}
|
|
|
+};
|
|
|
|
|
|
- const farmParams = {
|
|
|
- ...route.query,
|
|
|
- containerId: containerId.value,
|
|
|
- geom: geomValue,
|
|
|
- defaultFarm: Boolean(route.query.defaultFarm),
|
|
|
- agriculturalCreate: route.query.agriculturalCreate * 1,
|
|
|
- };
|
|
|
+// 获取农事规划数据以获取 containerSpaceTimeId
|
|
|
+const getFarmWorkPlanForPhenology = async () => {
|
|
|
+ try {
|
|
|
+ const { data, code } = await VE_API.monitor.farmWorkPlan({
|
|
|
+ containerId: containerId.value,
|
|
|
+ schemeId: active.value,
|
|
|
+ });
|
|
|
+ if (code === 0 && data?.phenologyList?.[0]?.containerSpaceTimeId) {
|
|
|
+ containerSpaceTimeId.value = data.phenologyList[0].containerSpaceTimeId;
|
|
|
+ intervalDaysArr.value = [];
|
|
|
+ data.phenologyList.forEach((phenology) => {
|
|
|
+ intervalDaysArr.value.push(phenology.intervalDays);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取农事规划数据失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
- // 验证必填字段
|
|
|
- if (
|
|
|
- !farmParams.wkt ||
|
|
|
- !farmParams.speciesId ||
|
|
|
- !farmParams.containerId ||
|
|
|
- !farmParams.address ||
|
|
|
- !farmParams.mu ||
|
|
|
- !farmParams.name ||
|
|
|
- !farmParams.fzr ||
|
|
|
- !farmParams.tel
|
|
|
- ) {
|
|
|
- ElMessage.error("农场信息不完整,请返回重新填写");
|
|
|
+/**
|
|
|
+ * 处理物候期开始时间变化
|
|
|
+ * 当修改某个物候期的开始时间时,自动更新后续所有物候期的开始时间
|
|
|
+ */
|
|
|
+const handleStartDateChange = (date, currentIndex) => {
|
|
|
+ if (!date || !mergedReproductiveList.value || mergedReproductiveList.value.length === 0) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- delete farmParams.from;
|
|
|
|
|
|
+ // 从当前修改的物候期开始,更新后续所有物候期的开始时间
|
|
|
+ for (let i = currentIndex; i < mergedReproductiveList.value.length - 1; i++) {
|
|
|
+ const currentItem = mergedReproductiveList.value[i];
|
|
|
+ const nextItem = mergedReproductiveList.value[i + 1];
|
|
|
+
|
|
|
+ // 获取当前物候期的间隔天数
|
|
|
+ const intervalDays = currentItem.intervalDays || 0;
|
|
|
+
|
|
|
+ if (intervalDays > 0 && currentItem.startDate) {
|
|
|
+ // 将日期字符串转换为时间戳(毫秒)
|
|
|
+ const currentStartDateTimestamp = new Date(currentItem.startDate).getTime();
|
|
|
+
|
|
|
+ // 在时间戳基础上加上间隔天数(转换为毫秒:天数 * 24小时 * 60分钟 * 60秒 * 1000毫秒)
|
|
|
+ const nextStartDateTimestamp = currentStartDateTimestamp + (intervalDays * 24 * 60 * 60 * 1000);
|
|
|
+
|
|
|
+ // 将时间戳转换回日期对象,然后格式化为 YYYY-MM-DD 格式
|
|
|
+ const nextStartDate = new Date(nextStartDateTimestamp);
|
|
|
+ const year = nextStartDate.getFullYear();
|
|
|
+ const month = String(nextStartDate.getMonth() + 1).padStart(2, '0');
|
|
|
+ const day = String(nextStartDate.getDate()).padStart(2, '0');
|
|
|
+ const nextStartDateStr = `${year}-${month}-${day}`;
|
|
|
+
|
|
|
+ // 更新下一个物候期的开始时间
|
|
|
+ nextItem.startDate = nextStartDateStr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * 确认物候期设置
|
|
|
+ */
|
|
|
+const handleConfirmPhenologySetting = async () => {
|
|
|
+ const userInfoStr = localStorage.getItem("localUserInfo");
|
|
|
+ const userInfo = userInfoStr ? JSON.parse(userInfoStr) : {};
|
|
|
+ const params = {
|
|
|
+ farmId: route.query.farmId || null,
|
|
|
+ agriculturalId: userInfo?.agriculturalId,
|
|
|
+ items: mergedReproductiveList.value.map((item) => ({
|
|
|
+ phenologyId: item.id,
|
|
|
+ startDate: item.startDate,
|
|
|
+ })),
|
|
|
+ };
|
|
|
+ const res = await VE_API.monitor.batchSaveFarmPhenologyTime(params);
|
|
|
+ if (res.code === 0) {
|
|
|
+ showPhenologySetting.value = false;
|
|
|
+ // 物候期设置完成后,继续创建农场
|
|
|
+ if (pendingFarmParams.value) {
|
|
|
+ createFarm(pendingFarmParams.value);
|
|
|
+ pendingFarmParams.value = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 创建农场的实际逻辑
|
|
|
+const createFarm = (farmParams) => {
|
|
|
// 设置正在创建状态
|
|
|
isCreating.value = true;
|
|
|
|
|
|
@@ -174,6 +282,68 @@ const handleConfirmPlan = () => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
+const handleConfirmPlan = async () => {
|
|
|
+ // 如果正在创建,阻止重复点击
|
|
|
+ if (isCreating.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从路由参数中获取农场数据
|
|
|
+ let geomValue = route.query.geom;
|
|
|
+
|
|
|
+ // 处理 geom 参数,可能是 JSON 字符串或数组
|
|
|
+ if (typeof geomValue === "string") {
|
|
|
+ try {
|
|
|
+ // 尝试解析 JSON 字符串
|
|
|
+ const parsed = JSON.parse(geomValue);
|
|
|
+ if (Array.isArray(parsed)) {
|
|
|
+ geomValue = parsed;
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ // 如果不是 JSON 字符串,保持原值
|
|
|
+ console.warn("geom 参数解析失败,使用原值:", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const farmParams = {
|
|
|
+ ...route.query,
|
|
|
+ containerId: containerId.value,
|
|
|
+ geom: geomValue,
|
|
|
+ defaultFarm: Boolean(route.query.defaultFarm),
|
|
|
+ agriculturalCreate: route.query.agriculturalCreate * 1,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 验证必填字段
|
|
|
+ if (
|
|
|
+ !farmParams.wkt ||
|
|
|
+ !farmParams.speciesId ||
|
|
|
+ !farmParams.containerId ||
|
|
|
+ !farmParams.address ||
|
|
|
+ !farmParams.mu ||
|
|
|
+ !farmParams.name ||
|
|
|
+ !farmParams.fzr ||
|
|
|
+ !farmParams.tel
|
|
|
+ ) {
|
|
|
+ ElMessage.error("农场信息不完整,请返回重新填写");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ delete farmParams.from;
|
|
|
+
|
|
|
+ // 先获取物候期数据,然后弹出物候期设置弹窗
|
|
|
+ await getFarmWorkPlanForPhenology();
|
|
|
+ if (containerSpaceTimeId.value) {
|
|
|
+ // 保存待创建的农场参数
|
|
|
+ pendingFarmParams.value = farmParams;
|
|
|
+ // 获取物候期列表并显示弹窗
|
|
|
+ await getPhenologyList();
|
|
|
+ showPhenologySetting.value = true;
|
|
|
+ } else {
|
|
|
+ // 如果没有物候期数据,直接创建农场
|
|
|
+ createFarm(farmParams);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
const handleShareFarm = () => {
|
|
|
const query = {
|
|
|
agriculturalStoreId: shareData.value.agriculturalStoreId,
|
|
|
@@ -253,4 +423,58 @@ const handleClickOverlay = () => {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.phenology-popup {
|
|
|
+ padding: 28px 20px 20px;
|
|
|
+ .phenology-header {
|
|
|
+ font-size: 24px;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ font-family: "PangMenZhengDao";
|
|
|
+ }
|
|
|
+ .phenology-list {
|
|
|
+ width: 100%;
|
|
|
+ .phenology-item {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ .item-label {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+ font-size: 15px;
|
|
|
+ color: rgba(0, 0, 0, 0.4);
|
|
|
+ .label-text {
|
|
|
+ color: #000;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .item-value {
|
|
|
+ width: calc(100% - 156px);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .phenology-item + .phenology-item {
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .phenology-footer-tip {
|
|
|
+ margin-top: 20px;
|
|
|
+ text-align: center;
|
|
|
+ .text{
|
|
|
+ color: rgba(0, 0, 0, 0.4);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .phenology-footer {
|
|
|
+ width: 100%;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 16px;
|
|
|
+ margin-top: 10px;
|
|
|
+ color: #fff;
|
|
|
+ background: #2199f8;
|
|
|
+ border-radius: 25px;
|
|
|
+ padding: 10px 0;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|