lisy hace 2 semanas
padre
commit
fa886b389c

+ 7 - 0
package-lock.json

@@ -27,6 +27,7 @@
                 "@uni-helper/vite-plugin-uni-components": "^0.2.3",
                 "clipboard": "^2.0.11",
                 "dayjs": "^1.11.13",
+                "number-precision": "^1.6.0",
                 "pinia": "^2.0.36",
                 "pinia-plugin-persistedstate": "^4.7.1",
                 "rollup-plugin-visualizer": "^6.0.3",
@@ -7864,6 +7865,12 @@
                 "node": ">=8"
             }
         },
+        "node_modules/number-precision": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmmirror.com/number-precision/-/number-precision-1.6.0.tgz",
+            "integrity": "sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==",
+            "license": "MIT"
+        },
         "node_modules/object-inspect": {
             "version": "1.13.4",
             "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz",

+ 1 - 0
package.json

@@ -56,6 +56,7 @@
         "@uni-helper/vite-plugin-uni-components": "^0.2.3",
         "clipboard": "^2.0.11",
         "dayjs": "^1.11.13",
+        "number-precision": "^1.6.0",
         "pinia": "^2.0.36",
         "pinia-plugin-persistedstate": "^4.7.1",
         "rollup-plugin-visualizer": "^6.0.3",

+ 1 - 0
src/assets/styles/uview-plus.scss

@@ -47,6 +47,7 @@ uni-button::after{
 
 .paging-btm-shadow {
     .zp-page-bottom-container {
+        position: relative;
         box-shadow: 0px 0px 6rpx 0px #AECEBF;
     }
 }

+ 101 - 43
src/plant/packaging/create/index.vue

@@ -1,13 +1,19 @@
 <template>
-    <z-paging ref="paging" bgColor="#fff" safe-area-inset-bottom paging-class="paging-btm-shadow" scroll-with-animation>
+    <z-paging ref="paging" bgColor="#f7f7f7" safe-area-inset-bottom scroll-with-animation>
         <template #top>
-            <ut-navbar :title="did ? '编辑包装任务' : '创建包装任务'" :fixed="false" border></ut-navbar>
+            <ut-navbar :title="'创建包装任务'" :fixed="false" border></ut-navbar>
         </template>
-        <up-form class="p-rtv" labelPosition="top" :model="form" :rules="rules" labelWidth="auto" ref="upFormRef">
+        <up-form class="p-rtv bg-#fff" labelPosition="top" :model="form" :rules="rules" labelWidth="auto" ref="upFormRef">
             <view class="pd-24 bg-#fff mb-10">
                 <view class="h-1" id="inputStorageIdpppp"></view>
                 <up-form-item borderBottom label="选择包装对象" prop="inputStorageId" required>
-                     
+                    <view class="flex1">
+                        <up-button v-if="!form.inputStorageId" @click="selectStorage" type="primary" plain>
+                            <image class="w-36 h-36 mr-10" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/common/select_push_icon.png" mode="widthFix" />
+                            <span>请选择您要包装的对象</span>
+                        </up-button>
+                        <view v-else class="bg-#FBFDFB card-info-block pd-24 p-rtv"> </view>
+                    </view>
                 </up-form-item>
                 <view class="h-1" id="storageUseAmountpppp"></view>
                 <up-form-item borderBottom label="本次包装用量" prop="storageUseAmount" required>
@@ -46,10 +52,10 @@
                 </up-form-item>
                 <view class="h-1" id="packagingDateStartpppp"></view>
                 <view class="h-1" id="packagingDateEndpppp"></view>
-                <up-form-item prop="packagingDateStart" required label="包装日期" class="form-item-bottom-padding-0">
+                <up-form-item required label="包装日期" class="form-item-bottom-padding-0">
                     <view class="flex1 d-flex">
                         <view class="flex1">
-                            <ut-datetime-picker v-model="form.packagingDateStart" :maxDate="form.packagingDateEnd || new Date()" mode="date">
+                            <ut-datetime-picker v-model="form.packagingDateStart" :maxDate="form.packagingDateEnd" mode="date">
                                 <up-form-item borderBottom prop="packagingDateStart" class="form-item-top-padding-0">
                                     <up-input v-model="form.packagingDateStart" readonly placeholder="包装开始日期" border="none" clearable></up-input>
                                     <template #right>
@@ -60,7 +66,7 @@
                         </view>
                         <view class="pd2-0-20"></view>
                         <view class="flex1">
-                            <ut-datetime-picker v-model="form.packagingDateEnd" :minDate="form.packagingDateStart" :maxDate="new Date()" mode="date">
+                            <ut-datetime-picker v-model="form.packagingDateEnd" :minDate="form.packagingDateStart" mode="date">
                                 <up-form-item borderBottom prop="packagingDateEnd" class="form-item-top-padding-0">
                                     <up-input v-model="form.packagingDateEnd" readonly placeholder="包装结束日期" border="none" clearable></up-input>
                                     <template #right>
@@ -107,10 +113,10 @@
                     </div>
                 </up-form-item>
                 <!-- 请选择赋码方式 -->
-                <view class="h-1" id="packCodeTypepppp"></view>
-                <ut-action-sheet v-model="form.packCodeType" :tabs="pt_pack_code_type" mode="custom" title="请选择赋码方式">
-                    <up-form-item borderBottom label="赋码方式" required prop="packCodeType">
-                        <view v-if="form.packCodeType" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(pt_pack_code_type, form.packCodeType) }}</view>
+                <view class="h-1" id="refTypepppp"></view>
+                <ut-action-sheet v-model="form.refType" :tabs="pt_pack_ref_type" mode="custom" title="请选择赋码方式">
+                    <up-form-item borderBottom label="赋码方式" required prop="refType">
+                        <view v-if="form.refType" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(pt_pack_ref_type, form.refType) }}</view>
                         <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择赋码方式</view>
                         <template #right>
                             <up-icon size="22rpx" color="#37A954" name="arrow-down-fill"></up-icon>
@@ -123,26 +129,32 @@
                 </view>
             </view>
         </up-form>
-        <template #bottom>
-            <view class="pd-20">
-                <up-button type="primary" @click="submit">
-                    <text>{{ did ? '保存' : '提交' }}</text>
-                </up-button>
+        <view class="d-flex flex-cln a-c pd3-40-24-24">
+            <view class="f-s-30 c-#333 f-w-5 mb-16">
+                <span>预计分包数:</span>
+                <span class="f-s-46 c-primary f-w-7">{{ packResult.packNum || '-' }}</span>
+                <span>包</span>
             </view>
-        </template>
+            <view class="d-flex a-c mb-30">
+                <view class="f-s-28 c-#333">包装规格:</view>
+                <view class="d-flex a-c gap-24">
+                    <view class="bg-#E3EFE6 pd2-12-28 c-primary radius-8 f-s-26">{{ packResult.spec1 || '-' }}</view>
+                    <view v-if="packResult.spec2" class="bg-#E3EFE6 pd2-12-28 c-primary radius-8 f-s-26">{{ packResult.spec2 || '-' }}</view>
+                </view>
+            </view>
+            <up-button type="primary" @click="submit">立即分包</up-button>
+        </view>
     </z-paging>
 </template>
 <script setup lang="ts">
 import { useClientRequest } from '@/utils/request';
 import { formItemBtnStyle } from '@/assets/styles/uview-plus';
 import type { PackTaskForm } from './types';
-
+import NP from 'number-precision';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { pt_pack_code_type, pt_pack_spec_unit, pt_expire_date_unit } = toRefs<any>(proxy?.useDict('pt_pack_code_type', 'pt_pack_spec_unit', 'pt_expire_date_unit'));
+const { pt_pack_ref_type, pt_pack_spec_unit, pt_expire_date_unit } = toRefs<any>(proxy?.useDict('pt_pack_ref_type', 'pt_pack_spec_unit', 'pt_expire_date_unit'));
 const upFormRef = ref();
 const paging = ref();
-const did = ref<string>('');
-
 const form = ref<PackTaskForm>({
     storageUseAmount: '',
     stroeUnit: 'kg',
@@ -154,7 +166,8 @@ const form = ref<PackTaskForm>({
     batchSn: '',
     expireDate: '',
     expireDateUnit: '',
-    packCodeType: '',
+    refType: '',
+    packCodeType: '1',
 });
 
 const rules = reactive<Record<string, any>>({
@@ -166,6 +179,10 @@ const rules = reactive<Record<string, any>>({
                 const num = Number(value);
                 if (Number.isNaN(num)) return Promise.reject('本次包装用量请输入数字');
                 if (num <= 0) return Promise.reject('本次包装用量需大于0');
+                // 本次包装用量不能大于剩余可用量
+                if (form.value.stroeObject && num > form.value.stroeObject.restAmount) {
+                    return Promise.reject(`本次包装用量不能大于剩余量${form.value.stroeObject.restAmount}${form.value.stroeUnit}`);
+                }
                 return Promise.resolve();
             },
         },
@@ -178,6 +195,10 @@ const rules = reactive<Record<string, any>>({
                 const num = Number(value);
                 if (Number.isNaN(num)) return Promise.reject('包装规格请输入数字');
                 if (num <= 0) return Promise.reject('包装规格需大于0');
+                // 包装规格不能大于本次包装用量
+                if (form.value.storageUseAmount && num > Number(form.value.storageUseAmount)) {
+                    return Promise.reject('包装规格不能大于本次包装用量');
+                }
                 return Promise.resolve();
             },
         },
@@ -190,18 +211,9 @@ const rules = reactive<Record<string, any>>({
     batchSn: [{ required: true, message: '请输入成品批号' }],
     expireDate: [{ required: true, message: '请输入保质期' }],
     expireDateUnit: [{ required: true, message: '请选择保质期单位' }],
-    packCodeType: [{ required: true, message: '请选择赋码方式' }],
+    refType: [{ required: true, message: '请选择赋码方式' }],
 });
 
-const loadDetail = async (id: string) => {
-    if (!id) return;
-    const res = await useClientRequest.get(`/plt-api/app/packTask/getInfo/${id}`);
-    if (res && res.code === 200) {
-        const data = res.data || {};
-        console.log(data);
-    }
-};
-
 const submit = async () => {
     try {
         await upFormRef.value?.validate();
@@ -212,17 +224,17 @@ const submit = async () => {
     }
 
     try {
-        await uni.showLoading({ title: did.value ? '保存中...' : '提交中...', mask: true });
-        const url = did.value ? '/plt-api/app/packTask/edit' : '/plt-api/app/packTask/save';
-        const payload: any = { ...(form.value as any) };
-        if (did.value) payload.id = did.value;
-        const res = await useClientRequest.post(url, payload);
+        await uni.showLoading({ title: '分包中...', mask: true });
+        const payload: any = { ...(form.value as any), planCount: packResult.value.packNum };
+        delete payload.stroeObject;
+        const res = await useClientRequest.post('/plt-api/app/packTask/save', payload);
         uni.hideLoading();
         if (res && res.code === 200) {
-            uni.showToast({ title: did.value ? '保存成功' : '新增成功', icon: 'success' });
-            uni.$emit('refreshContactUnitDetail');
-            uni.$emit('refreshContactUnitList');
-            setTimeout(() => uni.navigateBack(), 300);
+            uni.showToast({ title: '操作成功', icon: 'success' });
+            uni.$emit('refreshPackTaskList');
+            setTimeout(() => uni.navigateBack({
+                delta: 1,
+            }), 300);
         }
     } catch (e) {
         uni.hideLoading();
@@ -247,10 +259,56 @@ const generateBatchCode = async () => {
         });
     }
 };
-const confirmArea = (area: any) => {
-    form.value.adcdCodeName = area.fullName;
+// 去选择包装对象页选择包装对象,选择后返回并赋值
+const selectStorage = () => {
+    uni.$on('selectStorageObject', (data: any) => {
+        console.log(data, '---');
+        form.value.inputStorageId = data.id;
+        form.value.packTaskType = data.storageType;
+        form.value.stroeUnit = data.unit;
+        form.value.storageUseAmount = '';
+        form.value.capacity = '';
+        form.value.stroeObject = data;
+        uni.$off('selectStorageObject');
+    });
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/packaging/select-object/index',
+        params: {
+            emitField: 'selectStorageObject',
+            storageType: form.value.packTaskType, // 传入当前选择的包装对象类型,种子、苗木、农资等
+            id: form.value.inputStorageId, // 传入当前选择的包装对象id,编辑时使用,用于回显选中状态
+        },
+    });
 };
+// 计算属性分包结果
+const packResult = computed(() => {
+    // 预计分包数 = 本次包装用量 / 包装规格,向上取整
+    // 分包数,包装规格,整除的情况,直接除;不整除的情况,向上取整
+    // 包装规格,整除的时候包装规格只有一个,不整除包装规格有两个,第二个是剩余量
+    const result: any = {
+        packNum: 0,
+        spec1: '',
+        // 零包规格
+        spec2: '',
 
+    };
+    if (form.value.storageUseAmount && form.value.capacity) {
+        const useAmount = Number(form.value.storageUseAmount);
+        const capacity = Number(form.value.capacity);
+        if (capacity > 0) {
+            result.packNum = Math.ceil(useAmount / capacity);
+            result.spec1 = `${capacity}${form.value.stroeUnit}/${form.value.unit}`;
+            if (useAmount % capacity !== 0) {
+                const lastAmount = NP.round(useAmount - capacity * Math.floor(useAmount / capacity), 2);
+                result.spec2 = `${lastAmount}${form.value.stroeUnit}/${form.value.unit}`; // 零包规格
+            } else {
+                result.spec2 = ''; // 没有零包规格
+            }
+        }
+    }
+    return result;
+});
 onLoad((options: any) => {});
 </script>
 <style lang="scss" scoped></style>

+ 1 - 1
src/plant/packaging/list/index.vue

@@ -110,7 +110,7 @@ const onRefresh = () => {
     paging.value.reload();
 };
 onMounted(() => {
-    uni.$on('refreshStorageRoomList', () => {
+    uni.$on('refreshPackTaskList', () => {
         onRefresh();
     });
 });

+ 84 - 2
src/plant/packaging/select-object/index.vue

@@ -1,3 +1,85 @@
 <template>
-    <view>xx</view>
-</template>
+    <z-paging-swiper>
+        <!-- 需要固定在顶部不滚动的view放在slot="top"的view中 -->
+        <!-- 注意!此处的z-tabs为独立的组件,可替换为第三方的tabs,若需要使用z-tabs,请在插件市场搜索z-tabs并引入,否则会报插件找不到的错误 -->
+        <template #top>
+            <ut-navbar title="请选择包装对象" :fixed="false" border :breadcrumb="false"></ut-navbar>
+            <view class="pd3-16-24-0 bg-#fff">
+                <ut-tabs :tabs="tabs" v-model="viewType" mode="btw"></ut-tabs>
+            </view>
+        </template>
+        <view class="swiper-content d-flex flex-cln">
+            <!-- swiper必须设置height:100%,因为swiper有默认的高度,只有设置高度100%才可以铺满页面  -->
+            <swiper class="flex1 ov-hd" :current="viewType" @transition="swiperTransition" @animationfinish="swiperAnimationfinish">
+                <swiper-item class="swiper-item">
+                    <select-medicine-list :checkedId="checkedId" @clickItem="clickItem" @confirm="confirmSelection" />
+                </swiper-item>
+                <swiper-item class="swiper-item">
+                    <select-fresh-list :checkedId="checkedId" @clickItem="clickItem" @confirm="confirmSelection" />
+                </swiper-item>
+                <swiper-item class="swiper-item">
+                    <select-seed-source-list :checkedId="checkedId" @clickItem="clickItem" @confirm="confirmSelection" />
+                </swiper-item>
+            </swiper>
+        </view>
+    </z-paging-swiper>
+</template>
+<script setup lang="ts">
+import { ref, onMounted, getCurrentInstance, type ComponentInternalInstance } from 'vue';
+import { setCipByNum } from '@/utils/public';
+
+import SelectMedicineList from './models/select-medicine-list.vue';
+import SelectFreshList from './models/select-fresh-list.vue';
+import SelectSeedSourceList from './models/select-seed-source-list.vue';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+// 证书文件类型
+const tabs = ref([
+    { label: '从药材库选择', value: '0' },
+    { label: '从鲜货库选择', value: '1' },
+    { label: '从种源库选择', value: '2' },
+]);
+
+const viewType = ref('0');
+const swiperTransition = (e: any) => {};
+const swiperAnimationfinish = (e: any) => {
+    viewType.value = e.detail.current.toString();
+};
+const checkedId = ref<string>('');
+const checkedInfo = ref<any>(null);
+const clickItem = (item: any) => {
+    console.log('点击了item', item);
+    checkedInfo.value = item;
+    checkedId.value = item.id + '-' + item.storageType;
+};
+const confirmSelection = () => {
+    console.log('确认选择', checkedInfo.value, opts.value?.emitField);
+    
+    uni.$emit(opts.value?.emitField, checkedInfo.value);
+    uni.navigateBack({
+        delta: 1,
+    });
+};
+const opts = ref<{ emitField: string, storageType: string, id: string }>({ emitField: 'selectStorageObject', storageType: '', id: '' });
+onLoad((options: any) => {
+    const { storageType, id } = options;
+    opts.value = options;
+    if (storageType && id) {
+        checkedId.value = id + '-' + storageType;
+        // 根据storageType设置对应的tab
+        if (storageType === '4') {
+            viewType.value = '1';
+        } else if (storageType === '5') {
+            viewType.value = '0';
+        } else {
+            viewType.value = '2';
+        }
+    }
+});
+</script>
+<style lang="scss" scoped>
+.swiper-content {
+    height: 100%;
+    overflow: hidden;
+}
+</style>

+ 176 - 0
src/plant/packaging/select-object/models/select-fresh-list.vue

@@ -0,0 +1,176 @@
+<template>
+    <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" @query="query" safe-area-inset-bottom bottom-bg-color="#fff" paging-class="paging-btm-shadow" hide-no-more-inside>
+        <view class="pd3-24-24-0">
+            <view class="d-flex a-c">
+                <view class="min-w-230 flex1">
+                    <ut-action-sheet v-model="form.instoreType" :tabs="tabs_pt_fresh_instore_type" mode="custom" @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">{{ selectDictLabel(pt_fresh_instore_type, form.instoreType) || '全部' }} </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="changeSeach" margin="0" :border="false" placeholder="搜名称、批号、库房、供应商" bgColor="#fff" height="86rpx" borderRadius="10rpx"></ut-search>
+                </view>
+            </view>
+            <view></view>
+        </view>
+        <view class="pd-24 bg-#f7f7f7">
+            <template v-for="(item, index) in list" :key="index">
+                <view class="b-radius bg-#fff pd-20 p-rtv mb-20 select-item-list" :class="{ 'active': item.id + '-' + item.storageType === checkedId }" @click="emit('clickItem', item)">
+                    <view class="d-flex j-sb a-c li-item-head mb-16">
+                        <view class="li-left-tag" :class="{ [`bg-instore-${item?.instoreType}`]: true }">{{ selectDictLabel(pt_fresh_instore_type, item?.instoreType) }}</view>
+                        <view class="f-s-22 c-#666">{{ item?.instoreBizInfo?.instoreDate }}</view>
+                    </view>
+                    <view class="d-flex flex1 mb-10">
+                        <view class="flex1">
+                            <span class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.variety }}</span>
+                            <span v-if="item?.partName" class="f-s-24 c-#666">{{ item?.level || '' }}{{ item?.partName }}</span>
+                        </view>
+                        <view>
+                            <view v-if="item?.examinReport?.length" class="tag-span c-primary bg-#EBF6EE">已检验</view>
+                            <view v-else class="tag-span c-danger bg-#F9ECEA">未检验</view>
+                        </view>
+                    </view>
+                    <template v-if="item?.instoreType == '2'">
+                        <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">入库批号:</span>
+                            <span class="c-#333 f-w-500">{{ item?.batchCode || '-' }}</span>
+                        </view>
+                        <view v-if="item?.supplierId" class="pd2-4-0 f-s-28">
+                            <span class="c-#666">供应商:</span>
+                            <span class="c-#333 f-w-500">{{ item?.supplierInfo?.cusName || '-' }}</span>
+                        </view>
+                    </template>
+                    <template v-if="item?.instoreType == '3'">
+                        <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">采收批号:</span>
+                            <span class="c-#333 f-w-500">{{ item?.harvestInfo?.harvestCode || '-' }}</span>
+                        </view>
+                        <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">采收基地:</span>
+                            <span class="c-#333 f-w-500">
+                                {{ item?.harvestInfo?.baseInfo?.baseName || '-' }}
+                            </span>
+                        </view>
+                    </template>
+
+                    <view v-if="item?.warehouses?.length" class="pd2-4-0 f-s-28">
+                        <span class="c-#666">存放库房:</span>
+                        <span class="c-#333 f-w-500">{{ getStorageRoomNames(item?.warehouses) || '-' }}</span>
+                    </view>
+                    <view class="pd2-4-0 f-s-28">
+                        <span class="c-#666">入库量:</span>
+                        <span class="c-#333 f-w-500">{{ item?.capacity }}{{ item?.unit }}</span>
+                    </view>
+                    <view class="d-flex">
+                        <view v-if="item?.inputAmount" class="pd2-4-0 f-s-28 flex1">
+                            <span class="c-#666">出库量:</span>
+                            <span class="c-#333 f-w-500">{{ item?.inputAmount || '0' }}{{ item?.unit }}</span>
+                        </view>
+                        <view v-if="item?.restAmount" class="pd2-4-0 f-s-28 flex1">
+                            <span class="c-danger">剩余量:</span>
+                            <span class="c-danger f-w-500">{{ item?.restAmount || '0' }}{{ item?.unit }}</span>
+                        </view>
+                    </view>
+                     <image v-if="item.id + '-' + item.storageType === checkedId" class="w-40 h-40 checked-icon" src="/static/images/common/btn_checked_icon.png" mode="widthFix" />
+                </view>
+            </template>
+        </view>
+
+        <template #empty>
+            <view class="d-flex flex-cln a-c" style="margin-top: -200rpx">
+                <ut-empty class="mg-at" color="#ccc" size="28rpx">暂无鲜货信息,点击下方+号新增吧</ut-empty>
+            </view>
+        </template>
+        <template #bottom>
+            <view class="pd-24">
+                <up-button @click="emit('confirm')" type="primary">确认选择</up-button>
+            </view>
+        </template>
+    </z-paging>
+</template>
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+import { getStorageRoomNames } from '@/utils/common';
+const props = defineProps({
+    checkedId: {
+        type: String,
+        default: '',
+    },
+});
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_fresh_instore_type } = toRefs<any>(proxy?.useDict('pt_fresh_instore_type'));
+const list = ref<any[]>();
+const form = ref({ keyword: '', restFlag: '1', instoreType: '', storageType: '4' });
+const paging = ref();
+const tabs_pt_fresh_instore_type = computed(() => {
+    return [{ label: '全部', value: '' }, ...pt_fresh_instore_type.value].filter((item: any) => item.value != '4');
+});
+const emit = defineEmits(['clickItem', 'confirm']);
+const changeSeach = () => {
+    paging.value.reload();
+};
+const query = async (pageNum: number, pageSize: number) => {
+    const params = {
+        pageNum,
+        pageSize,
+        ...form.value,
+    };
+    const res = await useClientRequest.get('/plt-api/app/storage/list', params);
+    if (res) {
+        const { rows } = res;
+        paging.value.complete(rows);
+    }
+};
+const onRefresh = () => {
+    try {
+        paging.value?.reload();
+    } catch (error) {
+        console.error('刷新列表失败:', error);
+    }
+};
+onMounted(() => {
+    uni.$on('refreshStorageRoomList', () => {
+        onRefresh();
+    });
+});
+</script>
+<style lang="scss" scoped>
+.search-select-item {
+    height: 86rpx;
+    background-color: #fff;
+    border-radius: 10rpx;
+    box-sizing: border-box;
+    padding: 12rpx;
+}
+.tag-span {
+    padding: 4rpx 12rpx;
+    font-size: 20rpx;
+    border-radius: 18rpx;
+}
+.li-item-head {
+    margin-left: -24rpx;
+    margin-top: -24rpx;
+}
+.li-left-tag {
+    padding: 6rpx 16rpx;
+    color: #fff;
+    border-radius: 16rpx 0 16rpx 0;
+    font-size: 20rpx;
+    font-weight: 500;
+}
+.select-item-list {
+    border: 1rpx solid #fff;
+    &.active {
+        background-color: #ebf6ee;
+        border: 1rpx solid $u-primary;
+    }
+    .checked-icon {
+        position: absolute;
+        right: 0rpx;
+        bottom: 0rpx;
+    }
+}
+</style>

+ 154 - 0
src/plant/packaging/select-object/models/select-medicine-list.vue

@@ -0,0 +1,154 @@
+<template>
+    <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" safe-area-inset-bottom bottom-bg-color="#fff" paging-class="paging-btm-shadow" @query="query">
+        <view class="pd3-24-24-0">
+            <view class="d-flex a-c">
+                <view class="min-w-230 flex1">
+                    <ut-action-sheet v-model="form.processType" :tabs="[{ label: '全部', value: '' }, ...st_medicine_process_type]" mode="custom" @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">{{ selectDictLabel(st_medicine_process_type, form.processType) || '全部' }} </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="changeSeach" margin="0" :border="false" placeholder="搜动植物名称、品种、批号" bgColor="#fff" height="86rpx" borderRadius="10rpx"></ut-search>
+                </view>
+            </view>
+        </view>
+        <view class="pd-24 bg-#f7f7f7">
+            <template v-for="(item, index) in list" :key="index">
+                <view class="b-radius bg-#fff pd-20 p-rtv mb-20 select-item-list" :class="{ active: item.id + '-' + item.storageType === checkedId }" @click="emit('clickItem', item)">
+                    <view class="d-flex j-sb a-c li-item-head mb-16">
+                        <view class="li-left-tag" :class="{ [`bg-instore-${item?.instoreBizInfo?.processType}`]: true }">{{ item?.seedLevel || '' }}{{ selectDictLabel(st_medicine_process_type, item?.instoreBizInfo?.processType) }}</view>
+                        <view class="f-s-22 c-#666">{{ item?.instoreBizInfo?.instoreDate }}</view>
+                    </view>
+                    <view class="d-flex flex1 mb-10">
+                        <view class="flex1">
+                            <span class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.variety }}</span>
+                            <span v-if="item?.partName" class="f-s-24 c-#666">{{ item?.partName }}</span>
+                        </view>
+                        <view>
+                            <view v-if="item?.examinReport?.length" class="tag-span c-primary bg-#EBF6EE">已检验</view>
+                            <view v-else class="tag-span c-danger bg-#F9ECEA">未检验</view>
+                        </view>
+                    </view>
+                    <view class="pd2-4-0 f-s-28">
+                        <span class="c-#666">生产批号:</span>
+                        <span class="c-#333 f-w-500">{{ item?.batchCode || '-' }}</span>
+                    </view>
+                    <view class="pd2-4-0 f-s-28">
+                        <span class="c-#666">执行标准:</span>
+                        <span class="c-#333 f-w-500">{{ item?.supplierInfo?.cusName || '-' }}</span>
+                    </view>
+                    <view class="pd2-4-0 f-s-28">
+                        <span class="c-#666">加工工艺:</span>
+                        <span class="c-#333 f-w-500">{{ item?.supplierInfo?.cusName || '-' }}</span>
+                    </view>
+                    <view class="pd2-4-0 f-s-28">
+                        <span class="c-#666">入库量:</span>
+                        <span class="c-#333 f-w-500">{{ item?.capacity }}{{ item?.unit }}</span>
+                    </view>
+                    <view class="d-flex">
+                        <view v-if="item?.inputAmount" class="pd2-4-0 f-s-28 flex1">
+                            <span class="c-#666">出库量:</span>
+                            <span class="c-#333 f-w-500">{{ item?.inputAmount || '0' }}{{ item?.unit }}</span>
+                        </view>
+                        <view v-if="item?.restAmount" class="pd2-4-0 f-s-28 flex1">
+                            <span class="c-danger">剩余量:</span>
+                            <span class="c-danger f-w-500">{{ item?.restAmount || '0' }}{{ item?.unit }}</span>
+                        </view>
+                    </view>
+                    <image v-if="item.id + '-' + item.storageType === checkedId" class="w-40 h-40 checked-icon" src="/static/images/common/btn_checked_icon.png" mode="widthFix" />
+                </view>
+            </template>
+        </view>
+
+        <template #empty>
+            <view class="d-flex flex-cln a-c" style="margin-top: -200rpx">
+                <ut-empty class="mg-at" color="#ccc" size="28rpx">暂无药材信息</ut-empty>
+            </view>
+        </template>
+        <template #bottom>
+            <view class="pd-24">
+                <up-button @click="emit('confirm')" type="primary">确认选择</up-button>
+            </view>
+        </template>
+    </z-paging>
+</template>
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+const props = defineProps({
+    checkedId: {
+        type: String,
+        default: '',
+    },
+});
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { st_medicine_process_type } = toRefs<any>(proxy?.useDict('st_medicine_process_type'));
+const list = ref<any[]>();
+const form = ref({ keyword: '', restFlag: '1', processType: '', storageType: '5' });
+const paging = ref();
+const changeSeach = () => {
+    paging.value.reload();
+};
+const emit = defineEmits(['clickItem', 'confirm']);
+const query = async (pageNum: number, pageSize: number) => {
+    const params = {
+        pageNum,
+        pageSize,
+        ...form.value,
+    };
+    const res = await useClientRequest.get('/plt-api/app/storage/list', params);
+    if (res) {
+        const { rows } = res;
+        paging.value.complete(rows);
+    }
+};
+
+const onRefresh = () => {
+    paging.value.reload();
+};
+onMounted(() => {
+    uni.$on('refreshStorageRoomList', () => {
+        onRefresh();
+    });
+});
+</script>
+<style lang="scss" scoped>
+.search-select-item {
+    height: 86rpx;
+    background-color: #fff;
+    border-radius: 10rpx;
+    box-sizing: border-box;
+    padding: 12rpx;
+}
+.tag-span {
+    padding: 4rpx 12rpx;
+    font-size: 20rpx;
+    border-radius: 18rpx;
+}
+.li-item-head {
+    margin-left: -24rpx;
+    margin-top: -24rpx;
+}
+.li-left-tag {
+    padding: 6rpx 16rpx;
+    color: #fff;
+    border-radius: 16rpx 0 16rpx 0;
+    font-size: 20rpx;
+    font-weight: 500;
+}
+.select-item-list {
+    border: 1rpx solid #fff;
+    &.active {
+        background-color: #ebf6ee;
+        border: 1rpx solid $u-primary;
+    }
+    .checked-icon {
+        position: absolute;
+        right: 0rpx;
+        bottom: 0rpx;
+    }
+}
+</style>

+ 186 - 0
src/plant/packaging/select-object/models/select-seed-source-list.vue

@@ -0,0 +1,186 @@
+<template>
+    <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" bottom-bg-color="#fff" safe-area-inset-bottom paging-class="paging-btm-shadow" @query="query">
+        <view class="pd3-24-24-0">
+            <view class="d-flex a-c">
+                <view class="min-w-230 flex1">
+                    <ut-action-sheet v-model="form.instoreType" :tabs="[{ label: '全部', value: '' }, ...pt_seed_instore_type]" mode="custom" @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">{{ selectDictLabel(pt_seed_instore_type, form.instoreType) || '全部' }} </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="changeSeach" margin="0" :border="false" placeholder="搜名称、批号、库房、供应商" bgColor="#fff" height="86rpx" borderRadius="10rpx"></ut-search>
+                </view>
+            </view>
+            <view></view>
+        </view>
+        <view class="pd-24 bg-#f7f7f7">
+            <template v-for="(item, index) in list" :key="index">
+                <view class="b-radius bg-#fff pd-20 p-rtv mb-20 select-item-list" :class="{ 'active': item.id + '-' + item.storageType === checkedId }" @click="emit('clickItem', item)">
+                    <view class="d-flex j-sb a-c li-item-head mb-16">
+                        <view class="li-left-tag" :class="{ [`bg-instore-${item?.instoreType}`]: true }">{{ selectDictLabel(pt_seed_instore_type, item?.instoreType) }}</view>
+                        <view class="f-s-22 c-#666">{{ item?.instoreBizInfo?.instoreDate }}</view>
+                    </view>
+                    <view class="d-flex flex1 mb-10">
+                        <view class="flex1">
+                            <span class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.variety }}</span>
+                            <span class="f-s-24 c-#666">{{ item?.seedLevel }}{{ selectDictLabel(pt_seed_type, item?.seedType) }}</span>
+                        </view>
+                        <view>
+                            <view v-if="item?.examinReport?.length" class="tag-span c-primary bg-#EBF6EE">已检验</view>
+                            <view v-else class="tag-span c-danger bg-#F9ECEA">未检验</view>
+                        </view>
+                    </view>
+                    <template v-if="item?.instoreType == '2'">
+                        <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">入库批号:</span>
+                            <span class="c-#333 f-w-500">{{ item?.batchCode }}</span>
+                        </view>
+                        <!-- <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">溯源批号:</span>
+                            <span class="c-#333 f-w-500">暂无</span>
+                        </view> -->
+                        <view v-if="['A3', 'A4'].includes(item?.seedType)" class="pd2-4-0 f-s-28">
+                            <span class="c-#666">菌种/菌株编号:</span>
+                            <span class="c-#333 f-w-500">{{ selectDictLabel(pt_fungus_code_type, item?.fungusCodeType) }}/{{ item?.fungusCode }}</span>
+                        </view>
+                        <view v-if="item?.supplierId" class="pd2-4-0 f-s-28">
+                            <span class="c-#666">供应商:</span>
+                            <span class="c-#333 f-w-500">{{ item?.supplierInfo?.cusName || '-' }}</span>
+                        </view>
+                        <view v-if="item?.warehouses?.length" class="pd2-4-0 f-s-28">
+                            <span class="c-#666">存放库房:</span>
+                            <span class="c-#333 f-w-500">{{ getStorageRoomNames(item?.warehouses) || '-' }}</span>
+                        </view>
+                    </template>
+                    <template v-if="item?.instoreType == '3'">
+                        <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">采收批号:</span>
+                            <span class="c-#333 f-w-500">{{ item?.harvestInfo?.harvestCode || '-' }}</span>
+                        </view>
+                        <view class="pd2-4-0 f-s-28">
+                            <span class="c-#666">采收基地:</span>
+                            <span class="c-#333 f-w-500">
+                                {{ item?.harvestInfo?.baseInfo?.baseName || '-' }}
+                            </span>
+                        </view>
+                        <view v-if="['A3', 'A4'].includes(item?.seedType)" class="pd2-4-0 f-s-28">
+                            <span class="c-#666">菌种/菌株编号:</span>
+                            <span class="c-#333 f-w-500">{{ selectDictLabel(pt_fungus_code_type, item?.fungusCodeType) }}/{{ item?.fungusCode }}</span>
+                        </view>
+                        <view v-if="item?.warehouses?.length" class="pd2-4-0 f-s-28">
+                            <span class="c-#666">存放库房:</span>
+                            <span class="c-#333 f-w-500">{{ getStorageRoomNames(item?.warehouses) || '-' }}</span>
+                        </view>
+                    </template>
+                    <view class="pd2-4-0 f-s-28">
+                        <span class="c-#666">入库量:</span>
+                        <span class="c-#333 f-w-500">{{ item?.capacity }}{{ item?.unit }}</span>
+                    </view>
+                    <view class="d-flex">
+                        <view v-if="item?.inputAmount" class="pd2-4-0 f-s-28 flex1">
+                            <span class="c-#666">出库量:</span>
+                            <span class="c-#333 f-w-500">{{ item?.inputAmount || '0' }}{{ item?.unit }}</span>
+                        </view>
+                        <view v-if="item?.restAmount" class="pd2-4-0 f-s-28 flex1">
+                            <span class="c-danger">剩余量:</span>
+                            <span class="c-danger f-w-500">{{ item?.restAmount || '0' }}{{ item?.unit }}</span>
+                        </view>
+                    </view>
+                     <image v-if="item.id + '-' + item.storageType === checkedId" class="w-40 h-40 checked-icon" src="/static/images/common/btn_checked_icon.png" mode="widthFix" />
+                </view>
+            </template>
+        </view>
+
+        <template #empty>
+            <view class="d-flex flex-cln a-c" style="margin-top: -200rpx">
+                <ut-empty class="mg-at" color="#ccc" size="28rpx">暂无种源信息,点击下方+号新增吧</ut-empty>
+            </view>
+        </template>
+        <template #bottom>
+            <view class="pd-24">
+                <up-button @click="emit('confirm')" type="primary">确认选择</up-button>
+            </view>
+        </template>
+    </z-paging>
+</template>
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+
+import { getStorageRoomNames } from '@/utils/common';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_seed_instore_type, pt_seed_type, pt_fungus_code_type } = toRefs<any>(proxy?.useDict('pt_seed_instore_type', 'pt_seed_type', 'pt_fungus_code_type'));
+const props = defineProps({
+    checkedId: {
+        type: String,
+        default: '',
+    },
+});
+const emit = defineEmits(['clickItem', 'confirm']);
+const list = ref<any[]>();
+const form = ref({ keyword: '', restFlag: '1', instoreType: '' });
+const paging = ref();
+const changeSeach = () => {
+    paging.value.reload();
+};
+const query = async (pageNum: number, pageSize: number) => {
+    const params = {
+        pageNum,
+        pageSize,
+        ...form.value,
+    };
+    const res = await useClientRequest.get('/plt-api/app/storageSeed/page', params);
+    if (res) {
+        const { rows } = res;
+        paging.value.complete(rows);
+    }
+};
+
+const onRefresh = () => {
+    paging.value.reload();
+};
+onMounted(() => {
+    uni.$on('refreshStorageRoomList', () => {
+        onRefresh();
+    });
+});
+</script>
+<style lang="scss" scoped>
+.search-select-item {
+    height: 86rpx;
+    background-color: #fff;
+    border-radius: 10rpx;
+    box-sizing: border-box;
+    padding: 12rpx;
+}
+.tag-span {
+    padding: 4rpx 12rpx;
+    font-size: 20rpx;
+    border-radius: 18rpx;
+}
+.li-item-head {
+    margin-left: -24rpx;
+    margin-top: -24rpx;
+}
+.li-left-tag {
+    padding: 6rpx 16rpx;
+    color: #fff;
+    border-radius: 16rpx 0 16rpx 0;
+    font-size: 20rpx;
+    font-weight: 500;
+}
+.select-item-list {
+    border: 1rpx solid #fff;
+    &.active {
+        background-color: #ebf6ee;
+        border: 1rpx solid $u-primary;
+    }
+    .checked-icon {
+        position: absolute;
+        right: 0rpx;
+        bottom: 0rpx;
+    }
+}
+</style>

+ 2 - 2
src/plant/storage/medicine/list/index.vue

@@ -128,7 +128,7 @@ const clickTempSwipe = async (event: object) => {
         try {
             const res = await uni.showModal({
                 title: '删除提示',
-                content: '确定删除鲜货信息吗?',
+                content: '确定删除药材信息吗?',
                 confirmColor: '#F74C30',
             });
             if (!res.confirm) return;
@@ -144,7 +144,7 @@ const clickTempSwipe = async (event: object) => {
             });
             paging.value?.reload();
         } catch (error) {
-            console.error('删除暂存鲜货信息失败:', error);
+            console.error('删除暂存药材信息失败:', error);
         }
     }
 };