huangxw vor 4 Tagen
Ursprung
Commit
1561c36edc
2 geänderte Dateien mit 139 neuen und 60 gelöschten Zeilen
  1. 97 49
      src/tools/select-cultivation-location/index.vue
  2. 42 11
      src/tools/select-layers-amount/index.vue

+ 97 - 49
src/tools/select-cultivation-location/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <z-paging ref="paging" bgColor="#f7f7f7" :loading-more-enabled="false" bottom-bg-color="#fff" paging-class="paging-btm-shadow" hide-no-more-inside :show-loading-more-no-more-view="false" safe-area-inset-bottom v-model="list" @query="query" :to-bottom-loading-more-enabled="false">
+    <z-paging ref="paging" bgColor="#f7f7f7" :auto="false" :loading-more-enabled="false" bottom-bg-color="#fff" paging-class="paging-btm-shadow" hide-no-more-inside :show-loading-more-no-more-view="false" safe-area-inset-bottom v-model="list" @query="query" :to-bottom-loading-more-enabled="false">
         <template #top>
             <ut-navbar leftText="请选择放置的具体位置" :fixed="false" :breadcrumb="false"></ut-navbar>
         </template>
@@ -42,6 +42,11 @@
 </template>
 <script setup lang="ts">
 import { useClientRequest } from '@/utils/request';
+type CheckedPosition = {
+    x: number;
+    y: number;
+};
+
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const list = ref<any[]>([]);
 const form = ref({ baseId: 9 });
@@ -90,13 +95,39 @@ const selectedCount = computed(() => {
         return total + (item.checkedList ? item.checkedList.length : 0);
     }, 0);
 });
+const normalizeCheckedList = (checkedList: any[]): CheckedPosition[] => {
+    if (!Array.isArray(checkedList)) {
+        return [];
+    }
+
+    const result = new Map<string, CheckedPosition>();
+    checkedList.forEach((item) => {
+        if (item && typeof item === 'object') {
+            const x = Number(item.x);
+            const y = Number(item.y);
+            if (Number.isFinite(x) && Number.isFinite(y) && x > 0 && y > 0) {
+                result.set(`${x}-${y}`, { x, y });
+            }
+            return;
+        }
+
+        if (typeof item === 'string') {
+            const [x, y] = item.split('-').map(Number);
+            if (Number.isFinite(x) && Number.isFinite(y) && x > 0 && y > 0) {
+                result.set(`${x}-${y}`, { x, y });
+            }
+        }
+    });
+
+    return Array.from(result.values());
+};
 const buildCheckedList = (item: any) => {
-    const result: string[] = [];
+    const result: CheckedPosition[] = [];
     const layers = Number(item?.layers || 0);
     const capacityAmount = Number(item?.capacityAmount || 0);
     for (let layer = 1; layer <= layers; layer++) {
         for (let capacity = 1; capacity <= capacityAmount; capacity++) {
-            result.push(`${layer}-${capacity}`);
+            result.push({ x: layer, y: capacity });
         }
     }
     return result;
@@ -119,7 +150,7 @@ const goSelectLayersAmount = (item: any) => {
         // 在这里处理接收到的数据,例如更新列表或发送请求等
         if (data && data.id) {
             const landItem = list.value.find((land: any) => land.id === data.id);
-            const checkedList = Array.isArray(data.list) ? data.list : [];
+            const checkedList = normalizeCheckedList(data.list);
             checkeds.value[data.id] = {
                 checkedAll: checkedList.length === Number(landItem?.layers || 0) * Number(landItem?.capacityAmount || 0),
                 id: data.id,
@@ -140,59 +171,55 @@ const goSelectLayersAmount = (item: any) => {
         },
     });
 };
-const stringifyCheckedList = (list: any[], capacityAmount: number) => {
-    if (!list || list.length === 0) {
+const stringifyCheckedList = (list: CheckedPosition[], perLayerCount: number) => {
+    if (!Array.isArray(list) || !list.length) {
         return '';
     }
-    type ParsedItem = {
-        layer: number;
-        capacity: number;
-        value: string;
-    };
-    const parsed = list
-        .map((value) => {
-            const [layerText, capacityText] = String(value).split('-');
-            const layer = Number(layerText);
-            const capacity = Number(capacityText);
-            if (!layer || !capacity) {
-                return null;
-            }
-            return {
-                layer,
-                capacity,
-                value: `${layer}-${capacity}`,
-            };
-        })
-        .filter((item): item is ParsedItem => item !== null)
-        .sort((left, right) => {
-            if (left.layer !== right.layer) {
-                return left.layer - right.layer;
-            }
-            return left.capacity - right.capacity;
-        });
+    const capacity = Number(perLayerCount || 0);
+    if (!capacity) {
+        return '';
+    }
+
+    const serialMap = new Map<number, CheckedPosition>();
+    list.forEach((item) => {
+        const serial = (item.x - 1) * capacity + item.y;
+        if (serial > 0 && !serialMap.has(serial)) {
+            serialMap.set(serial, item);
+        }
+    });
 
-    if (!parsed.length) {
+    const serials = Array.from(serialMap.keys()).sort((a, b) => a - b);
+    if (!serials.length) {
         return '';
     }
 
     const segments: string[] = [];
-    let startIndex = 0;
+    let startSerial = serials[0];
+    let endSerial = serials[0];
+
+    const pushSegment = (start: number, end: number) => {
+        const startItem = serialMap.get(start)!;
+        const endItem = serialMap.get(end)!;
+        if (start === end) {
+            segments.push(`${startItem.x}-${startItem.y}`);
+        } else {
+            segments.push(`${startItem.x}-${startItem.y}至${endItem.x}-${endItem.y}`);
+        }
+    };
 
-    for (let index = 1; index <= parsed.length; index++) {
-        const previous = parsed[index - 1]!;
-        const current = parsed[index];
-        const isSameLayerContinuous = !!current && current.layer === previous.layer && current.capacity === previous.capacity + 1;
-        const isCrossLayerContinuous = !!current && current.layer === previous.layer + 1 && previous.capacity === capacityAmount && current.capacity === 1;
-        const isContinuous = isSameLayerContinuous || isCrossLayerContinuous;
-        if (isContinuous) {
-            continue;
+    for (let index = 1; index < serials.length; index++) {
+        const current = serials[index];
+        if (current === endSerial + 1) {
+            endSerial = current;
+        } else {
+            pushSegment(startSerial, endSerial);
+            startSerial = current;
+            endSerial = current;
         }
-        const start = parsed[startIndex]!;
-        segments.push(start.value === previous.value ? start.value : `${start.value}至${previous.value}`);
-        startIndex = index;
     }
+    pushSegment(startSerial, endSerial);
 
-    return `${segments.join(',')}共${parsed.length}个位置`;
+    return `${segments.join(',')}共${serials.length}个位置`;
 };
 const clickExpandedIndex = (id: string) => {
     if (expandedIndex.value === id) {
@@ -209,15 +236,36 @@ const handleConfirmSelection = () => {
         checkedList: item.checkedList,
     }));
     console.log('确认选择的数据:', selectedData);
-    
+
     // 去掉没有选择任何位置的项
     const filteredSelectedData = selectedData.filter((item: any) => item.checkedList && item.checkedList.length > 0);
     // 发送事件给父组件或其他页面
     uni.$emit('cultivationLocationSelected', filteredSelectedData);
+    uni.navigateBack({
+        delta: 1,
+    });
 };
-onMounted(() => {
-
+onLoad(() => {
+    try {
+        const instanceproxy: any = getCurrentInstance()?.proxy;
+        const eventChannel = instanceproxy?.getOpenerEventChannel();
+        eventChannel?.on('selectCultivationLocation', (data: any[]) => {
+            if (Array.isArray(data)) {
+                data.forEach((item) => {
+                    checkeds.value[item.id] = {
+                        id: item.id,
+                        landName: item.landName,
+                        checkedList: normalizeCheckedList(item.checkedList),
+                    };
+                });
+            }
+            onRefresh();
+        });
+    } catch (error) {
+        console.warn('selectCultivationLocation 事件通道不可用,使用空选中列表', error);
+    }
 });
+onMounted(() => {});
 //卸载监听
 onUnload(() => {
     uni.$off('cultivationLocationSelected');

+ 42 - 11
src/tools/select-layers-amount/index.vue

@@ -28,9 +28,14 @@
     </view>
 </template>
 <script setup lang="ts">
+type CheckedPosition = {
+    x: number;
+    y: number;
+};
+
 type LayerItem = {
-    layer: number;
-    capacity: number;
+    x: number;
+    y: number;
     value: string;
     sort: number;
     rowIndex: number;
@@ -79,8 +84,8 @@ const generateLayersAmount = (layers: number, capacityAmount: number) => {
         for (let j = 1; j <= capacityAmount; j++) {
             const index = result.length;
             result.push({
-                layer: i,
-                capacity: j,
+                x: i,
+                y: j,
                 value: `${i}-${j}`,
                 sort: (i - 1) * capacityAmount + j,
                 rowIndex: Math.floor(index / CARDS_PER_ROW),
@@ -159,9 +164,36 @@ const applyCheckedIndexes = (indexesToUpdate: number[], checked: boolean) => {
     });
 };
 
-// 将父页面传入的已选 value 列表映射成当前页面的索引选中态,用于进入页面时回显。
-const initCheckedStates = (checkedList: string[]) => {
-    const selectedSet = new Set(checkedList);
+const normalizeCheckedList = (checkedList: any[]): CheckedPosition[] => {
+    if (!Array.isArray(checkedList)) {
+        return [];
+    }
+
+    const result = new Map<string, CheckedPosition>();
+    checkedList.forEach((item) => {
+        if (item && typeof item === 'object') {
+            const x = Number(item.x);
+            const y = Number(item.y);
+            if (Number.isFinite(x) && Number.isFinite(y) && x > 0 && y > 0) {
+                result.set(`${x}-${y}`, { x, y });
+            }
+            return;
+        }
+
+        if (typeof item === 'string') {
+            const [x, y] = item.split('-').map(Number);
+            if (Number.isFinite(x) && Number.isFinite(y) && x > 0 && y > 0) {
+                result.set(`${x}-${y}`, { x, y });
+            }
+        }
+    });
+
+    return Array.from(result.values());
+};
+
+// 将父页面传入的已选位置列表映射成当前页面的索引选中态,用于进入页面时回显。
+const initCheckedStates = (checkedList: CheckedPosition[]) => {
+    const selectedSet = new Set(checkedList.map((item) => `${item.x}-${item.y}`));
     checkedStates.value = layersAmount.value.map((item) => selectedSet.has(item.value));
 };
 
@@ -477,11 +509,10 @@ const handleScroll = (event: any) => {
 
 // 确认选择时统一返回固定结构,后续外部页面接收时不需要再重新组装。
 const handleConfirmSelection = () => {
-    const { layers, capacityAmount } = opts.value;
     const payload = {
         id: opts.value?.id || '',
         checkedAll: allLayers.value,
-        list: layersAmount.value.filter((_, index) => checkedStates.value[index]).map((item) => item.value),
+        list: layersAmount.value.filter((_, index) => checkedStates.value[index]).map((item) => ({ x: item.x, y: item.y })),
     };
     console.log(payload);
 
@@ -497,9 +528,9 @@ onLoad((options) => {
             const { layers, capacityAmount, id } = data;
             opts.value = { layers, capacityAmount, id };
             layersAmount.value = generateLayersAmount(Number(layers), Number(capacityAmount));
-            let selectedValues: string[] = [];
+            let selectedValues: CheckedPosition[] = [];
             if (data?.id === id && Array.isArray(data?.checkedList)) {
-                selectedValues = data.checkedList;
+                selectedValues = normalizeCheckedList(data.checkedList);
                 initCheckedStates(selectedValues);
                 nextTick(() => {
                     updateScrollAreaRect();