lisy пре 1 недеља
родитељ
комит
e50700a15f

+ 45 - 40
src/components/ut-suspension/ut-suspension.vue

@@ -1,19 +1,18 @@
 <template>
-    <movable-area class="suspension-area" :style="areaStyle">
+    <movable-area v-if="inited" class="suspension-area" :style="areaStyle">
         <movable-view
             class="suspension-view"
             direction="all"
             :x="x"
             :y="y"
-            :inertia="props.inertia"
+            :inertia="inertia"
             :out-of-bounds="true"
             :disabled="false"
             :scale="false"
             :style="{
-                width: `${props.imageWidth}px`,
-                height: `${props.imageHeight}px`,
+                width: width,
+                height: height,
             }"
-            @change="onChange"
             @click="handleClick">
             <slot />
         </movable-view>
@@ -21,41 +20,54 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, computed } from 'vue';
 
+
+/**
+ * Props
+ * - width: 组件宽度字符串,支持 rpx/px,例如 '120rpx'
+ * - height: 组件高度字符串,支持 rpx/px,例如 '120rpx'
+ * - right: 距右侧偏移,支持 rpx/px,例如 '20rpx'
+ * - bottom: 距底部偏移,支持 rpx/px,例如 '200rpx'
+ * - inertia/snapThreshold/bgColor/borderRadius: 其他配置
+ * 行为:初始化后根据屏幕宽高与 right/bottom 计算 x/y,默认右下角,避免渲染闪动
+ */
 // 定义props
 interface Props {
-    imageSrc?: string;
-    imageWidth?: number; // 使用px单位,不再支持rpx
-    imageHeight?: number; // 使用px单位,不再支持rpx
-    x?: number; // x坐标(距离屏幕左边的距离,px单位)
-    y?: number; // y坐标(距离屏幕顶部的距离,px单位)
+    width?: string; // 宽度 rpx/px 字符串
+    height?: string; // 高度 rpx/px 字符串
+    right?: string; // 距右侧 rpx/px 字符串
+    bottom?: string; // 距底部 rpx/px 字符串
     inertia?: boolean;
-    snapThreshold?: number;
     bgColor?: string;
     borderRadius?: string;
 }
 
 const props = withDefaults(defineProps<Props>(), {
-    imageSrc: '/static/logo.png',
-    imageWidth: 50, // 默认宽度 50px
-    imageHeight: 50, // 默认高度 50px
-    x: 10, // 默认距离左边 10px
-    y: 200, // 默认距离顶部 200px
+    width: '120rpx', // 默认宽度
+    height: '120rpx', // 默认高度
+    right: '10rpx', // 默认右侧间距
+    bottom: '280rpx', // 默认底部间距
     inertia: false,
-    snapThreshold: 30,
     bgColor: 'transparent',
     borderRadius: '0',
 });
 
 // 响应式状态
-const x = ref<number>(props.x); // movable-view的x坐标(距离左边)
-const y = ref<number>(props.y); // movable-view的y坐标(距离顶部)
+const x = ref<number>(0); // movable-view的x坐标(距离左边)
+const y = ref<number>(0); // movable-view的y坐标(距离顶部)
+const inited = ref<boolean>(false); // 控制渲染时机,避免闪动
 
 // 屏幕尺寸
 const screenWidth = ref<number>(0);
 const screenHeight = ref<number>(0);
 
+// 将字符串尺寸转换为像素(px),使用 uView 的换算
+function toPx(val?: string | number): number {
+    if (val === undefined || val === null) return 0;
+    if (typeof val === 'number') return val;
+    return (uni as any).$u.getPx(val as string);
+}
+
 // movable-area 样式
 const areaStyle = computed(() => {
     return {
@@ -73,30 +85,23 @@ onMounted(() => {
     const systemInfo = uni.getSystemInfoSync();
     screenWidth.value = systemInfo.windowWidth;
     screenHeight.value = systemInfo.windowHeight;
+    // 根据 right/bottom 计算初始位置(默认右下角)
+    const widthPx = toPx(props.width);
+    const heightPx = toPx(props.height);
+    const rightPx = toPx(props.right);
+    const bottomPx = toPx(props.bottom);
+    x.value = Math.max(0, screenWidth.value - rightPx - widthPx);
+    y.value = Math.max(0, screenHeight.value - bottomPx - heightPx);
+    inited.value = true;
 });
-// movable-view 位置变化事件
-const onChange = (e: any) => {
-    // if (e.detail) {
-    //     // 直接更新位置
-    //     x.value = e.detail.x;
-    //     y.value = e.detail.y;
-    //     console.log(x.value, y.value);
-    // 标记为正在拖动
-    // isDragging.value = true;
-    // }
-};
-
-// 触摸结束事件(拖动结束)
-const onTouchEnd = () => {
-    // 拖动结束后进行边界检查和吸附
-    // applyBoundaryAndSnap();
-    // isDragging.value = false;
-};
+// click 事件抛出
+const emit = defineEmits<{
+    (e: 'click', payload: { x: number; y: number }): void;
+}>();
 
 // 点击事件
 const handleClick = () => {
-    // 触发点击事件
-    console.log('悬浮按钮被点击', { x: x.value, y: y.value });
+    emit('click', { x: x.value, y: y.value });
 };
 </script>
 

+ 79 - 20
src/components/ut-tabar/ut-tabar.vue

@@ -1,34 +1,92 @@
 <template>
-    <view class="w-100%" style="position: fixed; bottom: 0; left: 0">
+    <up-popup v-model:show="showStorage" title="请选择操作类型" bgColor="#F7F7F7" round="0" zIndex="1000" closeable>
+        <view class="min-h-600">
+            <view class="c-#333 f-s-34 f-w-500 pd-24">请选择操作类型</view>
+            <view class="pd2-10-24">
+                <up-grid :border="false" :column="3" gap="10rpx">
+                    <up-grid-item>
+                        <view class="pd2-10-0 d-flex flex-cln a-c j-c" @click="showStorage = false;$u.route({ url: '/plant/storage/storage-room/list/index' })">
+                            <view class="w-109 h-109 bg-#fff radius-50% d-flex a-c j-c mb-10">
+                                <image class="w-72 h-72" src="@/static/images/plant/storage/nav_kfgl_icon.png" mode="widthFix" />
+                            </view>
+                            <view class="c-#333 f-s-28 text-center">库房管理</view>
+                        </view>
+                    </up-grid-item>
+                    <up-grid-item>
+                        <view class="pd2-10-0 d-flex flex-cln a-c j-c">
+                            <view class="w-109 h-109 bg-#fff radius-50% d-flex a-c j-c mb-10">
+                                <image class="w-72 h-72" src="@/static/images/plant/storage/nav_nzk_icon.png" mode="widthFix" />
+                            </view>
+                            <view class="c-#333 f-s-28 text-center">农资库</view>
+                        </view>
+                    </up-grid-item>
+                    <up-grid-item>
+                        <view class="pd2-10-0 d-flex flex-cln a-c j-c">
+                            <view class="w-109 h-109 bg-#fff radius-50% d-flex a-c j-c mb-10">
+                                <image class="w-72 h-72" src="@/static/images/plant/storage/nav_zyk_icon.png" mode="widthFix" />
+                            </view>
+                            <view class="c-#333 f-s-28 text-center">种源库</view>
+                        </view>
+                    </up-grid-item>
+                    <up-grid-item>
+                        <view class="pd2-10-0 d-flex flex-cln a-c j-c">
+                            <view class="w-109 h-109 bg-#fff radius-50% d-flex a-c j-c mb-10">
+                                <image class="w-72 h-72" src="@/static/images/plant/storage/nav_xhk_icon.png" mode="widthFix" />
+                            </view>
+                            <view class="c-#333 f-s-28 text-center">鲜货库</view>
+                        </view>
+                    </up-grid-item>
+                    <up-grid-item>
+                        <view class="pd2-10-0 d-flex flex-cln a-c j-c">
+                            <view class="w-109 h-109 bg-#fff radius-50% d-flex a-c j-c mb-10">
+                                <image class="w-72 h-72" src="@/static/images/plant/storage/nav_zjpk_icon.png" mode="widthFix" />
+                            </view>
+                            <view class="c-#333 f-s-28 text-center">中间品库</view>
+                        </view>
+                    </up-grid-item>
+                    <up-grid-item>
+                        <view class="pd2-10-0 d-flex flex-cln a-c j-c">
+                            <view class="w-109 h-109 bg-#fff radius-50% d-flex a-c j-c mb-10">
+                                <image class="w-72 h-72" src="@/static/images/plant/storage/nav_cpk_icon.png" mode="widthFix" />
+                            </view>
+                            <view class="c-#333 f-s-28 text-center">成品库</view>
+                        </view>
+                    </up-grid-item>
+                </up-grid>
+            </view>
+            <view class="h-210"></view>
+        </view>
+    </up-popup>
+    <view class="w-100%" style="position: fixed; bottom: 0; left: 0; z-index: 1100">
         <view class="p-rtv" style="height: 210rpx">
             <image class="w-100%" src="/static/images/plant/bottombg.png" mode="widthFix" style="position: absolute; bottom: 0; left: 0; z-index: -1" />
             <view class="d-flex h-140 w-100% j-sa" style="position: absolute; bottom: 0; left: 0">
                 <view class="d-flex a-c flex1 j-sa">
-                    <view @click="$u.route({ type: 'switchTab', url: '/pages/plant/base/index' })" class="c-#999 f-s-24 d-flex flex-cln">
-                        <image v-if="activeTab !== 'base'" class="w-80 h-80" src="/static/images/plant/bottomBase.png" mode="widthFix" />
-                        <image v-if="activeTab === 'base'" class="w-80 h-80" src="/static/images/plant/bottomBaseActive.png" mode="widthFix" />
-                        <view class="text-center" :class="activeTab === 'base' ? 'c-primary f-w-5' : ''">基地</view>
+                    <view @click="showStorage = false;$u.route({ type: 'switchTab', url: '/pages/plant/base/index' })" class="c-#999 f-s-24 d-flex flex-cln j-c a-c">
+                        <image v-if="activeTab === 'base' && !showStorage" class="w-80 h-80" src="/static/images/plant/bottomBaseActive.png" mode="widthFix" />
+                        <image v-else class="w-80 h-80" src="/static/images/plant/bottomBase.png" mode="widthFix" />
+                        <view class="text-center" :class="activeTab === 'base' && !showStorage ? 'c-primary f-w-5' : ''">基地</view>
                     </view>
-                    <view @click="$u.route({ type: 'switchTab', url: '/pages/plant/port/index' })" class="c-#999 f-s-24 d-flex flex-cln">
-                        <image v-if="activeTab !== 'planting'" class="w-80 h-80" src="/static/images/plant/bottomPlantingBreeding.png" mode="widthFix" />
-                        <image v-if="activeTab === 'planting'" class="w-80 h-80" src="/static/images/plant/bottomPlantingBreedingActive.png" mode="widthFix" />
-                        <view class="text-center" :class="activeTab === 'planting' ? 'c-primary f-w-5' : ''">种养殖</view>
+                    <view @click="showStorage = false;$u.route({ type: 'switchTab', url: '/pages/plant/port/index' })" class="c-#999 f-s-24 d-flex flex-cln j-c a-c">
+                        <image v-if="activeTab === 'planting' && !showStorage" class="w-80 h-80" src="/static/images/plant/bottomPlantingBreedingActive.png" mode="widthFix" />
+                        <image v-else class="w-80 h-80" src="/static/images/plant/bottomPlantingBreeding.png" mode="widthFix" />
+                        <view class="text-center" :class="activeTab === 'planting' && !showStorage ? 'c-primary f-w-5' : ''">种养殖</view>
                     </view>
                 </view>
-                <view class="w-126 d-flex a-c j-c p-rtv">
-                    <image v-if="activeTab !== 'warehouse'" class="w-80 h-80" src="/static/images/plant/bottomWarehouse.png" mode="widthFix" style="position: absolute; top: -40rpx" />
-                    <image v-if="activeTab === 'warehouse'" class="w-80 h-80" src="/static/images/plant/bottomWarehouseActive.png" mode="widthFix" style="position: absolute; top: -40rpx" />
+                <view class="w-126 d-flex a-c j-c p-rtv" @click="showStorage = !showStorage">
+                    <image v-if="!showStorage" class="w-80 h-80" src="/static/images/plant/bottomWarehouse.png" mode="widthFix" style="position: absolute; top: -40rpx" />
+                    <image v-else class="w-80 h-80" src="/static/images/plant/bottomWarehouseActive.png" mode="widthFix" style="position: absolute; top: -40rpx" />
                 </view>
                 <view class="d-flex a-c flex1 j-sa">
-                    <view class="c-#999 f-s-24 d-flex flex-cln">
-                        <image v-if="activeTab !== 'processing'" class="w-80 h-80" src="/static/images/plant/bottomProcessingPackaging.png" mode="widthFix" />
-                        <image v-if="activeTab === 'processing'" class="w-80 h-80" src="/static/images/plant/bottomProcessingPackagingActive.png" mode="widthFix" />
-                        <view class="text-center" :class="activeTab === 'processing' ? 'c-primary f-w-5' : ''">加工包装</view>
+                    <view class="c-#999 f-s-24 d-flex flex-cln j-c a-c">
+                        <image v-if="activeTab === 'processing' && !showStorage" class="w-80 h-80" src="/static/images/plant/bottomProcessingPackagingActive.png" mode="widthFix" />
+                        <image v-else class="w-80 h-80" src="/static/images/plant/bottomProcessingPackaging.png" mode="widthFix" />
+                        <view class="text-center" :class="activeTab === 'processing'  && !showStorage ? 'c-primary f-w-5' : ''">加工包装</view>
                     </view>
-                    <view class="c-#999 f-s-24 d-flex flex-cln">
-                        <image v-if="activeTab !== 'more'" class="w-80 h-80" src="/static/images/plant/bottomMore.png" mode="widthFix" />
-                        <image v-if="activeTab === 'more'" class="w-80 h-80" src="/static/images/plant/bottomMoreActive.png" mode="widthFix" />
-                        <view class="text-center" :class="activeTab === 'more' ? 'c-primary f-w-5' : ''">更多</view>
+                    <view class="c-#999 f-s-24 d-flex flex-cln j-c a-c">
+                        <image v-if="activeTab === 'more' && !showStorage" class="w-80 h-80" src="/static/images/plant/bottomMoreActive.png" mode="widthFix" />
+                        <image v-else class="w-80 h-80" src="/static/images/plant/bottomMore.png" mode="widthFix" />
+                        <view class="text-center" :class="activeTab === 'more' && !showStorage ? 'c-primary f-w-5' : ''">更多</view>
                     </view>
                 </view>
             </view>
@@ -38,6 +96,7 @@
 </template>
 
 <script setup lang="ts">
+const showStorage = ref(false);
 defineProps<{
     activeTab?: string; // 当前活跃的tab标识符:'base' | 'planting' | 'warehouse' | 'processing' | 'more'
 }>();

+ 27 - 0
src/pages.json

@@ -140,6 +140,33 @@
                 }
             ]
         },
+        // 库存
+        {
+            "root": "plant/storage",
+            "pages": [
+               // 库房管理
+                {
+                    "path": "storage-room/list/index",
+                    "style": {
+                        "navigationBarTitleText": "库房管理"
+                    }
+                },
+                // 新增库房
+                {
+                    "path": "storage-room/edit/index",
+                    "style": {
+                        "navigationBarTitleText": "新增库房"
+                    }
+                },
+                // 库房详情
+                {
+                    "path": "storage-room/detail/index",
+                    "style": {
+                        "navigationBarTitleText": "库房详情"
+                    }
+                }
+            ]
+        },
         {
             "root": "tools",
             "pages": [

+ 1 - 1
src/pages/index/index.vue

@@ -26,7 +26,7 @@
             <view class="bg-blue-500 c-primary p-4 rounded">Hello UnoCSS!</view>
             <up-button @click="$u.route({ type: 'switchTab', url: '/pages/plant/base/index' })" text="index1" color="linear-gradient(to right, rgb(66, 83, 216), rgb(213, 51, 186))" />
             <up-button @click="$u.route({ type: 'switchTab', url: '/pages/plant/port/index' })" text="plantport" color="linear-gradient(to right, rgb(66, 83, 216), rgb(213, 51, 186))" />
-            <up-button @click="$u.route({ type: 'navigateTo', url: '/pages/plant/base/index' })" text="plant" color="linear-gradient(to right, rgb(66, 83, 216), rgb(213, 51, 186))" />
+            <up-button @click="$u.route({ type: 'switchTab', url: '/pages/plant/base/index' })" text="plant" color="linear-gradient(to right, rgb(66, 83, 216), rgb(213, 51, 186))" />
             <up-button @click="$u.route({ type: 'switchTab', url: '/pages/production/index' })" text="production" color="linear-gradient(to right, rgb(66, 83, 216), rgb(213, 51, 186))" />
         </view>
     </z-paging>

+ 78 - 39
src/pages/plant/base/index.vue

@@ -80,40 +80,44 @@
                     </up-sticky>
                     <view class="pd4-16-24-16-24">
                         <template>
-                            <view v-for="(item, index) in list" :key="index" class="b-radius bg-#fff pd-20 mb-20 p-rtv" @click="$u.route({ url: '/plant/base/base-detail/index', params: { id: item.id } })">
-                                <view class="c-333 f-s-34 pd-5 f-w-5">{{ item?.baseName }}</view>
-                                <view class="c-ccc f-s-24 pd-5 pt-0">{{ item?.baseCode }}</view>
-                                <view class="d-flex a-c">
-                                    <view class="c-333 f-s-28 pd-5">
-                                        <text class="c-#666">基地面积:</text>
-                                        <text class="f-w-5">{{ item?.gapInfo?.area || '-' }}</text>
+                            <up-swipe-action>
+                                <up-swipe-action-item v-for="(item, index) in list" :key="index" :name="item?.id" :options="optionsActionTemp" @click="clickTempSwipe" class="mb-20 b-radius">
+                                    <view class="b-radius bg-#fff pd-20 p-rtv" @click.stop="$u.route({ url: '/plant/base/base-detail/index', params: { id: item.id } })">
+                                        <view class="c-333 f-s-34 pd-5 f-w-5">{{ item?.baseName }}</view>
+                                        <view class="c-ccc f-s-24 pd-5 pt-0">{{ item?.baseCode }}</view>
+                                        <view class="d-flex a-c">
+                                            <view class="c-333 f-s-28 pd-5">
+                                                <text class="c-#666">基地面积:</text>
+                                                <text class="f-w-5">{{ item?.gapInfo?.area || '-' }}</text>
+                                            </view>
+                                            <view class="flex1"></view>
+                                            <view class="c-333 f-s-28 pd-5">
+                                                <text class="c-#666">建设时间:</text>
+                                                <text class="f-w-5">{{ item?.buildDate || '-' }}</text>
+                                            </view>
+                                        </view>
+                                        <view class="c-333 f-s-28 pd-5">
+                                            <text class="c-#666">基地地址:</text>
+                                            <text class="f-w-5">{{ item?.gapInfo?.address || '-' }}</text>
+                                        </view>
+                                        <view v-if="item?.plantingVarieties?.length" class="c-333 f-s-28 pd-5 d-flex">
+                                            <text class="c-#666 w-s-no">当前在地品种:</text>
+                                            <text class="ov-hd tx-ov w-s-no f-w-5">{{ item.plantingVarieties?.map((items) => items.variety).join('、') || '-' }}</text>
+                                            <text v-if="item?.plantingVarieties?.length" class="flex1 w-s-no f-w-5">等{{ item.plantingVarieties?.length }}个品种</text>
+                                        </view>
+                                        <view class="pd-10"></view>
+                                        <view v-if="item.gapInfo?.basePic" class="p-rtv">
+                                            <image class="w-full h-310" :src="item.gapInfo?.basePic" mode="aspectFill"></image>
+                                            <view class="d-flex flex-cln a-ed" style="position: absolute; bottom: 20rpx; right: 0">
+                                                <view class="pd2-10-20 bg-black-op-0.5 c-#ccc f-s-20 mb-10" style="border-radius: 10rpx 0 0 10rpx; width: max-content">{{ item?.contactName }}负责</view>
+                                                <view class="pd2-10-20 bg-black-op-0.5 c-#ccc f-s-20 mb-10" style="border-radius: 10rpx 0 0 10rpx; width: max-content">公司+合作社</view>
+                                                <view class="pd2-10-20 bg-black-op-0.5 c-#ccc f-s-20" style="border-radius: 10rpx 0 0 10rpx; width: max-content">经度:E{{ item?.gapInfo?.lng }} 纬度:N{{ item?.gapInfo?.lat }}</view>
+                                            </view>
+                                        </view>
+                                        <view v-if="+(item?.tempFlag ?? 0)" class="temp_flag">暂存</view>
                                     </view>
-                                    <view class="flex1"></view>
-                                    <view class="c-333 f-s-28 pd-5">
-                                        <text class="c-#666">建设时间:</text>
-                                        <text class="f-w-5">{{ item?.buildDate || '-' }}</text>
-                                    </view>
-                                </view>
-                                <view class="c-333 f-s-28 pd-5">
-                                    <text class="c-#666">基地地址:</text>
-                                    <text class="f-w-5">{{ item?.gapInfo?.address || '-' }}</text>
-                                </view>
-                                <view v-if="item?.plantingVarieties?.length" class="c-333 f-s-28 pd-5 d-flex">
-                                    <text class="c-#666 w-s-no">当前在地品种:</text>
-                                    <text class="ov-hd tx-ov w-s-no f-w-5">{{ item.plantingVarieties?.map((items) => items.variety).join('、') || '-' }}</text>
-                                    <text v-if="item?.plantingVarieties?.length" class="flex1 w-s-no f-w-5">等{{ item.plantingVarieties?.length }}个品种</text>
-                                </view>
-                                <view class="pd-10"></view>
-                                <view v-if="item.gapInfo?.basePic" class="p-rtv">
-                                    <image class="w-full h-310" :src="item.gapInfo?.basePic" mode="aspectFill"></image>
-                                    <view class="d-flex flex-cln a-ed" style="position: absolute; bottom: 20rpx; right: 0">
-                                        <view class="pd2-10-20 bg-black-op-0.5 c-#ccc f-s-20 mb-10" style="border-radius: 10rpx 0 0 10rpx; width: max-content"> {{ item?.contactName }}负责</view>
-                                        <view class="pd2-10-20 bg-black-op-0.5 c-#ccc f-s-20 mb-10" style="border-radius: 10rpx 0 0 10rpx; width: max-content"> 公司+合作社</view>
-                                        <view class="pd2-10-20 bg-black-op-0.5 c-#ccc f-s-20" style="border-radius: 10rpx 0 0 10rpx; width: max-content"> 经度:E{{ item?.gapInfo?.lng }} 纬度:N{{ item?.gapInfo?.lat }}</view>
-                                    </view>
-                                </view>
-                                <view v-if="+(item?.tempFlag ?? 0)" class="temp_flag">暂存</view>
-                            </view>
+                                </up-swipe-action-item>
+                            </up-swipe-action>
                         </template>
                     </view>
                 </view>
@@ -130,10 +134,8 @@
         </template>
         <view class="h-210" v-if="list?.length"></view>
         <view v-if="list?.length" :style="{ height: `${safeAreaBottom}px` }"></view>
-        <template #bottom>
-            <ut-tabar activeTab="base"></ut-tabar>
-        </template>
     </z-paging>
+    <ut-tabar activeTab="base"></ut-tabar>
     <ut-confirm-dialog v-model:show="showDeleteDialog" width="80vw" title="请选择要添加到基地类型" :confirmText="'确认选择'" :cancelText="'取消'" @confirm="handlechoseConfirm" @cancel="handleDeleteCancel">
         <view class="" v-for="item in pt_base_type" :key="item?.value">
             <view style="border: 1rpx solid" :style="{ backgroundColor: item?.value == basetype ? '#EBF6EE' : '#f7f7f7', borderColor: item?.value == basetype ? '#37A954' : 'transparent' }" class="pr-30 d-flex a-c mb-20 radius-100" @click="handlechose(item.value)">
@@ -150,15 +152,14 @@
             </view>
         </view>
     </ut-confirm-dialog>
-    <ut-suspension v-if="sus?.left" :imageWidth="60" :imageHeight="60" :x="sus?.left" :y="sus?.bottom" :inertia="false" :snap-threshold="40">
-        <image src="/static/images/plant/addBase.png" mode="widthFix" style="height: 60px; width: 60px" @click="showDeleteDialog = true"></image>
+    <ut-suspension @click="showDeleteDialog = true">
+        <image src="/static/images/plant/addBase.png" mode="widthFix" class="w-120 h-120"></image>
     </ut-suspension>
 </template>
 <script setup lang="ts">
 import { useClientRequest } from '@/utils/request';
 import { setCipByNum } from '@/utils/public';
 import { useInfoStore } from '@/store';
-import { computed, ref } from 'vue';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { pt_base_type } = toRefs<any>(proxy?.useDict('pt_base_type'));
 const infoStore = useInfoStore();
@@ -305,6 +306,44 @@ const handlechoseConfirm = () => {
     uni.$u.route({ type: 'navigateTo', url: '/plant/base/base-edit/index', params: { baseType: basetype.value } });
 };
 
+// 暂存项左滑删除配置
+const optionsActionTemp = reactive([
+    {
+        text: '删除',
+        style: {
+            backgroundColor: '#f56c6c',
+        },
+    },
+]);
+
+// 暂存项删除点击(本地移除)
+const clickTempSwipe = async (event: object) => {
+    const { name, index } = event as any;
+    if (index === 0) {
+        try {
+            const res = await uni.showModal({
+                title: '提示',
+                content: '确定删除该基地吗?',
+                confirmColor: '#FF4C4C',
+            });
+            if (!res.confirm) return;
+            await uni.showLoading({
+                title: '删除中...',
+                mask: true,
+            });
+            await useClientRequest.get(`/plt-api/app/base/delById/${name}`);
+            uni.hideLoading();
+            uni.showToast({
+                title: '删除成功',
+                icon: 'success',
+            });
+            paging.value?.reload();
+        } catch (error) {
+            console.error('删除暂存基地失败:', error);
+        }
+    }
+};
+
 onMounted(() => {
     const querys = uni.createSelectorQuery().in(instance?.proxy);
     querys

+ 15 - 15
src/pages/plant/port/index.vue

@@ -30,25 +30,25 @@
                     <view class="c-#666 f-s-26">虫卵属蓝棵</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">养殖批号:</view>
+                    <view class="c-#666 w-s-no">养殖批号</view>
                     <view class="c-#333 f-w-5">1231231231232</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">种源批号:</view>
+                    <view class="c-#666 w-s-no">种源批号</view>
                     <view class="c-#333 f-w-5">1231231231232</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">基地:</view>
+                    <view class="c-#666 w-s-no">基地</view>
                     <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">123112312312312312312312312312312312312312312323</view>
                     <view class="flex1 d-flex j-ed"><up-icon name="arrow-right" size="34rpx"></up-icon></view>
                 </view>
                 <view class="d-flex f-s-28 pd-16 pt-8 pb-8">
                     <view class="d-flex a-c w-50%">
-                        <view class="c-#666 w-s-no">养殖区域:</view>
+                        <view class="c-#666 w-s-no">养殖区域</view>
                         <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">20亩</view>
                     </view>
                     <view class="d-flex a-c w-50%">
-                        <view class="c-#666 w-s-no">养殖量:</view>
+                        <view class="c-#666 w-s-no">养殖量</view>
                         <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">120000</view>
                     </view>
                 </view>
@@ -71,25 +71,25 @@
                     <view class="c-#666 f-s-26">虫卵属蓝棵</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">繁育批号:</view>
+                    <view class="c-#666 w-s-no">繁育批号</view>
                     <view class="c-#333 f-w-5">1231231231232</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">种源批号:</view>
+                    <view class="c-#666 w-s-no">种源批号</view>
                     <view class="c-#333 f-w-5">1231231231232</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">基地:</view>
+                    <view class="c-#666 w-s-no">基地</view>
                     <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">123112312312312312312312312312312312312312312323</view>
                     <view class="flex1 d-flex j-ed"><up-icon name="arrow-right" size="34rpx"></up-icon></view>
                 </view>
                 <view class="d-flex f-s-28 pd-16 pt-8 pb-8">
                     <view class="d-flex a-c w-50%">
-                        <view class="c-#666 w-s-no">种植面积:</view>
+                        <view class="c-#666 w-s-no">种植面积</view>
                         <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">20亩</view>
                     </view>
                     <view class="d-flex a-c w-50%">
-                        <view class="c-#666 w-s-no">繁育量:</view>
+                        <view class="c-#666 w-s-no">繁育量</view>
                         <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">120000</view>
                     </view>
                 </view>
@@ -112,25 +112,25 @@
                     <view class="c-#666 f-s-26">虫卵属蓝棵</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">种植批号:</view>
+                    <view class="c-#666 w-s-no">种植批号</view>
                     <view class="c-#333 f-w-5">1231231231232</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">种源批号:</view>
+                    <view class="c-#666 w-s-no">种源批号</view>
                     <view class="c-#333 f-w-5">1231231231232</view>
                 </view>
                 <view class="d-flex a-c f-s-28 pd-16 pt-8 pb-8">
-                    <view class="c-#666 w-s-no">基地:</view>
+                    <view class="c-#666 w-s-no">基地</view>
                     <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">123112312312312312312312312312312312312312312323</view>
                     <view class="flex1 d-flex j-ed"><up-icon name="arrow-right" size="34rpx"></up-icon></view>
                 </view>
                 <view class="d-flex f-s-28 pd-16 pt-8 pb-8">
                     <view class="d-flex a-c w-50%">
-                        <view class="c-#666 w-s-no">种植面积:</view>
+                        <view class="c-#666 w-s-no">种植面积</view>
                         <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">20亩</view>
                     </view>
                     <view class="d-flex a-c w-50%">
-                        <view class="c-#666 w-s-no">种植量:</view>
+                        <view class="c-#666 w-s-no">种植量</view>
                         <view class="c-#333 f-w-5 tx-ov w-s-no ov-hd">120000</view>
                     </view>
                 </view>

+ 2 - 2
src/plant/base/base-detail/index.vue

@@ -94,11 +94,11 @@
                     </view>
                 </view>
                 <view class="h-1" id="plot12345"></view>
-                <!-- 地块/圈舍/培架信息 -->
+                <!-- 地块/圈舍/培架信息 -->
                 <view ref="plotRef" class="pd-24">
                     <view class="startline-title" v-if="form?.baseInfo?.baseType == '1'">地块信息</view>
                     <view class="startline-title" v-else-if="form?.baseInfo?.baseType == '2'">圈舍信息</view>
-                    <view class="startline-title" v-else-if="form?.baseInfo?.baseType == '3'">培架信息</view>
+                    <view class="startline-title" v-else-if="form?.baseInfo?.baseType == '3'">培架信息</view>
                 </view>
                 <view class="pd-24 bg-#fff mb-10">
                     <template v-if="Array.isArray(form?.landInfoList) && form.landInfoList.length">

+ 6 - 6
src/plant/base/base-edit/index.vue

@@ -214,7 +214,7 @@
                     </up-form-item>
                 </template>
             </view>
-            <!-- 地块/圈舍/培架信息 -->
+            <!-- 地块/圈舍/培架信息 -->
             <view ref="plotRef" class="h-1" id="plot12345"></view>
             <template v-if="form.baseInfo.baseType == '1'">
                 <view class="pd-24">
@@ -273,12 +273,12 @@
             </template>
             <template v-if="form.baseInfo.baseType == '3'">
                 <view class="pd-24">
-                    <view class="startline-title">培架信息</view>
+                    <view class="startline-title">培架信息</view>
                 </view>
                 <view class="pd-24 bg-#fff">
                     <up-swipe-action>
                         <template v-for="(item, index) in form.landInfoList" :key="index">
-                            <up-swipe-action-item class="mb-20" :options="options" @click="clickPlotSwipe($event, item, index, '编辑培架信息')">
+                            <up-swipe-action-item class="mb-20" :options="options" @click="clickPlotSwipe($event, item, index, '编辑培架信息')">
                                 <view class="plot-item pd-24">
                                     <view class="d-flex mb-16">
                                         <view class="f-s-32 f-w-5 c-#333 flex1 mr-10">{{ item?.landName || '-' }}</view>
@@ -306,9 +306,9 @@
                             </up-swipe-action-item>
                         </template>
                     </up-swipe-action>
-                    <up-button @click="addPlot({ landType: form.baseInfo.baseType, areaUnit: form.baseInfo.gapInfo.areaUnit, capacityUnit: '瓶' }, '添加培架')" type="primary" text="确定" plain>
+                    <up-button @click="addPlot({ landType: form.baseInfo.baseType, areaUnit: form.baseInfo.gapInfo.areaUnit, capacityUnit: '瓶' }, '添加培架')" type="primary" text="确定" plain>
                         <up-icon class="mr-10" name="plus" color="#37A954"></up-icon>
-                        <span>添加培架信息</span>
+                        <span>添加培架信息</span>
                     </up-button>
                 </view>
             </template>
@@ -594,7 +594,7 @@ const form = ref<any>({
         },
         coordinates: [],
     }, // 基地信息
-    landInfoList: [], // 地块/圈舍/培架信息
+    landInfoList: [], // 地块/圈舍/培架信息
     environmentInfo: {}, // 基地环境信息
 });
 const options = ref([

+ 2 - 2
src/plant/base/gap-base-info/index.vue

@@ -3,10 +3,10 @@
         <template #top>
             <ut-navbar title="GAP基地信息" :fixed="false" border></ut-navbar>
             <view class="d-flex a-c pd-25">
-                <view class="min-w-170 flex1">
+                <view class="min-w-200 flex1">
                     <ut-action-sheet v-model="form.res" :tabs="tabs" @change="onRefresh" title="选择基地类型">
                         <view class="d-flex search-select-item a-c">
-                            <view class="flex1 ov-hd f-s-28 c-333 text-center f-w-5 w-s-no">{{ '全部' }}</view>
+                            <view class="flex1 ov-hd f-s-28 c-333 text-center f-w-5 w-s-no">{{ selectDictLabel(tabs, form.res) || '全部' }}</view>
                             <up-icon size="24rpx" color="#333" name="arrow-down-fill" class="mr-5"></up-icon>
                         </view>
                     </ut-action-sheet>

+ 180 - 33
src/plant/port/port-create/index.vue

@@ -7,10 +7,10 @@
             <up-form class="p-rtv" labelPosition="top" :model="form" :rules="rules" labelWidth="auto" ref="upFormRef">
                 <view class="startline-title pl-24 ml-24 mb-16">基地信息</view>
                 <view class="bg-#fff pd-24">
-                    <view class="b-radius bg-#EBF6EE c-primary f-s-24 pd-24 pb-16"> 注意:关联时请确保已添加到地块;关联时必须选到地块/圈舍/培架。</view>
+                    <view class="b-radius bg-#EBF6EE c-primary f-s-24 pd-24 pb-16"> 注意:关联时请确保已添加到地块;关联时必须选到地块/圈舍/培架。</view>
                 </view>
                 <view class="bg-#fff pd-24 mb-20 pt-0">
-                    <up-form-item :borderBottom="false" label="种养殖所在基地" required prop="baseId">
+                    <up-form-item :borderBottom="false" label="种养殖所在基地" required prop="baseId" id="baseIdpppp">
                         <view v-if="!deawerData" class="w-100% d-flex a-c j-c pd-24 b-radius bg-#FBFDFB border-#AFDDBB" @click="openDrawer">
                             <view class=""></view>
                             <view class="f-s-34 c-primary">请选择种养殖所在的基地</view>
@@ -23,12 +23,12 @@
                 <view class="startline-title pl-24 ml-24 mb-16">种养殖信息</view>
                 <view class="bg-#fff pd-24 mb-20">
                     <ut-action-sheet v-model="form.taskType" :tabs="pt_task_type" title="选择任务类型">
-                        <up-form-item borderBottom label="任务类型" required prop="taskType">
+                        <up-form-item borderBottom label="任务类型" required prop="taskType" id="taskTypepppp">
                             <view class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(pt_task_type, form.taskType) }}</view>
                         </up-form-item>
                     </ut-action-sheet>
                     <ut-action-sheet v-model="form.mgMethod" :tabs="mg_method" title="选择溯源级别">
-                        <up-form-item borderBottom label="溯源级别" required prop="mgMethod">
+                        <up-form-item borderBottom label="溯源级别" required prop="mgMethod" id="mgMethodpppp">
                             <view v-if="form.mgMethod" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(mg_method, form.mgMethod) }}</view>
                             <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择溯源级别</view>
                             <template #right>
@@ -37,7 +37,7 @@
                         </up-form-item>
                     </ut-action-sheet>
                     <ut-action-sheet v-model="form.gapFlag" :tabs="task_gap_flag" title="选择符合要求">
-                        <up-form-item borderBottom label="符合要求" required prop="gapFlag">
+                        <up-form-item borderBottom label="符合要求" required prop="gapFlag" id="gapFlagpppp">
                             <view v-if="form.gapFlag" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(task_gap_flag, form.gapFlag) }}</view>
                             <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择符合要求</view>
                             <template #right>
@@ -45,12 +45,12 @@
                             </template>
                         </up-form-item>
                     </ut-action-sheet>
-                    <up-form-item borderBottom label="动物名称" required prop="varietyId">
+                    <up-form-item borderBottom label="动物名称" required prop="varietyId" id="varietyIdpppp">
                         <view v-if="!Biological" @click="$u.route({ type: 'navigateTo', url: '/plant/port/por-torganism/index' })" class="w-100% d-flex a-c j-c pd-24 b-radius bg-#FBFDFB border-#AFDDBB">
                             <view class=""></view>
                             <view class="f-s-34 c-primary">请选择养植的动物名称</view>
                         </view>
-                        <view v-if="Biological" class="pd-30 d-flex flex-cln bg-#FBFDFB border-#37A954 b-radius mb-20 w-100% p-rtv">
+                        <view v-if="Biological" class="pd-24 d-flex flex-cln bg-#FBFDFB border-#37A954 b-radius mb-20 w-100% p-rtv">
                             <up-icon @click="Biological = null" size="26rpx" color="red" name="close" style="position: absolute; right: 10rpx; top: 10rpx"></up-icon>
                             <view class="mb-20">
                                 <text class="c-#333 f-s-34 f-w-5 mr-5">{{ Biological?.varietyName }}</text>
@@ -66,18 +66,18 @@
                             </view>
                         </view>
                     </up-form-item>
-                    <up-form-item borderBottom label="养殖批号" required prop="plantationCode">
+                    <up-form-item borderBottom label="养殖批号" required prop="plantationCode" id="plantationCodepppp">
                         <view class="d-flex a-c j-sb w-100%">
-                            <view class="flex1 c-#999">请生成养殖批号</view>
-                            <view class="flex1 c-#333">{{ form.plantationCode }}</view>
+                            <view v-if="!form.plantationCode" class="flex1 c-#999">请生成养殖批号</view>
+                            <view v-else class="flex1 c-#333">{{ form.plantationCode }}</view>
                             <up-button @click="randomCode" class="c-#fff" type="primary" style="height: 50rpx; width: 130rpx">随机生成</up-button>
                         </view>
                     </up-form-item>
-                    <up-form-item label="请选择养殖技术规程文件" prop="technicalFile" borderBottom>
+                    <up-form-item label="请选择养殖技术规程文件" prop="technicalFile" borderBottom id="technicalFilepppp">
                         <ut-upload v-model="form.technicalFile" :max-count="9" valueType="array" accept="file"></ut-upload>
                     </up-form-item>
                     <ut-action-sheet v-model="form.plantationMethod" :tabs="feeding_method" title="选择养殖方式">
-                        <up-form-item borderBottom label="养殖方式" required prop="plantationMethod">
+                        <up-form-item borderBottom label="养殖方式" required prop="plantationMethod" id="plantationMethodpppp">
                             <view v-if="form.plantationMethod" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(feeding_method, form.plantationMethod) }}</view>
                             <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择养殖方式</view>
                             <template #right>
@@ -85,32 +85,34 @@
                             </template>
                         </up-form-item>
                     </ut-action-sheet>
+                    <view class="h-1" id="queryType6pppp"></view>
                     <up-form-item :borderBottom="false" label="养殖时间" required prop="queryType6">
-                        <ut-datetime-picker v-model="form.queryType6.plannedStartDate" mode="date" dateFields="month">
+                        <ut-datetime-picker v-model="form.queryType6.plannedStartDate" mode="date" dateFields="day">
                             <view class="d-flex mr-20">
                                 <up-input v-model="form.queryType6.plannedStartDate" placeholder="请选择养殖开始时间" border="bottom" :customStyle="{ paddingLeft: '0rpx' }"></up-input>
                                 <up-icon size="22rpx" color="#2A6D52" name="arrow-down-fill" style="margin-left: -20rpx"></up-icon>
                             </view>
                         </ut-datetime-picker>
-                        <ut-datetime-picker v-model="form.queryType6.plannedEndDate" mode="date" dateFields="month">
+                        <ut-datetime-picker v-model="form.queryType6.plannedEndDate" mode="date" dateFields="day">
                             <view class="d-flex">
                                 <up-input v-model="form.queryType6.plannedEndDate" placeholder="请选择养殖结束时间" border="bottom" :customStyle="{ paddingLeft: '0rpx' }"></up-input>
                                 <up-icon size="22rpx" color="#2A6D52" name="arrow-down-fill" style="margin-left: -20rpx"></up-icon>
                             </view>
                         </ut-datetime-picker>
                     </up-form-item>
-                    <up-form-item borderBottom label="养殖面积" required prop="plantingAmount">
+                    <up-form-item borderBottom label="养殖面积" required prop="plantingAmount" id="plantingAmountpppp">
                         <view class="d-flex a-c j-sb w-100%">
                             <up-input style="padding-left: 0" v-model="form.plantingAmount" placeholder="请输入养殖面积" border="none"></up-input>
                             <view class="c-#333 f-s-32 f-w-5">平方米</view>
                         </view>
                     </up-form-item>
-                    <up-form-item borderBottom label="养殖区域" required prop="breedScale">
+                    <up-form-item borderBottom label="养殖区域" required prop="breedScale" id="breedScalepppp">
                         <view class="d-flex a-c j-sb w-100%">
                             <up-input v-model="form.breedScale" placeholder="请输入养殖区域" border="none"></up-input>
                             <view class="c-#333 f-s-32 f-w-5">个</view>
                         </view>
                     </up-form-item>
+                    <view class="h-1" id="plantpppp"></view>
                     <up-form-item borderBottom label="养殖量" required prop="plant">
                         <up-input v-model="form.plant.plantingMgAmount" placeholder="请输入养殖量" border="none"></up-input>
                         <ut-action-sheet v-model="form.plant.plantingMgUnit" :tabs="scale_unit" title="选择单位">
@@ -121,11 +123,34 @@
                             </view>
                         </ut-action-sheet>
                     </up-form-item>
-                    <up-form-item borderBottom label="备注" required prop="remark">
+                    <up-form-item borderBottom label="备注" required prop="remark" id="remarkpppp">
                         <up-input v-model="form.remark" placeholder="请输入备注" border="none"></up-input>
                     </up-form-item>
                 </view>
             </up-form>
+            <view v-if="+form.mgMethod == 2" class="">
+                <view class="startline-title pl-24 ml-24 mb-16">个体标识信息</view>
+                <view class="bg-#fff pd-24">
+                    <view class="d-flex pt-20 pb-20">
+                        <view class="">个体标识({{ animalIds.length }}个)</view>
+                        <view class="flex1"></view>
+                        <view class="border-#79C58C radius-100 c-primary f-s-24 pd4-10-20-10-20 d-flex a-c j-c">扫一扫添加</view>
+                    </view>
+                    <view class="d-flex gap-20">
+                        <view @click="showDeleteDialog = true" class="b-radius border-#AFDDBB bg-#FBFDFB c-primary w-100% d-flex j-c a-c h-100 f-s-34">手动输入添加</view>
+                        <view class="b-radius border-#A3E5EA c-#18BECA bg-#FAFFFF w-100% d-flex j-c a-c h-100 f-s-34">从种源库快速添加</view>
+                    </view>
+                    <up-swipe-action>
+                        <up-swipe-action-item v-model:show="showswipeAction" :options="options1">
+                            <view class="swipe-action up-border-top up-border-bottom">
+                                <view class="swipe-action__content">
+                                    <text class="swipe-action__content__text">基础使用</text>
+                                </view>
+                            </view>
+                        </up-swipe-action-item>
+                    </up-swipe-action>
+                </view>
+            </view>
         </view>
         <template #bottom>
             <view class="pd-24 d-flex j-c gap-20 base-bottom-wrap">
@@ -134,7 +159,14 @@
             </view>
         </template>
     </z-paging>
-
+    <ut-confirm-dialog v-model:show="showDeleteDialog" width="75vw" title="添加个体标识" :confirmText="'确认'" :cancelText="'取消'" @confirm="handleDeleteConfirm" @cancel="handleDeleteCancel">
+        <view class="">
+            <view class="c-#333 f-s-28"> 个体标识号 </view>
+            <view class="">
+                <up-input placeholder="请输入个体标识号" v-model="animalId" border="bottom"></up-input>
+            </view>
+        </view>
+    </ut-confirm-dialog>
     <!-- 添加drawer组件 -->
     <Drawer v-if="drawerVisible" :baseType="form.taskType" v-model="drawerVisible" @open="onDrawerOpen" @close="onDrawerClose" @confirm="onDrawerConfirm" />
 </template>
@@ -171,7 +203,75 @@ const form = ref({
     BreedingArea: '',
     breedingVolume: '',
     remark: '',
+    delegateFlag: '0',
 });
+//单个溯源都数组
+const animalIds = ref<any>([]);
+const animalId = ref();
+const showDeleteDialog = ref(false);
+const showswipeAction = ref(false);
+// 使用 reactive 创建响应式对象
+const options1 = reactive([
+    {
+        text: '删除',
+        style: {
+            backgroundColor: '#f56c6c',
+        },
+    },
+    {
+        text: '编辑',
+        style: {
+            backgroundColor: '#37A954',
+        },
+    },
+]);
+// 自定义校验函数:养殖时间校验
+const validateBreedingTime = (rule: any, value: any, callback: any) => {
+    if (!value) {
+        callback(new Error('请选择养殖时间'));
+        return;
+    }
+    const { plannedStartDate, plannedEndDate } = value;
+    if (!plannedStartDate) {
+        callback(new Error('请选择养殖开始时间'));
+        return;
+    }
+    if (!plannedEndDate) {
+        callback(new Error('请选择养殖结束时间'));
+        return;
+    }
+    const startDate = new Date(plannedStartDate);
+    const endDate = new Date(plannedEndDate);
+    if (endDate <= startDate) {
+        callback(new Error('养殖结束时间必须晚于开始时间'));
+        return;
+    }
+
+    callback();
+};
+
+// 自定义校验函数:养殖量校验
+const validateBreedingAmount = (rule: any, value: any, callback: any) => {
+    if (!value) {
+        callback(new Error('请输入养殖量'));
+        return;
+    }
+
+    const { plantingMgAmount, plantingMgUnit } = value;
+
+    if (!plantingMgAmount || plantingMgAmount.trim() === '') {
+        callback(new Error('请输入养殖量'));
+        return;
+    }
+
+    if (!plantingMgUnit) {
+        callback(new Error('请选择养殖量单位'));
+        return;
+    }
+
+    callback();
+};
+
 const rules = reactive({
     baseId: [{ required: true, message: '请选择种养殖所在的基地' }],
     taskType: [{ required: true, message: '请选择任务类型' }],
@@ -181,19 +281,15 @@ const rules = reactive({
     plantationCode: [{ required: true, message: '请输入养殖批号' }],
     technicalFile: [{ required: true, message: '请选择养殖技术规程文件' }],
     plantationMethod: [{ required: true, message: '请选择养殖方式' }],
-    'queryType6.plannedStartDate': [{ required: true, message: '请选择养殖开始时间' }],
-    'queryType6.plannedEndDate': [{ required: true, message: '请选择养殖结束时间' }],
+    queryType6: [{ validator: validateBreedingTime, trigger: 'blur' }],
     plantingAmount: [{ required: true, message: '请输入养殖面积' }],
     breedScale: [{ required: true, message: '请输入养殖区域' }],
-    'plant.plantingMgAmount': [{ required: true, message: '请输入养殖量' }],
-    'plant.plantingMgUnit': [{ required: true, message: '请选择养殖量单位' }],
+    plant: [{ validator: validateBreedingAmount, trigger: 'blur' }],
     remark: [{ required: true, message: '请输入备注' }],
 });
-const paging = ref<unknown>('paging');
+const upFormRef = ref<any>();
+const paging = ref<any>();
 const list = ref<unknown>([]);
-setTimeout(() => {
-    console.log(form.value?.technicalFile, 'technicalFile');
-}, 10000);
 // 控制抽屉显示状态
 const drawerVisible = ref(false);
 
@@ -222,10 +318,15 @@ const deawerData = ref<any>(null);
 function onDrawerConfirm(data: any) {
     console.log('收到基地选择数据:', data);
     deawerData.value = data;
-    form.value.baseId = data.data?.baseId;
-    // 这里可以将数据赋值给表单的相应字段
-    // 例如:form.value.plantBase = data.baseName;
-    // 可以根据需要添加其他处理逻辑
+    // 确认基地id
+    form.value.baseId = data.data[0]?.baseId;
+    //确认地块面积
+    form.value.plantingAmount = '';
+    data.data.forEach((i: any) => {
+        form.value.plantingAmount += i.area;
+    });
+    //确认养殖区域的个数
+    form.value.breedScale = data.data?.length;
 }
 // 处理Baseinfo组件的关闭事件
 function handleBaseinfoClose() {
@@ -233,7 +334,7 @@ function handleBaseinfoClose() {
 }
 const Biological = ref<any>(null);
 //随机生成
-const randomCode = () => {
+const randomCode = async () => {
     let plType = '';
     if (+form.value.taskType == 1) {
         plType = 'P';
@@ -242,12 +343,58 @@ const randomCode = () => {
     } else {
         plType = 'C';
     }
-    const code = useClientRequest.post('/plt-api/app/plantationTask/getBatchCode', { plType: plType, linkType: plType });
+    const code = await useClientRequest.post('/plt-api/app/plantationTask/getBatchCode', { plType: plType, linkType: plType });
     form.value.plantationCode = code.data;
+    console.log(code.data, 'code.data');
 };
 //完成提交表单
 const save = () => {
-    console.log(form.value);
+    uni.$u.debounce(async () => {
+        try {
+            await upFormRef.value?.validate();
+            const params = {
+                ...form.value,
+                plannedStartDate: form.value.queryType6.plannedStartDate,
+                plannedEndDate: form.value.queryType6.plannedEndDate,
+                plantingMgAmount: form.value.plant.plantingMgAmount,
+                plantingMgUnit: form.value.plant.plantingMgUnit,
+            };
+            const res = await useClientRequest.post('/plt-api/app/plantationTask/saveTask', params);
+            if (res.code == 200) {
+                uni.showToast({
+                    title: '提交成功',
+                    icon: 'success',
+                    duration: 2000,
+                });
+                setTimeout(() => {
+                    uni.navigateBack();
+                }, 1000);
+            }
+        } catch (error: any) {
+            // 滚动到第一个错误字段
+            console.log(error);
+
+            const firstErrorField = error && error[0].field + 'pppp';
+            paging.value?.scrollIntoViewById(firstErrorField, 30, true);
+            return;
+        }
+    });
+};
+
+//确认添加个体
+const handleDeleteConfirm = () => {
+    if (animalId.value) {
+        animalIds.value.push(animalId.value);
+        animalId.value = null;
+    } else {
+        uni.showToast({
+            title: '请输入个体标识号',
+            icon: 'none',
+        });
+    }
+};
+const handleDeleteCancel = () => {
+    animalId.value = null;
 };
 onLoad((options) => {
     form.value.taskType = options?.taskType;

+ 9 - 11
src/plant/port/port-create/models/baseinfo.vue

@@ -1,16 +1,14 @@
 <template>
-    <view class="border-#AFDDBB pd-26 pb-8 bg-#FBFDFB p-rtv">
+    <view class="border-#AFDDBB pd-26 pb-10 pt-10 bg-#FBFDFB p-rtv">
         <!-- 关闭按钮 -->
-        <view class="c-#F81242 f-s-30 ab2-10-20" @click="handleClose"> × </view>
-        <view class="c-#333 f-s-34 f-w-5 pt-8 pb-8 pr-16">{{ modeValue?.baseName }}</view>
-
+        <view class="c-#F81242 f-s-30 ab2-10-20" style="position: absolute; right: 10rpx; top: 0rpx" @click="handleClose"> × </view>
         <!-- 标签显示:GAP和三无一全 -->
-        <view v-if="modeValue?.gapFlag || modeValue?.swyqRes" class="pt-8 pb-8 d-flex" style="position: absolute; left: 0; top: 0">
-            <view v-if="+modeValue?.gapFlag && !+modeValue?.swyqRes" class="label mr-10">获评{{ modeValue?.medicineName }}GAP基地</view>
-            <view v-if="+modeValue?.swyqRes && !+modeValue?.gapFlag" class="label mr-10">获评{{ modeValue?.swyqVarietyName }}三无一全基地</view>
-            <view v-if="+modeValue?.gapFlag && +modeValue?.swyqRes" class="label">获评{{ modeValue?.medicineName }}GAP基地和{{ modeValue?.swyqVarietyName }}三无一全基地</view>
+        <view v-if="+modeValue?.gapFlag || +modeValue?.swyqRes" class="pt-8 pb-8 d-flex pr-20 pl-20" style="width: max-content; margin-top: -10rpx; margin-left: -26rpx; background: linear-gradient(90deg, #5eba75, #c6e391); border-bottom-right-radius: 88rpx">
+            <view v-if="+modeValue?.gapFlag && !+modeValue?.swyqRes" class="c-#fff f-s-24 f-w-6">获评{{ modeValue?.medicineName }}GAP基地</view>
+            <view v-if="+modeValue?.swyqRes && !+modeValue?.gapFlag" class="c-#fff f-s-24 f-w-6">获评{{ modeValue?.swyqVarietyName }}三无一全基地</view>
+            <view v-if="+modeValue?.gapFlag && +modeValue?.swyqRes" class="c-#fff f-s-24 f-w-6">获评{{ modeValue?.medicineName }}GAP基地和{{ modeValue?.swyqVarietyName }}三无一全基地</view>
         </view>
-
+        <view class="c-#333 f-s-34 f-w-5 pt-8 pb-8 pr-16">{{ modeValue?.baseName }}</view>
         <view class="pt-8 pb-8">
             <text class="c-#666 f-s-28">基地面积:</text>
             <text class="c-#333 f-s-28 f-w-5">{{ modeValue?.area }}{{ modeValue?.areaUnit }}</text>
@@ -23,9 +21,9 @@
         <view class="pt-16 pb-8">
             <text v-if="+baseType == 1" class="c-#666 f-s-28">地块信息:</text>
             <text v-if="+baseType == 2" class="c-#666 f-s-28">圈舍信息:</text>
-            <text v-if="+baseType == 3" class="c-#666 f-s-28">培架信息:</text>
+            <text v-if="+baseType == 3" class="c-#666 f-s-28">培架信息:</text>
             <text v-if="!modeValue?.aloneChecked" class="c-#333 f-s-28 f-w-5">{{ modeValue?.data?.length }}个</text>
-            <text v-if="modeValue?.aloneChecked" class="c-#333 f-s-28 f-w-5">该基地所有{{ baseType == '1' ? '地块' : baseType == '2' ? '圈舍' : '培架' }}</text>
+            <text v-if="modeValue?.aloneChecked" class="c-#333 f-s-28 f-w-5">该基地所有{{ baseType == '1' ? '地块' : baseType == '2' ? '圈舍' : '培架' }}</text>
         </view>
         <view v-if="!modeValue?.aloneChecked" class="pt-8 pb-8" v-for="(item, index) in modeValue?.data" :key="index">
             <text class="c-#666 f-s-28">{{ item?.landName }}:</text>

+ 1 - 0
src/plant/port/port-create/models/drawer.vue

@@ -61,6 +61,7 @@ const form = ref({
     tempFlag: 0,
     gapFlag: '',
     swyqRes: '',
+    plBaseType: props.baseType,
 });
 // 左侧基地列表数据
 const list = ref<any[]>([]);

+ 3 - 0
src/plant/storage/storage-room/detail/index.vue

@@ -0,0 +1,3 @@
+<template>
+    <view>库房详情</view>
+</template>

+ 3 - 0
src/plant/storage/storage-room/edit/index.vue

@@ -0,0 +1,3 @@
+<template>
+    <view>新增编辑库房</view>
+</template>

+ 188 - 0
src/plant/storage/storage-room/list/index.vue

@@ -0,0 +1,188 @@
+<template>
+    <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" @query="query" safe-area-inset-bottom>
+        <template #top>
+            <ut-navbar title="库房管理" :fixed="false" border></ut-navbar>
+            <view class="d-flex a-c pd-25">
+                <view class="min-w-220 flex1">
+                    <ut-action-sheet v-model="form.res" :tabs="tabs" @change="onRefresh" title="选择库房类型">
+                        <view class="d-flex search-select-item a-c">
+                            <view class="flex1 ov-hd f-s-28 c-333 text-center f-w-5 w-s-no">{{ '全部类型' }}</view>
+                            <up-icon size="24rpx" color="#333" name="arrow-down-fill" class="mr-5"></up-icon>
+                        </view>
+                    </ut-action-sheet>
+                </view>
+                <view class="h-86 pl-20 w-100%">
+                    <ut-search ref="searchRef" v-model="form.keyword" @search="onRefresh" margin="0" :border="false" :placeholder="placeholder" bgColor="#fff" height="86rpx" borderRadius="10rpx"></ut-search>
+                </view>
+            </view>
+        </template>
+        <template>
+            <template>
+                <view class="pl-25 pr-25">
+                    <up-swipe-action>
+                        <up-swipe-action-item v-for="item in list" :name="item?.id" :key="item?.id" :disabled="item?.res !== '2'" :options="optionsAction" @click="clickSwipe" class="mb-20 b-radius">
+                            <view @click.stop="clickItem(item)" class="b-radius bg-#fff pd-20 p-rtv">
+                                <view class="d-flex">
+                                    <view class="flex1 ov-hd mr-20 f-s-34 c-#333 f-w-500">{{ item?.warehouseName }}</view>
+                                    <view class="f-s-24 c-#666">{{ item?.createTime }}创建</view>
+                                </view>
+                                <view class="f-s-24 c-#666 mb-10">{{ item?.sn }}</view>
+                                <view class="f-s-28 pd2-5-0">
+                                    <span class="c-#666">库房类型:</span>
+                                    <span class="c-#333 f-w-600">农资库</span>
+                                </view>
+                                <view class="f-s-28 pd2-5-0">
+                                    <span class="c-#666">负责人:</span>
+                                    <span class="c-#333 f-w-600">{{ item?.contactName }}</span>
+                                </view> 
+                                <view class="f-s-28 pd2-5-0">
+                                    <span class="c-#666">所在位置:</span>
+                                    <span class="c-#333 f-w-600">{{ item?.address }}</span>
+                                </view>
+                                <view class="f-s-28 pd2-5-0">
+                                    <span class="c-#666">货位数量:</span>
+                                    <span class="c-#333 f-w-600">{{ item?.shelvesCount }}</span>
+                                </view>
+                            </view>
+                        </up-swipe-action-item>
+                    </up-swipe-action>
+                </view>
+            </template>
+            <!-- 空数据处理 -->
+
+            <template #empty v-if="address">
+                <ut-empty class="mg-at" size="28rpx" color="#999" padding="10rpx" image="/static/images/plant/noEmptyBase.png">暂无获评GAP基地信息~</ut-empty>
+                <view class="d-flex j-c f-s-28 c-#ccc">如需认定GAP基地,可前往数字云药官网进行申报</view>
+                <view class="d-flex j-c f-s-28 c-primary pd-15">https://www.shuziyunyao.com/</view>
+                <up-button type="primary" class="b-radius" style="width: 340rpx" @click="copyText('https://www.shuziyunyao.com/')">复制网址</up-button>
+            </template>
+        </template>
+        <template #empty v-if="!address">
+            <ut-empty class="mg-at" size="28rpx" color="#999" padding="10rpx" image="/static/images/plant/noEmptyBase.png">非云南省内企业,无法获取已获评的GAP基地信息~</ut-empty>
+            <view class="d-flex j-c f-s-28 c-#ccc">可点击底部按钮上传佐证材料添加获评信息</view>
+        </template>
+        <template #bottom v-if="!address">
+            <view class="base-bottom-wrap pd-20 pb-0">
+                <up-button type="primary" @click="$u.route({ url: '/plant/base/gap-base-info-edit/index' })">
+                    <img class="w-38 h-36 mr-10" src="/static/images/plant/chooseGAP.png" alt="" mode="widthFix" />
+                    <text>添加GAP基地信息</text>
+                </up-button>
+            </view>
+        </template>
+    </z-paging>
+    <ut-suspension :imageWidth="60" :imageHeight="60" :x="sus?.left" :y="sus?.bottom" :inertia="false" :snap-threshold="40">
+        <image src="/static/images/plant/addBase.png" mode="widthFix" class="w-120 h-120"></image>
+    </ut-suspension>
+</template>
+<script setup lang="ts">
+import { copyText } from '@/utils/public';
+import { useClientRequest } from '@/utils/request';
+import { useInfoStore } from '@/store';
+const paging = ref();
+const list = ref<any[]>([]);
+const placeholder = ref('搜库房名称、编号、负责人');
+const tabs = ref([
+    { label: '全部', value: '' },
+    { label: '有效', value: '1' },
+    { label: '审核不通过', value: '2' },
+    { label: '待审核', value: '0' },
+]);
+// 判断是否是云南的企业
+const isYunnanCompany = (): boolean => {
+    const adcdCode = useInfoStore().companyInfo?.adcdCode;
+    return adcdCode?.startsWith('53') || false;
+};
+const address = computed(() => isYunnanCompany());
+const form = ref({
+    keyword: '',
+    res: '',
+});
+
+const query = async (pageNum: number, pageSize: number) => {
+    const params = {
+        pageNum,
+        pageSize,
+        ...form.value,
+    };
+    const res = await useClientRequest.get<any>('/plt-api/app/warehouse/pageList', params);
+    if (!res || res.code !== 200) return;
+    const { rows } = res;
+    paging.value.complete(rows);
+};
+const onRefresh = () => {
+    paging.value.reload();
+};
+const optionsAction = reactive([
+    {
+        text: '删除',
+        style: {
+            backgroundColor: '#f56c6c',
+        },
+    },
+]);
+const clickSwipe = async (event: object) => {
+    const { name, index } = event as any;
+    if (index === 0) {
+        // 删除
+        const res = await uni.showModal({
+            title: '提示',
+            content: '确定删除该GAP基地信息吗?',
+        });
+        console.log(res);
+
+        if (res.confirm) {
+            const delRes = await useClientRequest.get(`/plt-api/app/gapCertificationInfo/delById/${name}`);
+            if (delRes && delRes.code === 200) {
+                uni.showToast({ title: '删除成功', icon: 'none' });
+                onRefresh();
+            }
+        }
+    }
+};
+const clickItem = (item: any) => {
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/base/gap-base-info-detail/index',
+        params: {
+            id: item?.id,
+        },
+    });
+};
+onMounted(() => {
+    uni.$on('gapBaseInfoUpdated', () => {
+        onRefresh();
+    });
+});
+</script>
+<style lang="scss" scoped>
+// @import '@/assets/styles/theme.scss';
+.search-select-item {
+    height: 86rpx;
+    background-color: #fff;
+    border-radius: 10rpx;
+    box-sizing: border-box;
+    padding-left: 16rpx;
+    padding-right: 16rpx;
+    padding-top: 14rpx;
+    padding-bottom: 14rpx;
+}
+.u-page {
+    padding: 0;
+}
+
+.u-demo-block__title {
+    padding: 10px 0 2px 15px;
+}
+
+.swipe-action {
+    &__content {
+        padding: 25rpx 0;
+
+        &__text {
+            font-size: 15px;
+            color: $u-main-color;
+            padding-left: 30rpx;
+        }
+    }
+}
+</style>

BIN
src/static/images/plant/storage/nav_cpk_icon.png


BIN
src/static/images/plant/storage/nav_kfgl_icon.png


BIN
src/static/images/plant/storage/nav_nzk_icon.png


BIN
src/static/images/plant/storage/nav_xhk_icon.png


BIN
src/static/images/plant/storage/nav_zjpk_icon.png


BIN
src/static/images/plant/storage/nav_zyk_icon.png


+ 39 - 8
src/tools/select-gap-info/index.vue

@@ -2,12 +2,13 @@
     <z-paging ref="paging" safe-area-inset-bottom v-model="list" @query="query">
         <template #top>
             <ut-navbar leftText="请选择GAP基地获评信息" :fixed="false"></ut-navbar>
-            <view class="pd-20">
-                <ut-search margin="0" height="68rpx" fontSize="26rpx" placeholder="搜基地名称、品种、基地地址" :border="false" v-model="form.keyword" @search="onRefresh"></ut-search>
+            <view ref="baseRef" class="pd-24" id="base12345">
+                <view class="startline-title mb-6">请选择GAP基地获评信息</view>
+                <view class="f-s-26 c-#999">未通过审核及待审核的GAP获评信息将不会在此展示</view>
             </view>
         </template>
         <view class="base-content pd-20">
-            <view :class="{ active: item.id === checkedId }" v-for="(item, index) in list" :key="item.id" @click="clickItem(item)" class="b-radius bg-#fff pd-20 p-rtv">
+            <view :class="{ active: item.id === checkedId }" v-for="(item, index) in list" :key="item.id" @click="clickItem(item)" class="b-radius bg-#fff pd-20 p-rtv select-item-card mb-20">
                 <view class="c-#333 f-s-34 f-w-5 pb-5">{{ item?.gapBaseName }}</view>
                 <view class="c-#999 f-s-24 pb-20">{{ item?.ratedDate }}获评</view>
                 <view class="d-flex pb-5">
@@ -22,7 +23,7 @@
                 </view>
                 <view class="pb-20">
                     <text class="c-#666 f-s-28">基地地址:</text>
-                    <text class="c-#333 f-s-28 f-w-5">{{ item?.address }}</text>
+                    <text class="c-#333 f-s-28 f-w-5">{{ item?.adcdName || '' }}{{ item?.address || '' }}</text>
                 </view>
                 <view v-if="+item?.res == 2" class="pl-5 pr-5 pt-20 pb-20 border-top-#f7f7f7 c-#FC333F">
                     <text class="f-s-28">审核不通过原因:</text>
@@ -31,8 +32,19 @@
                 <image v-if="+item?.res == 2" class="w-145" src="/static/images/plant/resFailed.png" style="position: absolute; top: 0; right: 0" mode="widthFix" />
                 <image v-if="+item?.res == 0" class="w-100" src="/static/images/plant/resPendingReview.png" style="position: absolute; top: 0; right: 0" mode="widthFix" />
                 <image v-if="+item?.res == 1" class="w-90" src="/static/images/plant/resEffective.png" style="position: absolute; top: 0; right: 0" mode="widthFix" />
+                <image v-if="item.id === checkedId" class="w-40 h-40 checked-icon" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-lm/price/checked1.png" mode="widthFix" />
             </view>
         </view>
+
+            <template #empty >
+                <ut-empty class="mg-at" size="28rpx" color="#999" padding="10rpx" image="/static/images/plant/noEmptyBase.png">暂无获评GAP基地信息~</ut-empty>
+                <view class="f-s-28 c-#ccc w-600 text-center">如已获评GAP信息,请前往<span class="c-primary">基地-GAP基地获评信息</span>添加后再来选择若未获评GAP基地,可前往各地官方渠道进行GAP基地申报</view>
+            </template>
+        <template #bottom>
+            <view class="pd-20 d-flex">
+                <up-button type="primary" @click="confirmSelect">确认选择</up-button>
+            </view>
+        </template>
     </z-paging>
 </template>
 <script setup lang="ts">
@@ -48,7 +60,7 @@ const query = async (pageNum: number, pageSize: number) => {
     const res = await useClientRequest.get('/plt-api/app/gapCertificationInfo/pageList', {
         ...form.value,
         pageNum: pageNum,
-        pageSize: pageSize,
+        pageSize: 1000,
     });
     if (res.code == 200) {
         paging.value.complete(res.rows || []);
@@ -57,8 +69,19 @@ const query = async (pageNum: number, pageSize: number) => {
 const checkedId = ref(null);
 const clickItem = (item: any) => {
     checkedId.value = item.id;
-    uni.$emit('selectGapInfo', item);
-    uni.navigateBack();
+};
+// 确认选择
+const confirmSelect = () => {
+    const selectedItem = list.value.find(item => item.id === checkedId.value);
+    if (selectedItem) {
+        uni.$emit('selectGapInfo', selectedItem);
+        uni.navigateBack();
+    } else {
+        uni.showToast({
+            title: '请选择一项GAP基地获评信息',
+            icon: 'none'
+        });
+    }
 };
 const onRefresh = () => {
     try {
@@ -74,9 +97,17 @@ onLoad((options: any) => {
 </script>
 <style lang="scss" scoped>
 .select-item-card {
+    border: 1rpx solid #fff;
     border-radius: 16rpx;
+    overflow: hidden;
+    .checked-icon {
+        position: absolute;
+        right: 0;
+        bottom: 0;
+    }
     &.active {
-        border-color: #4456fb;
+        border-color: $u-primary;
+        background-color: #EBF6EE;
     }
 }
 </style>