huangxw 1 viikko sitten
vanhempi
säilyke
60aa108b2a

+ 8 - 0
src/assets/styles/uview-plus.ts

@@ -0,0 +1,8 @@
+// 表单按钮样式对象
+export const formItemBtnStyle = {
+    height: '50rpx',
+    borderRadius: '8rpx',
+    fontSize: '26rpx',
+    padding: '0 20rpx',
+    lineHeight: '50rpx',
+};

+ 47 - 21
src/components/ut-picker-area/ut-picker-area.vue

@@ -98,7 +98,6 @@ interface UtPickerAreaProps {
     title?: string;
     maxLevel?: number;
     selectCodeMax?: string;
-    selectedCodes?: string[];
 }
 
 const props = withDefaults(defineProps<UtPickerAreaProps>(), {
@@ -107,14 +106,12 @@ const props = withDefaults(defineProps<UtPickerAreaProps>(), {
     title: '选择区域',
     maxLevel: 3,
     selectCodeMax: '',
-    selectedCodes: () => [] as string[],
 });
 
 const emits = defineEmits<{
     (e: 'update:modelValue', value: string): void;
     (e: 'update:show', value: boolean): void;
     (e: 'confirm', payload: ConfirmPayload): void;
-    (e: 'update:selectedCodes', value: string[]): void;
 }>();
 
 const uToastRef = ref<{ show: (opts: any) => void } | null>(null);
@@ -178,21 +175,34 @@ const canonical6 = (code: MaybeStringNumber): string => {
     }
     return s;
 };
+// 从根开始拆分一条完整链路:只保留真实存在的层级
+// 规则:
+// - 先归一到 6 位区域基码 base6(省/市/区),再按 省(2) / 市(4) / 区(6) 拆分
+// - 若原始码长度 > 6(如 9/12 位),再追加完整码作为最后一级
+// 这样不会生成诸如 9 位的“虚拟层级”,避免回显时名称缺失
 const chainFromRoot = (code: MaybeStringNumber): string[] => {
-    const s = normalize6(code);
-    if (!s || s === '000000') return [];
+    const raw = normalize6(code);
+    if (!raw || raw === '000000') return [];
+
     const list: string[] = [];
-    // 省/市/区:统一输出为“最少6位”,少于补0,多余去掉末尾00(canonical6 内处理)
-    for (let i = 2; i <= Math.min(6, s.length); i += 2) {
-        list.push(canonical6(s.slice(0, i)));
+
+    // 6 位区域基码(省/市/区)
+    const base6 = canonical6(raw).slice(0, 6);
+    if (base6 && base6 !== '000000') {
+        const prov = base6.slice(0, 2).padEnd(6, '0');
+        const city = base6.slice(0, 4).padEnd(6, '0');
+        const dist = base6;
+
+        [prov, city, dist].forEach((c) => {
+            if (c && c !== '000000' && !list.includes(c)) list.push(c);
+        });
     }
-    // 扩展层级:9/12 位,保持真实长度;其 6 位基底已按 canonical6 规范化
-    if (s.length > 6) {
-        const base6 = canonical6(s).slice(0, 6);
-        for (let j = 9; j <= s.length; j += 3) {
-            list.push(base6 + s.slice(6, j));
-        }
+
+    // 扩展层级:保留原始完整码(9/12 位等),作为区县之后的细分层级
+    if (raw.length > 6 && !list.includes(raw)) {
+        list.push(raw);
     }
+
     return list;
 };
 
@@ -217,7 +227,7 @@ const pendingMap = ref<Record<string, Promise<AreaItem[]> | undefined>>({});
 const nameMap = ref<Record<string, string>>({ '000000': '全国' });
 
 // 选中链路(不包含 baseRoot),例如 baseRoot=省,选中市/区... 这里存 [市, 区, ...]
-const selectedCodes = ref<string[]>(props?.selectedCodes || []);
+const selectedCodes = ref<string[]>([]);
 const currentValue = ref<string>(''); // 当前选中最终 code
 
 // 计算列:每列的父节点仅为“下一列的父节点”,避免最后一级再多出一列
@@ -258,15 +268,32 @@ const getChildren = async (parentCode: string): Promise<AreaItem[]> => {
         });
         if (res?.code === 200) {
             const rows: AreaItem[] = (res.rows || []).map((x: any) => ({
-                // 不再截断为 6 位,保留完整 code
-                adcdCode: nameKey(x.adcdCode),
+                // 保留服务端返回的完整编码(6 位省级,12 位市/区/街道/村委会)
+                adcdCode: String(x.adcdCode ?? ''),
                 adcdName: x.adcdName,
             }));
             childrenMap.value[key] = rows; // 写入结果缓存
             rows.forEach((r) => {
-                // 名称缓存:精确键必存;仅当长度<=6时,才缓存到最少6位标准键,避免覆盖区县名称
-                nameMap.value[r.adcdCode] = r.adcdName;
-                nameMap.value[nameKey(r.adcdCode)] = r.adcdName;
+                const codeStr = String(r.adcdCode ?? '');
+                if (!codeStr) return;
+
+                // 精确键:始终缓存,保证 9/12 位街道、村委会可以直接取到名称
+                nameMap.value[codeStr] = r.adcdName;
+
+                // 若是 6 位(省/市/区),补一份到归一化 6 位 key(一般相同)
+                if (codeStr.length <= 6) {
+                    const k6 = nameKey(codeStr);
+                    if (!nameMap.value[k6]) nameMap.value[k6] = r.adcdName;
+                }
+
+                // 若是 12 位且末尾 6 位全为 0,视为“市/区等 6 位层级”的 12 位表示
+                // 额外为其 6 位基码建立名称映射,方便用 6 位链路回显
+                if (codeStr.length === 12 && codeStr.endsWith('000000')) {
+                    const base6 = codeStr.slice(0, 6);
+                    if (!nameMap.value[base6]) nameMap.value[base6] = r.adcdName;
+                    const k6 = nameKey(base6);
+                    if (!nameMap.value[k6]) nameMap.value[k6] = r.adcdName;
+                }
             });
             delete pendingMap.value[key]; // 清除进行中缓存
             return rows;
@@ -480,7 +507,6 @@ const confirmPick = (): void => {
         fullNames: nameList.join(''),
         fullName // 新增:完整地址名称
     });
-    emits('update:selectedCodes', codeList);
     close();
 };
 

+ 6 - 5
src/components/ut-tabs/ut-tabs.vue

@@ -43,9 +43,9 @@
     <template v-if="mode == 'subsection'">
         <view class="tabs-subsection-wrap d-flex">
             <template v-for="(item, idx) in tabs" :key="idx">
-                <view class="flex1 subsection-item d-flex p-rtv j-c a-c" :class="{ active: idx === activeIndex }">
-                    <slot :name="item.value">
-                        <text class="f-s-32 c-999">{{ item.label }}</text>
+                <view class="flex1 subsection-item d-flex p-rtv j-c a-c f-s-32 c-999"  @click="selectTab(idx)" :class="{ active: idx === activeIndex }">
+                    <slot :name="item.value" :active="idx === activeIndex">
+                        {{ item.label }}
                     </slot>
                 </view>
             </template>
@@ -180,8 +180,9 @@ const scrollToTab = (idx: number) => {
     background-color: #fff;
     overflow: hidden;
 
-    &.active .subsection-item {
-        background-color: #f0f9f4;
+    .active.subsection-item {
+        background-color: #37A954;
+        color: #fff;
     }
 }
 </style>

+ 14 - 0
src/pages.json

@@ -172,6 +172,20 @@
                     "style": {
                         "navigationBarTitleText": "种源详情"
                     }
+                },
+                // 新增种源入库
+                {
+                    "path": "seed-source/add/index",
+                    "style": {
+                        "navigationBarTitleText": "新增种源入库"
+                    }
+                },
+                // 添加种源信息
+                {
+                    "path": "seed-source/info-edit/index",
+                    "style": {
+                        "navigationBarTitleText": "添加种源信息"
+                    }
                 }
             ]
         },

+ 5 - 2
src/plant/base/base-edit/index.vue

@@ -35,6 +35,9 @@
                 <ut-datetime-picker v-model="form.baseInfo.buildDate" mode="date" dateFields="month">
                     <up-form-item borderBottom label="建设时间" required prop="baseInfo.buildDate">
                         <up-input v-model="form.baseInfo.buildDate" placeholder="请选择基地建设年份" border="none" clearable></up-input>
+                        <template #right>
+                            <up-icon size="22rpx" color="#2A6D52" name="arrow-down-fill"></up-icon>
+                        </template>
                     </up-form-item>
                 </ut-datetime-picker>
                 <!-- 选择基地组织方式 -->
@@ -75,7 +78,7 @@
                     <template v-if="+form.baseInfo.gapFlag">
                         <template v-if="!form.baseInfo.gapId">
                             <up-form-item borderBottom label="关联的GAP获评信息" prop="baseInfo.gapId">
-                                <up-button @click="selectGapInfo" type="primary" text="确定" plain>
+                                <up-button @click="selectGapInfo" type="primary" plain>
                                     <up-icon class="mr-10" name="plus" color="#37A954"></up-icon>
                                     <span>请选择要关联的GAP基地获评信息</span>
                                 </up-button>
@@ -540,7 +543,7 @@
             </view>
         </template>
     </z-paging>
-    <ut-picker-area v-model:show="showArea" v-model="form.baseInfo.gapInfo.adcode" @confirm="confirmArea"></ut-picker-area>
+    <ut-picker-area v-model:show="showArea" v-model="form.baseInfo.gapInfo.adcode" :maxLevel="5" @confirm="confirmArea"></ut-picker-area>
     <FormPlot v-if="showPlot" v-model:show="showPlot" v-model="rowForm" :title="plotTitle" :dict="{ pt_light_type, pt_capacity_unit, yes_no }" @submit="submitFormPlotAdd"></FormPlot>
     <FormPlot v-if="showPlotEdit" v-model:show="showPlotEdit" v-model="rowFormEdit" :title="plotTitle" :dict="{ pt_light_type, pt_capacity_unit, yes_no }" @submit="submitFormPlotEdit"></FormPlot>
 </template>

+ 1 - 17
src/plant/base/gap-base-info-edit/index.vue

@@ -310,20 +310,4 @@ const getLocationByAddress = async () => {
 };
 
 </script>
-<style lang="scss" scoped>
-.z-paging-wrap {
-    position: absolute;
-    right: 0;
-    top: 0;
-    bottom: 0;
-    left: 0;
-}
-
-.btn-aree-center {
-    position: absolute;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    left: 0;
-}
-</style>
+<style lang="scss" scoped></style>

+ 172 - 0
src/plant/storage/seed-source/add/index.vue

@@ -0,0 +1,172 @@
+<template>
+    <z-paging class="" ref="paging" bgColor="#f7f7f7" paging-class="paging-btm-shadow" safe-area-inset-bottom scroll-with-animation>
+        <template #top>
+            <ut-navbar :title="did ? '编辑种源入库' : '新增种源入库'" :fixed="false" border></ut-navbar>
+        </template>
+        <up-form class="p-rtv" labelPosition="top" :model="form" :rules="rules" labelWidth="auto" ref="upFormRef">
+            <!-- 种源信息 -->
+            <view class="pd-24">
+                <view class="startline-title">种源信息</view>
+            </view>
+            <view class="pd-24 bg-#fff">
+                <!-- TODO: 后续按 seedInfoList 设计种源信息明细,此处先留空结构避免表单错误 -->
+                <up-form-item borderBottom label="添加种源信息" required prop="seedInfoList">
+                    <view class="flex1">
+                        <template v-for="(item, index) in form.seedInfoList" :key="index"></template>
+                        <up-button type="primary" plain @click="$u.route({ url: '/plant/storage/seed-source/info-edit/index' })">
+                            <up-icon class="mr-10" name="plus" color="#37A954"></up-icon>
+                            <span>点击添加种源入库</span>
+                        </up-button>
+                    </view>
+                </up-form-item>
+            </view>
+            <view class="pd-24">
+                <view class="startline-title">入库信息</view>
+            </view>
+            <view class="pd-24 bg-#fff">
+                <!-- 种源级别 -->
+                <up-form-item borderBottom label="种源级别" prop="seedLevel">
+                    <up-input v-model="form.seedLevel" placeholder="请输入种源级别" border="none" clearable></up-input>
+                </up-form-item>
+                <!-- 入库类型 -->
+                <up-form-item borderBottom label="入库类型" required prop="instoreType">
+                    <view v-if="form.instoreType" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(pt_seed_instore_type, form.instoreType) }}</view>
+                    <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择入库类型</view>
+                </up-form-item>
+                <!-- 入库日期 -->
+                <view class="h-1" id="instoreDatepppp"></view>
+                <ut-datetime-picker v-model="form.instoreBizInfo.instoreDate" :maxDate="new Date()" mode="date">
+                    <up-form-item borderBottom label="入库日期" required prop="instoreBizInfo.instoreDate">
+                        <up-input v-model="form.instoreBizInfo.instoreDate" placeholder="请选择入库日期" border="none" clearable></up-input>
+                        <template #right>
+                            <up-icon size="22rpx" color="#2A6D52" name="arrow-down-fill"></up-icon>
+                        </template>
+                    </up-form-item>
+                </ut-datetime-picker>
+                <!-- 入库批号 -->
+                <up-form-item borderBottom label="入库批号" required prop="batchCode">
+                    <up-input v-model="form.batchCode" placeholder="请输入入库批号" border="none" clearable></up-input>
+                    <template #right>
+                        <up-button @click="generateBatchCode" type="primary" :customStyle="formItemBtnStyle">随机生成</up-button>
+                    </template>
+                </up-form-item>
+                <!-- 库房类型 -->
+                <up-form-item borderBottom label="库房类型" prop="storeType">
+                    <view v-if="form.storeType" class="f-s-30 c-333 f-w-5 flex1">{{ selectDictLabel(pt_warehouse_type, form.storeType) }}</view>
+                    <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择库房类型</view>
+                </up-form-item>
+                <!-- 存放库房(具体库房/货架信息稍后补充为选择器) -->
+                <up-form-item borderBottom label="存放库房" prop="storeCode">
+                    <up-input v-model="form.storeCode" placeholder="请输入存放库房或编码" border="none" clearable></up-input>
+                </up-form-item>
+                <!-- 入库人 -->
+                <up-form-item borderBottom label="入库人" required prop="instoreBizInfo.instoreMg">
+                    <up-input v-model="form.instoreBizInfo.instoreMg" placeholder="请输入入库人" border="none" clearable></up-input>
+                </up-form-item>
+                <!-- 入库备注 -->
+                <up-form-item borderBottom label="入库备注" prop="instoreBizInfo.remark">
+                    <up-textarea v-model="form.instoreBizInfo.remark" placeholder="请输入入库备注" autoHeight></up-textarea>
+                </up-form-item>
+            </view>
+        </up-form>
+        <template #bottom>
+            <view class="pd-20 d-flex">
+                <up-button @click="submitForm" type="primary">确认入库</up-button>
+            </view>
+        </template>
+    </z-paging>
+</template>
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+import { SeedSourceAddTypeEnum } from '../models/type';
+import { formItemBtnStyle } from '@/assets/styles/uview-plus';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_seed_instore_type, pt_warehouse_type } = toRefs<any>(proxy?.useDict('pt_seed_instore_type', 'pt_warehouse_type'));
+// 表单与分页等基础状态(参考 base-edit 风格)
+const paging = ref<any>(null);
+const upFormRef = ref<any>(null);
+const showArea = ref(false);
+const form = ref<SeedSourceAddTypeEnum>({
+    instoreType: '2',
+    storeType: '2',
+    seedInfoList: [],
+    warehouses: [],
+    instoreBizInfo: {},
+});
+const rules = reactive({});
+
+const submitForm = async () => {
+    uni.$u.debounce(
+        async () => {
+            try {
+                await upFormRef.value?.validate();
+            } catch (error: any) {
+                // 滚动到第一个错误字段
+                const firstErrorField = error && error[0].prop + 'pppp';
+                paging.value?.scrollIntoViewById(firstErrorField, 30, true);
+                return;
+            }
+            // 提交表单
+            uni.showLoading({
+                title: '提交中...',
+            });
+            try {
+                const res = did.value ? await useClientRequest.post(`/plt-api/app/gapCertificationInfo/update`, form.value) : await useClientRequest.post('/plt-api/app/gapCertificationInfo/add', form.value);
+                uni.hideLoading();
+                if (!res || res !== 200) return;
+                uni.hideLoading();
+                uni.showToast({
+                    title: '提交成功',
+                    icon: 'success',
+                });
+                uni.$emit('gapBaseInfoUpdated');
+                // 返回上一页
+                setTimeout(() => {
+                    uni.navigateBack();
+                }, 1500);
+            } catch (error) {
+                uni.hideLoading();
+            }
+        },
+        500,
+        true
+    );
+};
+// 点击随机生成服务端生成唯一的批号
+const generateBatchCode = async () => {
+    uni.showLoading({
+        title: '生成中...',
+    });
+    const res = await useClientRequest.post('/plt-api/app/plantationTask/getBatchCode', {
+        plType: 'S',
+        linkType: 'I',
+    });
+    if (res && res.code === 200) {
+        uni.hideLoading();
+        form.value.batchCode = res.data;
+        uni.showToast({
+            title: '批号生成成功',
+            icon: 'success',
+        });
+    }
+};
+const getDetailById = async (id: string) => {
+    if (!id) return;
+    const res = await useClientRequest.get(`/plt-api/app/gapCertificationInfo/getInfoById/${id}`);
+    if (res && res.code === 200) {
+        form.value = {
+            ...res.data,
+        };
+    }
+};
+const did = ref('');
+onLoad((optins: any) => {
+    if (optins.id) {
+        // 编辑加载详
+        did.value = optins.id;
+        getDetailById(optins.id);
+    } else {
+    }
+});
+</script>
+<style lang="scss" scoped></style>

+ 156 - 0
src/plant/storage/seed-source/info-edit/index.vue

@@ -0,0 +1,156 @@
+<template>
+    <z-paging class="" ref="paging" bgColor="#fff" paging-class="paging-btm-shadow" safe-area-inset-bottom scroll-with-animation>
+        <template #top>
+            <ut-navbar :title="did ? '编辑种源入库信息' : '添加种源入库信息'" :fixed="false" border></ut-navbar>
+        </template>
+        <view class="pd-24">
+            <up-form class="p-rtv" labelPosition="top" :model="form" :rules="rules" labelWidth="auto" ref="upFormRef">
+                <!-- 基本信息 -->
+                <up-form-item borderBottom label="种源类型" required prop="seedType">
+                    <up-input v-model="form.seedType" placeholder="请输入种源类型" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="物种基原" required prop="varietyId">
+                    <up-input v-model="form.varietyId" placeholder="请输入物种基原" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="具体品种/品系名称" prop="seedName">
+                    <up-input v-model="form.seedName" placeholder="请输入具体品种/品系名称" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="种源来源" required prop="seedSource">
+                    <up-input v-model="form.seedSource" placeholder="请输入种源来源" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="受托单位" prop="entrustId">
+                    <up-input v-model="form.entrustId" placeholder="请输入受托单位" border="none" clearable></up-input>
+                </up-form-item>
+
+                <!-- 入库数量与单位 -->
+                <up-form-item borderBottom label="入库量" prop="capacity">
+                    <up-input v-model="form.capacity" type="number" placeholder="请输入入库量" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="计量单位" prop="unit">
+                    <up-input v-model="form.unit" placeholder="请输入计量单位" border="none" clearable></up-input>
+                </up-form-item>
+
+                <!-- 检验报告与供应商信息 -->
+                <up-form-item borderBottom label="检验报告" prop="examinReport">
+                    <up-input v-model="form.examinReport" placeholder="请输入检验报告编号或说明" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="供应商" prop="supplierId">
+                    <up-input v-model="form.supplierId" placeholder="请输入供应商" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="供应商名称" prop="supplier">
+                    <up-input v-model="form.supplier" placeholder="请输入供应商名称" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="生产商" prop="producer">
+                    <up-input v-model="form.producer" placeholder="请输入生产商名称" border="none" clearable></up-input>
+                </up-form-item>
+
+                <!-- 菌种编码信息 -->
+                <up-form-item borderBottom label="菌种/菌株编号" prop="fungusCode">
+                    <up-input v-model="form.fungusCode" placeholder="请输入菌种/菌株编号" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="菌种编码类型" prop="fungusCodeType">
+                    <up-input v-model="form.fungusCodeType" placeholder="请输入菌种编码类型" border="none" clearable></up-input>
+                </up-form-item>
+
+                <!-- 个体标识:此处仅占位,后续可改为多选列表 -->
+                <up-form-item borderBottom label="是否有个体标识" prop="animalIds">
+                    <up-input v-model="form.animalIds" placeholder="如有个体标识,请稍后补充明细" border="none" disabled></up-input>
+                </up-form-item>
+
+                <!-- 媒体与附件 -->
+                <up-form-item borderBottom label="种源图片" prop="imgs">
+                    <ut-upload v-model="form.imgs" :max-count="9"></ut-upload>
+                </up-form-item>
+                <up-form-item borderBottom label="种源视频" prop="vedios">
+                    <ut-upload v-model="form.vedios" :max-count="3" accept="video" valueType="array"></ut-upload>
+                </up-form-item>
+
+                <!-- 产地与繁殖信息 -->
+                <up-form-item borderBottom label="种源产地" prop="adcode">
+                    <up-input v-model="form.adcode" placeholder="请输入种源产地行政编码" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="繁殖材料" prop="generationMaterial">
+                    <up-input v-model="form.generationMaterial" placeholder="请输入繁殖材料" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="繁殖地点/采集地点" prop="generationAdcode">
+                    <up-input v-model="form.generationAdcode" placeholder="请输入繁殖/采集地点编码或名称" border="none" clearable></up-input>
+                </up-form-item>
+
+                <!-- 资质证明附件(暂按上传控件处理,可后续细化) -->
+                <up-form-item borderBottom label="物种鉴定证书" prop="spCert">
+                    <ut-upload v-model="form.spCert" :max-count="9" valueType="array" accept="file"></ut-upload>
+                </up-form-item>
+                <up-form-item borderBottom label="新品种证书" prop="newSpCert">
+                    <ut-upload v-model="form.newSpCert" :max-count="9" valueType="array" accept="file"></ut-upload>
+                </up-form-item>
+                <up-form-item borderBottom label="引种证明" prop="importCert">
+                    <ut-upload v-model="form.importCert" :max-count="9" valueType="array" accept="file"></ut-upload>
+                </up-form-item>
+
+                <!-- 检疫信息 -->
+                <up-form-item borderBottom label="种源检疫证号" prop="seedCheckSn">
+                    <up-input v-model="form.seedCheckSn" placeholder="请输入种源检疫证号" border="none" clearable></up-input>
+                </up-form-item>
+                <up-form-item borderBottom label="种源检疫证书" prop="seedCheckCert">
+                    <ut-upload v-model="form.seedCheckCert" :max-count="9" valueType="array" accept="file"></ut-upload>
+                </up-form-item>
+            </up-form>
+        </view>
+        <template #bottom>
+            <view class="pd-20 d-flex">
+                <up-button @click="submitForm" type="primary">保存</up-button>
+            </view>
+        </template>
+    </z-paging>
+</template>
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+import { seedInfoListType } from '../models/type';
+
+const paging = ref<any>(null);
+const upFormRef = ref<any>(null);
+const form = ref<seedInfoListType>({
+    imgs: [],
+    vedios: [],
+    spCert: [],
+    newSpCert: [],
+    importCert: [],
+    seedCheckCert: [],
+});
+const rules = reactive({});
+
+const submitForm = async () => {
+    uni.$u.debounce(
+        async () => {
+            try {
+                await upFormRef.value?.validate();
+            } catch (error: any) {
+                // 滚动到第一个错误字段
+                const firstErrorField = error && error[0].prop + 'pppp';
+                paging.value?.scrollIntoViewById(firstErrorField, 30, true);
+                return;
+            }
+            // 提交表单
+            uni.showLoading({
+                title: '提交中...',
+            });
+            try {
+            } catch (error) {
+                uni.hideLoading();
+            }
+        },
+        500,
+        true
+    );
+};
+
+const did = ref('');
+onLoad((optins: any) => {
+    if (optins.id) {
+        // 编辑加载详
+        did.value = optins.id;
+    } else {
+    }
+});
+</script>
+<style lang="scss" scoped></style>

+ 6 - 4
src/plant/storage/seed-source/list/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" @query="query" safe-area-inset-bottom>
+    <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" @query="query">
         <template #top>
             <ut-navbar title="种源库" :fixed="false"></ut-navbar>
         </template>
@@ -8,7 +8,7 @@
             <view class="mb-20">
                 <ut-tabs mode="subsection" :tabs="tabs" v-model="form.queryType"></ut-tabs>
             </view>
-            <view class="d-flex a-c bg-#f7f7f7">
+            <view class="d-flex a-c">
                 <view class="min-w-170 flex1">
                     <ut-action-sheet v-model="form.queryType" :tabs="[{ label: '全部', value: '' }]" @change="onRefresh" title="选择原料类型">
                         <view class="d-flex search-select-item a-c">
@@ -30,11 +30,14 @@
                 <ut-empty class="mg-at" color="#ccc" size="28rpx">暂无种源信息,点击下方+号新增吧</ut-empty>
             </view>
         </template>
+        <template #bottom>
+            <source-bottom></source-bottom>
+        </template>
     </z-paging>
 </template>
 <script setup lang="ts">
 import { useClientRequest } from '@/utils/request';
-import { onShareAppMessage } from '@dcloudio/uni-app';
+import SourceBottom from './model/source-bottom.vue';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { pt_task_type } = toRefs<any>(proxy?.useDict('pt_task_type'));
 const list = ref<unknown[]>();
@@ -43,7 +46,6 @@ const paging = ref();
 const tabs = ref([
     { label: '有库存', value: 'seed' },
     { label: '无库存', value: 'seedling' },
-    { label: '种球', value: 'bulb' },
 ]);
 
 const changeSeach = () => {

+ 110 - 0
src/plant/storage/seed-source/list/model/source-bottom.vue

@@ -0,0 +1,110 @@
+<template>
+    <view class="source-bottom p-rtv">
+        <view class="source-top-view h-49"></view>
+        <view class="source-bottom-view pt-49 text-center bg-#fff pt-60" :style="{ opacity: btnStyle == 'close' ? 0 : 1 }">
+             <view style="opacity: 0;">{{ mapTextBtn[btnStyle] }}</view>
+       
+        </view>
+        <view @click="clickBtnBall" class="source-center-view d-flex flex-cln a-c j-c">
+            <view class="source-btn-ball d-flex a-c j-c" :class="{ [`btn-deg-${btnStyle}`]: true }" :style="{ backgroundImage: 'url(/static/images/plant/storage/add_c_btn.png)' }"></view>
+            <view class="c-primary f-s-28 pt-6">{{ mapTextBtn[btnStyle] }}</view>
+            
+        </view>
+        <view class="bg-#fff" :style="{ height: safeAreaBottom + 'px' }"></view>
+        <view class="bottom-circle-line" :class="{ 'bottom-circle-line-active': btnStyle == 'close' }" :style="{ bottom: safeAreaBottom + 'px' }">
+            <view class="bottom-circle d-flex" :style="{ backgroundImage: 'url(/static/images/plant/storage/send_btm_bg_c.png)' }">
+                <view class="flex1 d-flex flex-cln a-c pt-160 pl-30">
+                    <view>
+                        <image class="w-68 h-68" src="@/static/images/plant/storage/xzhwk_icon_sd.png" mode="widthFix" />
+                    </view>
+                    <view class="f-s-28 c-#333">下载货位卡</view>
+                    <view class="f-s-22 c-#999">库存结余清晰</view>
+                </view>
+                <view class="d-flex flex-cln a-c pt-24">
+                     <view>
+                        <image class="w-68 h-68" src="@/static/images/plant/storage/xzsyrk_icon_sd.png" mode="widthFix" />
+                    </view>
+                    <view class="f-s-28 c-#333">新增溯源入库</view>
+                    <view class="f-s-22 c-#999">适合贴有溯源码的种源</view>
+                </view>
+                <view class="flex1 d-flex flex-cln a-c pt-160 pr-30" @click="$u.route({ url: '/plant/storage/seed-source/add/index' })">
+                     <view>
+                        <image class="w-68 h-68" src="@/static/images/plant/storage/xzfsyrk_icon_sd.png" mode="widthFix" />
+                    </view>
+                    <view class="f-s-28 c-#333">新增非溯源入库</view>
+                    <view class="f-s-22 c-#999">适合无法溯源的种源</view>
+                </view>
+                </view>
+        </view>
+    </view>
+</template>
+<script setup lang="ts">
+const windowInfo = uni.getWindowInfo();
+const safeAreaBottom = windowInfo.safeAreaInsets.bottom;
+const btnStyle = ref('add')
+const mapTextBtn = ref<any>({
+    add: '新增种源信息',
+    close: '关闭',
+});
+const clickBtnBall = () => {
+    btnStyle.value = btnStyle.value === 'add' ? 'close' : 'add';
+}
+</script>
+
+<style scoped lang="scss">
+.source-center-view {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    margin: auto;
+    width: 200rpx;
+    z-index: 99;
+    .source-btn-ball {
+        width: 98rpx;
+        height: 98rpx;
+        border-radius: 50%;
+        background-size: contain;
+        background-position: center;
+        background-repeat: no-repeat;
+    }
+}
+.bottom-circle-line {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    height: 1rpx;
+    opacity: 0;
+    transform: translateY(80rpx);
+    pointer-events: none;
+    transition: opacity 0.3s ease, transform 0.3s ease;
+}
+.bottom-circle-line-active {
+    opacity: 1;
+    transform: translateY(0);
+    pointer-events: auto;
+}
+.source-bottom-view {
+    box-shadow: 0px 0px 6rpx 0px #F1F6F4;
+    transition: all 0.3s ease;
+}
+.bottom-circle {
+    position: absolute;
+    width: 750rpx;
+    height: 750rpx;
+    border-radius: 50%;
+    left: 0;
+    bottom: -375rpx;
+    background-size: contain;
+    background-position: top;
+}
+.btn-deg-add {
+    transform: rotate(0);
+    transition: transform 0.3s ease;
+}
+.btn-deg-close {
+    transform: rotate(135deg);
+    transition: transform 0.3s ease;
+}
+</style>

+ 110 - 0
src/plant/storage/seed-source/models/type.ts

@@ -0,0 +1,110 @@
+/**
+ * 入库信息类
+ */
+export interface SeedSourceAddTypeEnum {
+    // 种信息数组
+    seedInfoList?: seedInfoListType[];
+    /** 种源级别 */
+    seedLevel?: string;
+    /** 入库类型 */
+    instoreType: string;
+    /** 入库批号 */
+    batchCode?: string;
+    /** 库房类型 */
+    storeType?: string;
+    /** 库房类型 */
+    storeCode?: string;
+    /** 存放库房 */
+    warehouses?: warehousesType[];
+    /**
+     * 入库业务传输对象
+     */
+    instoreBizInfo: instoreBizInfoType;
+     [property: string]: any;
+}
+// 种源信息返回体
+export interface seedInfoListType {
+    /** 种源类型 */
+    seedType?: string;
+    /** 物种基原 */
+    varietyId?: string;
+    /** 具体品种/品系名称 */
+    seedName?: string;
+    /** 种源来源 */
+    seedSource?: string;
+    /** 受托单位 */
+    entrustId?: string;
+    /** 入库量 */
+    capacity?: number;
+    /** 计量单位 */
+    unit?: string;
+    /** 检验报告 */
+    examinReport?: AccesseryDTO;
+    /** 供应商 */
+    supplierId?: string;
+    /** 供应商名称 */
+    supplier?: string;
+    /** 生产商名称 */
+    producer?: string;
+    /** 菌种/菌株编号 */
+    fungusCode?: string;
+    /** 菌种编码类型 */
+    fungusCodeType?: string;
+    /** 是否有个体标识 */
+    animalIds?: string[];
+    /** 种源图片 */
+    imgs?: AccesseryDTO[];
+    /** 种源视频 */
+    vedios?: AccesseryDTO[];
+    /** 种源产地 */
+    adcode?: string;
+    /** 繁殖材料 */
+    generationMaterial?: string;
+    /** 繁殖地点/采集地点 */
+    generationAdcode?: string;
+    /** 物种鉴定证书 */
+    spCert?: AccesseryDTO[];
+    /** 新品种证书 */
+    newSpCert?: AccesseryDTO[];
+    /** 引种证明 */
+    importCert?: AccesseryDTO[];
+    /** 种源检疫证号 */
+    seedCheckSn?: string;
+     /** 种源检疫证书 */
+    seedCheckCert?: AccesseryDTO[];
+
+    [property: string]: any;
+}
+export interface AccesseryDTO {
+    /**
+     * 文件名称
+     */
+    fileName?: string;
+    /**
+     * 文件大小
+     */
+    fileSize?: number;
+    /**
+     * 文件URL
+     */
+    url?: string;
+    [property: string]: any;
+}
+// 存放库房对象
+export interface warehousesType {
+    /** 仓库id */
+    warehouseId?: string;
+    /** 货架id */
+    shelfId?: string;
+}
+/**
+ * 入库业务传输对象
+ */
+export interface instoreBizInfoType {
+    /** 入库日期 */
+    instoreDate?: string;
+    /** 入库人 */
+    instoreMg?: string;
+    /** 备注 */
+    remark?: string;
+}

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


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


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


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


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


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