|
@@ -2,28 +2,20 @@
|
|
|
<div class="select-variety">
|
|
<div class="select-variety">
|
|
|
<div class="select-variety__content">
|
|
<div class="select-variety__content">
|
|
|
<div class="page-header">
|
|
<div class="page-header">
|
|
|
- <div class="page-title">请选择您的种植品种</div>
|
|
|
|
|
- <div class="page-subtitle">请确定您的果园设施以及内容</div>
|
|
|
|
|
|
|
+ <div class="page-title">请选择您的种植品种<span class="page-title-tip">(单选)</span></div>
|
|
|
|
|
+ <div class="page-subtitle">精细管理每一块地、每一个品种</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 品类 Tab + 品种选择,照常显示 -->
|
|
|
|
|
- <div class="category-tabs" v-if="categoryTabs.length">
|
|
|
|
|
- <div
|
|
|
|
|
- v-for="(tab, index) in categoryTabs"
|
|
|
|
|
- :key="tab.id"
|
|
|
|
|
- class="category-tab"
|
|
|
|
|
- :class="{
|
|
|
|
|
- active: activeCategoryId === tab.id,
|
|
|
|
|
- first: index % 3 === 0,
|
|
|
|
|
- last: index === categoryTabs.length - 1,
|
|
|
|
|
- }"
|
|
|
|
|
- @click="activeCategoryId = tab.id"
|
|
|
|
|
- >
|
|
|
|
|
- <span>{{ tab.name }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
|
|
|
<div class="variety-card" v-loading="varietyLoading">
|
|
<div class="variety-card" v-loading="varietyLoading">
|
|
|
|
|
+ <!-- 单品类标题 -->
|
|
|
|
|
+ <div class="category-title" v-if="currentCategory?.name">
|
|
|
|
|
+ <span class="category-title__line"></span>
|
|
|
|
|
+ <span class="category-title__diamond"></span>
|
|
|
|
|
+ <span class="category-title__text">品类 - {{ currentCategory.name }}</span>
|
|
|
|
|
+ <span class="category-title__diamond"></span>
|
|
|
|
|
+ <span class="category-title__line right-line"></span>
|
|
|
|
|
+ </div>
|
|
|
<el-input v-model="searchKeyword" class="search-bar" placeholder="请输入品种" @keyup.enter="handleSearch">
|
|
<el-input v-model="searchKeyword" class="search-bar" placeholder="请输入品种" @keyup.enter="handleSearch">
|
|
|
<template #prefix>
|
|
<template #prefix>
|
|
|
<el-icon class="search-icon">
|
|
<el-icon class="search-icon">
|
|
@@ -50,28 +42,37 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 默认表单卡:始终在已选卡片上方 -->
|
|
|
|
|
- <div class="form-card form-card--default">
|
|
|
|
|
|
|
+ <!-- 默认表单卡(单选,始终一张) -->
|
|
|
|
|
+ <div v-if="currentSelected" :key="currentSelected.uid" class="form-card"
|
|
|
|
|
+ :class="hasVariety ? 'selected-card' : 'form-card--default'">
|
|
|
<div class="form-card__header">
|
|
<div class="form-card__header">
|
|
|
<img class="title-icon" src="@/assets/img/home/label-icon.png" alt="" />
|
|
<img class="title-icon" src="@/assets/img/home/label-icon.png" alt="" />
|
|
|
- <el-select v-model="defaultForm.varietyId" class="variety-select" placeholder="选择品种"
|
|
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="currentSelected.id"
|
|
|
|
|
+ class="variety-select"
|
|
|
|
|
+ placeholder="选择品种"
|
|
|
popper-class="variety-select-popper"
|
|
popper-class="variety-select-popper"
|
|
|
- @change="handleDefaultVarietyChange">
|
|
|
|
|
|
|
+ @change="handleFormVarietyChange"
|
|
|
|
|
+ >
|
|
|
<el-option
|
|
<el-option
|
|
|
- v-for="item in currentVarieties"
|
|
|
|
|
- :key="item.id"
|
|
|
|
|
- :label="item.name"
|
|
|
|
|
- :value="item.id"
|
|
|
|
|
- :class="{ 'is-variety-selected': isSelected(item.id) }"
|
|
|
|
|
|
|
+ v-for="opt in currentVarieties"
|
|
|
|
|
+ :key="opt.id"
|
|
|
|
|
+ :label="opt.name"
|
|
|
|
|
+ :value="opt.id"
|
|
|
/>
|
|
/>
|
|
|
</el-select>
|
|
</el-select>
|
|
|
|
|
+ <span v-if="hasVariety" class="delete-btn" @click="clearVariety">删除</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="form-card__body form-card__body--locked" @click="tipSelectVariety">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="form-card__body"
|
|
|
|
|
+ :class="{ 'form-card__body--locked': !hasVariety }"
|
|
|
|
|
+ @click="onFormBodyClick"
|
|
|
|
|
+ >
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
<span class="form-label">当下物候期</span>
|
|
<span class="form-label">当下物候期</span>
|
|
|
<el-select
|
|
<el-select
|
|
|
- v-model="defaultForm.phenologyId"
|
|
|
|
|
|
|
+ v-model="currentSelected.phenologyId"
|
|
|
class="form-select"
|
|
class="form-select"
|
|
|
placeholder="选择物候期"
|
|
placeholder="选择物候期"
|
|
|
placement="bottom-end"
|
|
placement="bottom-end"
|
|
@@ -87,9 +88,11 @@
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
- <span class="form-label muted">{{ currentStartingPointQuestion }}</span>
|
|
|
|
|
|
|
+ <span class="form-label" :class="{ muted: !hasVariety }">
|
|
|
|
|
+ {{ currentStartingPointQuestion }}
|
|
|
|
|
+ </span>
|
|
|
<el-date-picker
|
|
<el-date-picker
|
|
|
- v-model="defaultForm.startTime"
|
|
|
|
|
|
|
+ v-model="currentSelected.startTime"
|
|
|
class="form-picker"
|
|
class="form-picker"
|
|
|
type="date"
|
|
type="date"
|
|
|
placeholder="请选择时间"
|
|
placeholder="请选择时间"
|
|
@@ -97,89 +100,28 @@
|
|
|
value-format="YYYY-MM-DD"
|
|
value-format="YYYY-MM-DD"
|
|
|
:clearable="false"
|
|
:clearable="false"
|
|
|
style="width: 130px"
|
|
style="width: 130px"
|
|
|
- readonly
|
|
|
|
|
|
|
+ :readonly="!hasVariety"
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
<span class="form-label">种植亩数</span>
|
|
<span class="form-label">种植亩数</span>
|
|
|
<el-input
|
|
<el-input
|
|
|
- v-model.number="defaultForm.area"
|
|
|
|
|
|
|
+ v-model="currentSelected.area"
|
|
|
class="form-input"
|
|
class="form-input"
|
|
|
placeholder="请输入亩数"
|
|
placeholder="请输入亩数"
|
|
|
type="number"
|
|
type="number"
|
|
|
|
|
+ :readonly="!hasVariety"
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="form-row location-row">
|
|
<div class="form-row location-row">
|
|
|
<span class="form-label">选择种植点位</span>
|
|
<span class="form-label">选择种植点位</span>
|
|
|
- <div class="map" ref="defaultMapRef"></div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 已选品种详情卡:只显示当前品类 -->
|
|
|
|
|
- <div v-for="item in visibleSelectedList" :key="item.uid" class="form-card selected-card">
|
|
|
|
|
- <div class="form-card__header">
|
|
|
|
|
- <img class="title-icon" src="@/assets/img/home/label-icon.png" alt="" />
|
|
|
|
|
- <el-select v-model="item.id" class="variety-select" placeholder="选择品种"
|
|
|
|
|
- popper-class="variety-select-popper"
|
|
|
|
|
- @change="(val) => handleSelectedVarietyChange(item.uid, val)">
|
|
|
|
|
- <el-option
|
|
|
|
|
- v-for="opt in getVarietiesByCategory(item.categoryId)"
|
|
|
|
|
- :key="opt.id"
|
|
|
|
|
- :label="opt.name"
|
|
|
|
|
- :value="opt.id"
|
|
|
|
|
- :class="{ 'is-variety-selected': isSelected(opt.id) }"
|
|
|
|
|
- />
|
|
|
|
|
- </el-select>
|
|
|
|
|
- <span class="delete-btn" @click="removeVariety(item.uid)">删除</span>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="form-card__body">
|
|
|
|
|
- <div class="form-row">
|
|
|
|
|
- <span class="form-label">当下物候期</span>
|
|
|
|
|
- <el-select
|
|
|
|
|
- v-model="item.phenologyId"
|
|
|
|
|
- class="form-select"
|
|
|
|
|
- placeholder="选择物候期"
|
|
|
|
|
- placement="bottom-end"
|
|
|
|
|
- popper-class="variety-select-popper"
|
|
|
|
|
- >
|
|
|
|
|
- <el-option
|
|
|
|
|
- v-for="opt in getPhenologyOptions(item.categoryId)"
|
|
|
|
|
- :key="opt.id"
|
|
|
|
|
- :label="opt.name"
|
|
|
|
|
- :value="opt.id"
|
|
|
|
|
- />
|
|
|
|
|
- </el-select>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="form-row">
|
|
|
|
|
- <span class="form-label">{{ getStartingPointQuestion(item.categoryId) }}</span>
|
|
|
|
|
- <el-date-picker
|
|
|
|
|
- v-model="item.startTime"
|
|
|
|
|
- class="form-picker"
|
|
|
|
|
- type="date"
|
|
|
|
|
- placeholder="请选择时间"
|
|
|
|
|
- format="YYYY-MM-DD"
|
|
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
|
|
- :clearable="false"
|
|
|
|
|
- style="width: 130px"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="form-row">
|
|
|
|
|
- <span class="form-label">种植亩数</span>
|
|
|
|
|
- <el-input v-model="item.area" class="form-input" placeholder="请输入亩数" type="number" />
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="form-row location-row">
|
|
|
|
|
- <span class="form-label">选择种植点位</span>
|
|
|
|
|
<div
|
|
<div
|
|
|
- class="map map--clickable"
|
|
|
|
|
- :ref="(el) => setItemMapRef(item.uid, el)"
|
|
|
|
|
- @click="goSelectItemLocation(item)"
|
|
|
|
|
|
|
+ class="map"
|
|
|
|
|
+ :class="{ 'map--clickable': hasVariety }"
|
|
|
|
|
+ :ref="(el) => setItemMapRef(currentSelected.uid, el)"
|
|
|
|
|
+ @click="goSelectItemLocation(currentSelected)"
|
|
|
></div>
|
|
></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -194,7 +136,7 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { computed, nextTick, onActivated, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue";
|
|
|
|
|
|
|
+import { computed, nextTick, onActivated, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
|
import { ElMessage } from "element-plus";
|
|
import { ElMessage } from "element-plus";
|
|
|
import { Search } from "@element-plus/icons-vue";
|
|
import { Search } from "@element-plus/icons-vue";
|
|
|
import { useRouter } from "vue-router";
|
|
import { useRouter } from "vue-router";
|
|
@@ -205,7 +147,7 @@ const emit = defineEmits(["prev", "next"]);
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const store = useStore();
|
|
const store = useStore();
|
|
|
|
|
|
|
|
-const DEFAULT_VISIBLE_COUNT = 8;
|
|
|
|
|
|
|
+const DEFAULT_VISIBLE_COUNT = 12;
|
|
|
const DEFAULT_POINT = "POINT(113.6142086995688 23.585836479509055)";
|
|
const DEFAULT_POINT = "POINT(113.6142086995688 23.585836479509055)";
|
|
|
const LOCATION_KEY = "ENTRY_RESIDENT_LOCATION";
|
|
const LOCATION_KEY = "ENTRY_RESIDENT_LOCATION";
|
|
|
const EDIT_UID_KEY = "ENTRY_VARIETY_EDIT_UID";
|
|
const EDIT_UID_KEY = "ENTRY_VARIETY_EDIT_UID";
|
|
@@ -214,8 +156,6 @@ const CATEGORY_SESSION_KEY = "ENTRY_SELECTED_CATEGORY";
|
|
|
const MAP_PADDING = [6, 6, 6, 6];
|
|
const MAP_PADDING = [6, 6, 6, 6];
|
|
|
let selectedUid = 0;
|
|
let selectedUid = 0;
|
|
|
|
|
|
|
|
-const defaultMapRef = ref(null);
|
|
|
|
|
-let defaultPreviewMap = null;
|
|
|
|
|
const itemPreviewMaps = new Map();
|
|
const itemPreviewMaps = new Map();
|
|
|
|
|
|
|
|
function getDefaultPoint() {
|
|
function getDefaultPoint() {
|
|
@@ -281,15 +221,6 @@ function setItemMapRef(uid, el) {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function initDefaultMap() {
|
|
|
|
|
- if (!defaultMapRef.value) return;
|
|
|
|
|
- if (defaultPreviewMap) {
|
|
|
|
|
- nextTick(() => defaultPreviewMap.kmap?.map?.updateSize?.());
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- defaultPreviewMap = createPreviewMap(defaultMapRef.value, getDefaultPoint(), false);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
function syncItemLocationFromSession() {
|
|
function syncItemLocationFromSession() {
|
|
|
const uid = sessionStorage.getItem(EDIT_UID_KEY);
|
|
const uid = sessionStorage.getItem(EDIT_UID_KEY);
|
|
|
if (!uid) return;
|
|
if (!uid) return;
|
|
@@ -334,8 +265,9 @@ function restoreSelectedListDraft() {
|
|
|
if (typeof draft?.selectedUid === "number") {
|
|
if (typeof draft?.selectedUid === "number") {
|
|
|
selectedUid = draft.selectedUid;
|
|
selectedUid = draft.selectedUid;
|
|
|
}
|
|
}
|
|
|
- if (Array.isArray(draft?.list)) {
|
|
|
|
|
- selectedList.value = draft.list;
|
|
|
|
|
|
|
+ if (Array.isArray(draft?.list) && draft.list.length) {
|
|
|
|
|
+ // 单选:只保留一项
|
|
|
|
|
+ selectedList.value = draft.list.slice(0, 1);
|
|
|
}
|
|
}
|
|
|
} catch {
|
|
} catch {
|
|
|
// ignore
|
|
// ignore
|
|
@@ -343,6 +275,10 @@ function restoreSelectedListDraft() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const goSelectItemLocation = (item) => {
|
|
const goSelectItemLocation = (item) => {
|
|
|
|
|
+ if (!item?.id) {
|
|
|
|
|
+ ElMessage.warning("请选择品种");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
sessionStorage.setItem(EDIT_UID_KEY, item.uid);
|
|
sessionStorage.setItem(EDIT_UID_KEY, item.uid);
|
|
|
sessionStorage.setItem("ENTRY_INFORMATION_STEP", "3");
|
|
sessionStorage.setItem("ENTRY_INFORMATION_STEP", "3");
|
|
|
saveSelectedListDraft();
|
|
saveSelectedListDraft();
|
|
@@ -358,8 +294,8 @@ const goSelectItemLocation = (item) => {
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
initCategoryTabsFromSession();
|
|
initCategoryTabsFromSession();
|
|
|
restoreSelectedListDraft();
|
|
restoreSelectedListDraft();
|
|
|
|
|
+ ensureDefaultForm();
|
|
|
syncItemLocationFromSession();
|
|
syncItemLocationFromSession();
|
|
|
- nextTick(() => initDefaultMap());
|
|
|
|
|
await Promise.all(
|
|
await Promise.all(
|
|
|
categoryTabs.value.map((tab) => fetchVarietiesByCrop(tab.id))
|
|
categoryTabs.value.map((tab) => fetchVarietiesByCrop(tab.id))
|
|
|
);
|
|
);
|
|
@@ -368,9 +304,9 @@ onMounted(async () => {
|
|
|
onActivated(async () => {
|
|
onActivated(async () => {
|
|
|
initCategoryTabsFromSession();
|
|
initCategoryTabsFromSession();
|
|
|
restoreSelectedListDraft();
|
|
restoreSelectedListDraft();
|
|
|
|
|
+ ensureDefaultForm();
|
|
|
syncItemLocationFromSession();
|
|
syncItemLocationFromSession();
|
|
|
nextTick(() => {
|
|
nextTick(() => {
|
|
|
- initDefaultMap();
|
|
|
|
|
itemPreviewMaps.forEach((map) => map.kmap?.map?.updateSize?.());
|
|
itemPreviewMaps.forEach((map) => map.kmap?.map?.updateSize?.());
|
|
|
});
|
|
});
|
|
|
await Promise.all(
|
|
await Promise.all(
|
|
@@ -379,8 +315,6 @@ onActivated(async () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
onBeforeUnmount(() => {
|
|
|
- destroyPreviewMap(defaultPreviewMap);
|
|
|
|
|
- defaultPreviewMap = null;
|
|
|
|
|
itemPreviewMaps.forEach((map) => destroyPreviewMap(map));
|
|
itemPreviewMaps.forEach((map) => destroyPreviewMap(map));
|
|
|
itemPreviewMaps.clear();
|
|
itemPreviewMaps.clear();
|
|
|
});
|
|
});
|
|
@@ -452,13 +386,6 @@ const searchKeyword = ref("");
|
|
|
const appliedKeyword = ref("");
|
|
const appliedKeyword = ref("");
|
|
|
const gridExpanded = ref(false);
|
|
const gridExpanded = ref(false);
|
|
|
const selectedList = ref([]);
|
|
const selectedList = ref([]);
|
|
|
-const defaultForm = reactive({
|
|
|
|
|
- varietyId: "",
|
|
|
|
|
- varietyName: "",
|
|
|
|
|
- phenologyId: "",
|
|
|
|
|
- startTime: "",
|
|
|
|
|
- area: "",
|
|
|
|
|
-});
|
|
|
|
|
|
|
|
|
|
const fetchVarietiesByCrop = async (cropId, force = false) => {
|
|
const fetchVarietiesByCrop = async (cropId, force = false) => {
|
|
|
if (cropId == null || cropId === "") return;
|
|
if (cropId == null || cropId === "") return;
|
|
@@ -526,12 +453,6 @@ const getStartingPointQuestion = (categoryId) => {
|
|
|
return tab?.startingPointQuestion || "起种点问题";
|
|
return tab?.startingPointQuestion || "起种点问题";
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const currentPhenologyOptions = computed(() => getPhenologyOptions(activeCategoryId.value));
|
|
|
|
|
-
|
|
|
|
|
-const currentStartingPointQuestion = computed(() =>
|
|
|
|
|
- getStartingPointQuestion(activeCategoryId.value)
|
|
|
|
|
-);
|
|
|
|
|
-
|
|
|
|
|
const currentVarieties = computed(() => currentCategory.value?.varieties || []);
|
|
const currentVarieties = computed(() => currentCategory.value?.varieties || []);
|
|
|
|
|
|
|
|
const getVarietiesByCategory = (categoryId) => {
|
|
const getVarietiesByCategory = (categoryId) => {
|
|
@@ -551,101 +472,112 @@ const visibleVarieties = computed(() => {
|
|
|
return filteredVarieties.value.slice(0, DEFAULT_VISIBLE_COUNT);
|
|
return filteredVarieties.value.slice(0, DEFAULT_VISIBLE_COUNT);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const visibleSelectedList = computed(() =>
|
|
|
|
|
- selectedList.value.filter(
|
|
|
|
|
- (item) => String(item.categoryId) === String(activeCategoryId.value)
|
|
|
|
|
- )
|
|
|
|
|
|
|
+const createEmptyForm = (category) => ({
|
|
|
|
|
+ uid: `sel-${++selectedUid}`,
|
|
|
|
|
+ id: "",
|
|
|
|
|
+ name: "",
|
|
|
|
|
+ categoryId: category?.id ?? null,
|
|
|
|
|
+ categoryName: category?.name ?? "",
|
|
|
|
|
+ phenologyId: "",
|
|
|
|
|
+ startTime: "",
|
|
|
|
|
+ area: "",
|
|
|
|
|
+ location: "",
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+/** 始终保留一张可编辑的默认表单卡 */
|
|
|
|
|
+const ensureDefaultForm = () => {
|
|
|
|
|
+ const category = currentCategory.value;
|
|
|
|
|
+ if (!category) {
|
|
|
|
|
+ selectedList.value = [];
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!selectedList.value.length) {
|
|
|
|
|
+ selectedList.value = [createEmptyForm(category)];
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const item = selectedList.value[0];
|
|
|
|
|
+ item.categoryId = category.id;
|
|
|
|
|
+ item.categoryName = category.name;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/** 单选当前表单 */
|
|
|
|
|
+const currentSelected = computed(() => selectedList.value[0] || null);
|
|
|
|
|
+const hasVariety = computed(() => !!currentSelected.value?.id);
|
|
|
|
|
+const currentPhenologyOptions = computed(() =>
|
|
|
|
|
+ getPhenologyOptions(currentSelected.value?.categoryId || activeCategoryId.value)
|
|
|
|
|
+);
|
|
|
|
|
+const currentStartingPointQuestion = computed(() =>
|
|
|
|
|
+ getStartingPointQuestion(currentSelected.value?.categoryId || activeCategoryId.value)
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
watch(activeCategoryId, (id) => {
|
|
watch(activeCategoryId, (id) => {
|
|
|
searchKeyword.value = "";
|
|
searchKeyword.value = "";
|
|
|
appliedKeyword.value = "";
|
|
appliedKeyword.value = "";
|
|
|
gridExpanded.value = false;
|
|
gridExpanded.value = false;
|
|
|
- resetDefaultForm();
|
|
|
|
|
|
|
+ ensureDefaultForm();
|
|
|
if (id != null) {
|
|
if (id != null) {
|
|
|
fetchVarietiesByCrop(id);
|
|
fetchVarietiesByCrop(id);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const isSelected = (id) =>
|
|
const isSelected = (id) =>
|
|
|
- selectedList.value.some((item) => String(item.id) === String(id));
|
|
|
|
|
|
|
+ !!id && selectedList.value.some((item) => String(item.id) === String(id));
|
|
|
|
|
|
|
|
const handleSearch = () => {
|
|
const handleSearch = () => {
|
|
|
appliedKeyword.value = searchKeyword.value;
|
|
appliedKeyword.value = searchKeyword.value;
|
|
|
gridExpanded.value = false;
|
|
gridExpanded.value = false;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const createSelectedItem = (variety, category) => ({
|
|
|
|
|
- uid: `sel-${++selectedUid}`,
|
|
|
|
|
- id: variety.id,
|
|
|
|
|
- name: variety.name,
|
|
|
|
|
- categoryId: category.id,
|
|
|
|
|
- categoryName: category.name,
|
|
|
|
|
- phenologyId: "",
|
|
|
|
|
- startTime: "",
|
|
|
|
|
- area: "",
|
|
|
|
|
- location: "",
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-const resetDefaultForm = () => {
|
|
|
|
|
- defaultForm.varietyId = "";
|
|
|
|
|
- defaultForm.varietyName = "";
|
|
|
|
|
- defaultForm.phenologyId = "";
|
|
|
|
|
- defaultForm.startTime = "";
|
|
|
|
|
- defaultForm.area = "";
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const tipSelectVariety = () => {
|
|
|
|
|
- ElMessage.warning("请选择品种");
|
|
|
|
|
|
|
+const applyVarietyToForm = (variety) => {
|
|
|
|
|
+ ensureDefaultForm();
|
|
|
|
|
+ const item = selectedList.value[0];
|
|
|
|
|
+ if (!item || !variety || !currentCategory.value) return;
|
|
|
|
|
+ item.id = variety.id;
|
|
|
|
|
+ item.name = variety.name;
|
|
|
|
|
+ item.categoryId = currentCategory.value.id;
|
|
|
|
|
+ item.categoryName = currentCategory.value.name;
|
|
|
|
|
+ item.phenologyId = "";
|
|
|
|
|
+ saveSelectedListDraft();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-/** 顶部「选择品种」:选中后新增下方卡片,顶部表单重置为空 */
|
|
|
|
|
-const handleDefaultVarietyChange = (varietyId) => {
|
|
|
|
|
- if (!varietyId) return;
|
|
|
|
|
- const found = currentVarieties.value.find((item) => String(item.id) === String(varietyId));
|
|
|
|
|
- if (!found) {
|
|
|
|
|
- resetDefaultForm();
|
|
|
|
|
|
|
+const handleFormVarietyChange = (varietyId) => {
|
|
|
|
|
+ if (!varietyId) {
|
|
|
|
|
+ clearVariety();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (!isSelected(found.id)) {
|
|
|
|
|
- selectedList.value.unshift(createSelectedItem(found, currentCategory.value));
|
|
|
|
|
- saveSelectedListDraft();
|
|
|
|
|
- }
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- resetDefaultForm();
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const found = currentVarieties.value.find((item) => String(item.id) === String(varietyId));
|
|
|
|
|
+ if (!found) return;
|
|
|
|
|
+ applyVarietyToForm(found);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const handleSelectedVarietyChange = (uid, varietyId) => {
|
|
|
|
|
- const item = selectedList.value.find((i) => i.uid === uid);
|
|
|
|
|
|
|
+const clearVariety = () => {
|
|
|
|
|
+ ensureDefaultForm();
|
|
|
|
|
+ const item = selectedList.value[0];
|
|
|
if (!item) return;
|
|
if (!item) return;
|
|
|
- const found = getVarietiesByCategory(item.categoryId).find(
|
|
|
|
|
- (opt) => String(opt.id) === String(varietyId)
|
|
|
|
|
- );
|
|
|
|
|
- if (!found) return;
|
|
|
|
|
- item.id = found.id;
|
|
|
|
|
- item.name = found.name;
|
|
|
|
|
|
|
+ item.id = "";
|
|
|
|
|
+ item.name = "";
|
|
|
item.phenologyId = "";
|
|
item.phenologyId = "";
|
|
|
|
|
+ item.startTime = "";
|
|
|
|
|
+ item.area = "";
|
|
|
|
|
+ item.location = "";
|
|
|
|
|
+ nextTick(() => updateItemMap(item.uid, getDefaultPoint(), false));
|
|
|
saveSelectedListDraft();
|
|
saveSelectedListDraft();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const toggleVariety = (variety) => {
|
|
|
|
|
- const index = selectedList.value.findIndex((item) => String(item.id) === String(variety.id));
|
|
|
|
|
- if (index > -1) {
|
|
|
|
|
- selectedList.value.splice(index, 1);
|
|
|
|
|
- saveSelectedListDraft();
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+const onFormBodyClick = () => {
|
|
|
|
|
+ if (!hasVariety.value) {
|
|
|
|
|
+ ElMessage.warning("请选择品种");
|
|
|
}
|
|
}
|
|
|
- selectedList.value.unshift(createSelectedItem(variety, currentCategory.value));
|
|
|
|
|
- saveSelectedListDraft();
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const removeVariety = (uid) => {
|
|
|
|
|
- const index = selectedList.value.findIndex((item) => item.uid === uid);
|
|
|
|
|
- if (index > -1) {
|
|
|
|
|
- selectedList.value.splice(index, 1);
|
|
|
|
|
- saveSelectedListDraft();
|
|
|
|
|
|
|
+/** 单选:点新品种写入当前表单;再点已选则清空品种 */
|
|
|
|
|
+const toggleVariety = (variety) => {
|
|
|
|
|
+ const current = selectedList.value[0];
|
|
|
|
|
+ if (current && String(current.id) === String(variety.id)) {
|
|
|
|
|
+ clearVariety();
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+ applyVarietyToForm(variety);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handlePrev = () => {
|
|
const handlePrev = () => {
|
|
@@ -674,37 +606,26 @@ const validateSubmitData = () => {
|
|
|
ElMessage.warning("请先选择种植品类");
|
|
ElMessage.warning("请先选择种植品类");
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
- if (!selectedList.value.length) {
|
|
|
|
|
- ElMessage.warning("请至少选择一个品种");
|
|
|
|
|
|
|
+ const item = selectedList.value[0];
|
|
|
|
|
+ if (!item?.id) {
|
|
|
|
|
+ ElMessage.warning("请选择一个品种");
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
- for (const tab of categoryTabs.value) {
|
|
|
|
|
- const hasVariety = selectedList.value.some(
|
|
|
|
|
- (item) => String(item.categoryId) === String(tab.id)
|
|
|
|
|
- );
|
|
|
|
|
- if (!hasVariety) {
|
|
|
|
|
- ElMessage.warning(`请为「${tab.name}」选择品种并填写信息`);
|
|
|
|
|
- activeCategoryId.value = tab.id;
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!item.phenologyId) {
|
|
|
|
|
+ ElMessage.warning(`请选择「${item.name}」的当下物候期`);
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
- for (const item of selectedList.value) {
|
|
|
|
|
- if (!item.phenologyId) {
|
|
|
|
|
- ElMessage.warning(`请选择「${item.name}」的当下物候期`);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (!item.startTime) {
|
|
|
|
|
- ElMessage.warning(`请填写「${item.name}」的起种点时间`);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (item.area === "" || item.area == null || Number(item.area) <= 0) {
|
|
|
|
|
- ElMessage.warning(`请填写「${item.name}」的种植亩数`);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- if (!item.location) {
|
|
|
|
|
- ElMessage.warning(`请选择「${item.name}」的种植点位`);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!item.startTime) {
|
|
|
|
|
+ ElMessage.warning(`请填写「${item.name}」的起种点时间`);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (item.area === "" || item.area == null || Number(item.area) <= 0) {
|
|
|
|
|
+ ElMessage.warning(`请填写「${item.name}」的种植亩数`);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!item.location) {
|
|
|
|
|
+ ElMessage.warning(`请选择「${item.name}」的种植点位`);
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
const baForm = getBaForm();
|
|
const baForm = getBaForm();
|
|
|
if (!baForm?.name || !baForm?.phone) {
|
|
if (!baForm?.name || !baForm?.phone) {
|
|
@@ -724,10 +645,11 @@ const handleConfirm = () => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (!validateSubmitData()) return;
|
|
if (!validateSubmitData()) return;
|
|
|
- selectedList.value.forEach((item) => {
|
|
|
|
|
- const options = getPhenologyOptions(item.categoryId);
|
|
|
|
|
- const found = options.find((opt) => String(opt.id) === String(item.phenologyId));
|
|
|
|
|
- item.phenophase = found?.name || String(item.phenologyId || "");
|
|
|
|
|
|
|
+ selectedList.value.forEach((row) => {
|
|
|
|
|
+ if (!row.id) return;
|
|
|
|
|
+ const options = getPhenologyOptions(row.categoryId);
|
|
|
|
|
+ const found = options.find((opt) => String(opt.id) === String(row.phenologyId));
|
|
|
|
|
+ row.phenophase = found?.name || String(row.phenologyId || "");
|
|
|
});
|
|
});
|
|
|
saveSelectedListDraft();
|
|
saveSelectedListDraft();
|
|
|
emit("next");
|
|
emit("next");
|
|
@@ -756,6 +678,9 @@ const handleConfirm = () => {
|
|
|
font-size: 26px;
|
|
font-size: 26px;
|
|
|
color: #005599;
|
|
color: #005599;
|
|
|
font-family: "PangMenZhengDao";
|
|
font-family: "PangMenZhengDao";
|
|
|
|
|
+ .page-title-tip {
|
|
|
|
|
+ font-size: 20px;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.page-subtitle {
|
|
.page-subtitle {
|
|
@@ -763,52 +688,40 @@ const handleConfirm = () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .category-tabs {
|
|
|
|
|
|
|
+ .category-title {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- row-gap: 8px;
|
|
|
|
|
- margin-bottom: 10px;
|
|
|
|
|
-
|
|
|
|
|
- .category-tab {
|
|
|
|
|
- --arrow: 20px;
|
|
|
|
|
- flex: 0 0 calc((100% + 16px) / 3);
|
|
|
|
|
- height: 30px;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- color: #4e5969;
|
|
|
|
|
- background: #e8f3ff;
|
|
|
|
|
- cursor: default;
|
|
|
|
|
- pointer-events: none;
|
|
|
|
|
- clip-path: polygon(0 0,
|
|
|
|
|
- calc(100% - var(--arrow)) 0,
|
|
|
|
|
- 100% 50%,
|
|
|
|
|
- calc(100% - var(--arrow)) 100%,
|
|
|
|
|
- 0 100%,
|
|
|
|
|
- var(--arrow) 50%);
|
|
|
|
|
- margin-left: -8px;
|
|
|
|
|
-
|
|
|
|
|
- &.first {
|
|
|
|
|
- margin-left: 0;
|
|
|
|
|
- clip-path: polygon(0 0,
|
|
|
|
|
- calc(100% - var(--arrow)) 0,
|
|
|
|
|
- 100% 50%,
|
|
|
|
|
- calc(100% - var(--arrow)) 100%,
|
|
|
|
|
- 0 100%);
|
|
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ gap: 1px;
|
|
|
|
|
+ height: 24px;
|
|
|
|
|
+ margin-bottom: 9px;
|
|
|
|
|
+ padding: 0 6px;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+
|
|
|
|
|
+ &__line {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ height: 1px;
|
|
|
|
|
+ background: linear-gradient(90deg, rgba(118, 118, 118, 0) 0%, rgba(118, 118, 118, 0.4) 100%);
|
|
|
|
|
+ &.right-line {
|
|
|
|
|
+ background: linear-gradient(270deg, rgba(118, 118, 118, 0) 0%, rgba(118, 118, 118, 0.4) 100%);
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- &.last {
|
|
|
|
|
- clip-path: polygon(0 0,
|
|
|
|
|
- 100% 0,
|
|
|
|
|
- 100% 100%,
|
|
|
|
|
- 0 100%,
|
|
|
|
|
- var(--arrow) 50%);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ &__diamond {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ width: 6px;
|
|
|
|
|
+ height: 6px;
|
|
|
|
|
+ background: rgba(61, 61, 61, 0.2);
|
|
|
|
|
+ transform: rotate(45deg);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- &.active {
|
|
|
|
|
- color: #fff;
|
|
|
|
|
- background: #2199f8;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ &__text {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ padding: 0 10px;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #3D3D3D;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -950,11 +863,11 @@ const handleConfirm = () => {
|
|
|
&--default {
|
|
&--default {
|
|
|
.form-card__header {
|
|
.form-card__header {
|
|
|
.variety-select {
|
|
.variety-select {
|
|
|
-
|
|
|
|
|
:deep(.el-select__selected-item),
|
|
:deep(.el-select__selected-item),
|
|
|
:deep(.el-select__placeholder) {
|
|
:deep(.el-select__placeholder) {
|
|
|
- color: #1D2129;
|
|
|
|
|
|
|
+ color: #1d2129;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
:deep(.el-select__placeholder.is-transparent) {
|
|
:deep(.el-select__placeholder.is-transparent) {
|
|
|
color: rgba(34, 34, 34, 0.3);
|
|
color: rgba(34, 34, 34, 0.3);
|
|
|
}
|
|
}
|