Просмотр исходного кода

Merge branch 'master' of http://git.yujin.shuziyunyao.com/yujin/forestry-wx

huangxw 2 недель назад
Родитель
Сommit
ec859a041e

+ 14 - 0
src/pages.json

@@ -404,6 +404,20 @@
                     "style": {
                         "navigationBarTitleText": "加工任务首页"
                     }
+                },
+                //单个/批量入库
+                {
+                    "path": "processing-depstock/index",
+                    "style": {
+                        "navigationBarTitleText": "单个/批量入库"
+                    }
+                },
+                // 加工任务详情
+                {
+                    "path": "processing-detail/index",
+                    "style": {
+                        "navigationBarTitleText": "任务信息详情"
+                    }
                 }
             ]
         },

+ 0 - 1
src/plant/processing/processing-create/index.vue

@@ -155,7 +155,6 @@ import { ref, reactive, getCurrentInstance, type ComponentInternalInstance } fro
 import { useClientRequest } from '@/utils/request';
 import { useInfoStore } from '@/store';
 import Go_button from '@/components/go-button/Go_button.vue';
-
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { pt_process_type, pt_stock_type, pt_standard_type, yes_no } = toRefs<any>(proxy?.useDict('pt_process_type', 'pt_stock_type', 'pt_standard_type', 'yes_no'));
 

+ 289 - 0
src/plant/processing/processing-depstock/index.vue

@@ -0,0 +1,289 @@
+<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="'单个/批量入库'" :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">
+                <up-form-item borderBottom label="添加种源信息" required prop="processOutPutIds">
+                    <view class="flex1">
+                        <template v-for="(item, index) in selectedSeeds" :key="item.id">
+                            <view class="bg-#FBFDFB card-info-block pd-24 p-rtv mb-12">
+                                <view class="d-flex flex1 mb-10">
+                                    <view class="flex1">
+                                        <span class="f-s-34 c-#333 f-w-500 mr-10">{{ item.specnLevel }}</span>
+                                        <span class="f-s-24 c-#666">{{ item.finalSpecn }}{{ item.finalUnit }}{{ selectDictLabel(pt_final_form_type, item.finalFormType) }}</span>
+                                    </view>
+                                    <view class="pr-60">
+                                        <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="d-flex flex-cln">
+                                    <view class="flex1 f-s-28 pr-10 pd2-4-0">
+                                        <span class="c-#666">加工批号:</span>
+                                        <span class="c-#333 f-w-500">{{ item?.processCode || '-' }}</span>
+                                    </view>
+                                    <view class="flex1 f-s-28 pd2-4-0">
+                                        <span class="c-#666">产量:</span>
+                                        <span class="c-#333 f-w-500">{{ item.capacity }}{{ item.unit }}</span>
+                                    </view>
+                                </view>
+                                <view class="close-icon pd-16" @click.stop="deleteSeed(index)">
+                                    <up-icon color="#F81242" name="close" size="32rpx"></up-icon>
+                                </view>
+                            </view>
+                        </template>
+
+                        <up-button type="primary" plain @click="showSelectDialog = true">
+                            <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="入库类型" 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.instoreDate" :maxDate="new Date()" mode="date">
+                    <up-form-item borderBottom label="入库日期" required prop="instoreDate">
+                        <up-input v-model="form.instoreDate" readonly 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="库房类型" required>
+                    <view class="f-s-30 c-ccc f-w-4 flex1">种源库</view>
+                </up-form-item>
+                <!-- 存放库房 -->
+                <up-form-item borderBottom label="存放库房" prop="warehouses" required>
+                    <select-warehouse-input v-model="form.warehouses" title="请选择种源存放库房" :params="{ type: '2' }"></select-warehouse-input>
+                </up-form-item>
+                <!-- 入库人 -->
+                <up-form-item borderBottom label="入库人" required prop="instorer">
+                    <up-input v-model="form.instorer" placeholder="请输入入库人" border="none" clearable></up-input>
+                </up-form-item>
+                <!-- 入库备注 -->
+                <up-form-item label="入库备注" prop="remark">
+                    <up-textarea v-model="form.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>
+
+    <!-- 选择种子弹窗 -->
+    <select-seed-dialog v-model="showSelectDialog" :process-id="processId" @confirm="handleSeedConfirm" />
+</template>
+
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+import { formItemBtnStyle } from '@/assets/styles/uview-plus';
+import { parseTime } from '@/utils/ruoyi';
+import SelectWarehouseInput from '@/models/select-warehouse-input/select-warehouse-input.vue';
+import SelectSeedDialog from './models/select-seed-dialog.vue';
+import { useInfoStore } from '@/store';
+
+const infoStore = useInfoStore();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_seed_instore_type, pt_warehouse_type, pt_final_form_type } = toRefs<any>(proxy?.useDict('pt_seed_instore_type', 'pt_warehouse_type', 'pt_final_form_type'));
+
+// 表单与分页等基础状态
+const paging = ref<any>(null);
+const upFormRef = ref<any>(null);
+
+// 表单数据
+const form = ref({
+    instoreType: '4',
+    storageType: '2',
+    batchCode: '',
+    warehouses: [] as any[],
+    instoreDate: parseTime(new Date(), '{y}-{m}-{d}'),
+    instorer: infoStore.userInfo?.name || '',
+    remark: '',
+    processOutPutIds: [] as any[],
+});
+
+const rules = reactive({
+    processOutPutIds: [{ required: true, message: '请选择要入库的种子' }],
+    instoreType: [{ required: true, message: '请选择入库类型' }],
+    instoreDate: [{ required: true, message: '请选择入库日期' }],
+    batchCode: [{ required: true, message: '请输入入库批号' }],
+    instorer: [{ required: true, message: '请输入入库人' }],
+    warehouses: [{ required: true, message: '请选择存放库房' }],
+});
+
+// 选中的种子列表
+const selectedSeeds = ref<any[]>([]);
+const showSelectDialog = ref(false);
+
+// 处理种子选择确认
+const handleSeedConfirm = (ids: number[]) => {
+    // 根据 ID 过滤出选中的种子
+    selectedSeeds.value = seedList.value.filter((item) => ids.includes(item.id));
+    console.log(selectedSeeds.value, 'ids');
+};
+
+// 种子列表(用于过滤)
+const seedList = ref<any[]>([]);
+
+// 删除种子
+const deleteSeed = (index: number) => {
+    selectedSeeds.value.splice(index, 1);
+};
+
+// 提交表单
+const submitForm = async () => {
+    uni.$u.debounce(
+        async () => {
+            try {
+                form.value.processOutPutIds = selectedSeeds.value.map((item) => item.id);
+                await upFormRef.value?.validate();
+            } catch (error: any) {
+                // 滚动到第一个错误字段
+                const firstErrorField = error && error[0].prop + 'pppp';
+                paging.value?.scrollIntoViewById(firstErrorField, 30, true);
+                return;
+            }
+
+            // 验证是否选择了种子
+            if (selectedSeeds.value.length === 0) {
+                uni.showToast({
+                    title: '请选择要入库的种子',
+                    icon: 'none',
+                });
+                return;
+            }
+
+            uni.showLoading({
+                title: '提交中...',
+            });
+
+            // 构建提交参数
+            const params = {
+                processOutPutIds: selectedSeeds.value.map((item) => item.id),
+                batchCode: form.value.batchCode,
+                warehouses: form.value.warehouses.map((w) => ({
+                    warehouseId: w.warehouseId,
+                    shelfId: w.shelfId || 0,
+                })),
+                instoreType: form.value.instoreType,
+                instorer: form.value.instorer,
+                remark: form.value.remark,
+                instoreMg: form.value.instorer,
+                instoreDate: form.value.instoreDate,
+            };
+
+            try {
+                const res = await useClientRequest.post('/plt-api/app/processOutPut/outPutInstore', params);
+                if (!res || res.code !== 200) return;
+                uni.hideLoading();
+                uni.showToast({
+                    title: '提交成功',
+                    icon: 'success',
+                });
+                uni.$emit('refreshStorageRoomList');
+                // 返回上一页
+                setTimeout(() => {
+                    uni.navigateBack({
+                        delta: 1,
+                    });
+                }, 1500);
+            } catch (error) {
+                uni.hideLoading();
+            }
+        },
+        500,
+        true,
+    );
+};
+
+// 点击随机生成服务端生成唯一的批号
+const generateBatchCode = async () => {
+    uni.showLoading({
+        title: '生成中...',
+    });
+    const res = await useClientRequest.post('/plt-api/app/plantationTask/getBatchCode', {
+        plType: 'Z',
+        linkType: 'I',
+    });
+    if (res && res.code === 200) {
+        uni.hideLoading();
+        form.value.batchCode = res.data;
+        uni.showToast({
+            title: '批号生成成功',
+            icon: 'success',
+        });
+    }
+};
+
+// 监听弹窗打开,获取种子列表用于后续过滤
+watch(
+    () => showSelectDialog.value,
+    async (val) => {
+        if (val) {
+            try {
+                const res = await useClientRequest.get('/plt-api/app/processOutPut/pageList', {
+                    pageNum: 1,
+                    pageSize: 100,
+                });
+                if (res && res.code === 200) {
+                    seedList.value = res.rows || [];
+                }
+            } catch (error) {
+                console.error(error);
+            }
+        }
+    },
+);
+const processId = ref<any>();
+onLoad((optins: any) => {
+    processId.value = optins?.processId;
+    console.log(optins, 'processId.value');
+});
+</script>
+
+<style lang="scss" scoped>
+.card-info-block {
+    border: 1rpx solid #afddbb;
+    border-radius: 10rpx;
+}
+
+.tag-span {
+    padding: 4rpx 12rpx;
+    font-size: 20rpx;
+    border-radius: 18rpx;
+}
+
+.close-icon {
+    position: absolute;
+    top: 0;
+    right: 0;
+    z-index: 10;
+}
+</style>

+ 141 - 0
src/plant/processing/processing-depstock/models/select-seed-dialog.vue

@@ -0,0 +1,141 @@
+<template>
+    <up-popup v-model:show="visible" mode="right" :round="20" :closeOnClickOverlay="false" @close="visible = false">
+        <ut-navbar :fixed="false" bgColor="transparent" :breadcrumb="false">
+            <template #left>
+                <view class="c-#333 f-s-34 f-w-5">请选择要入库的种子</view>
+            </template>
+        </ut-navbar>
+        <view class="w-700 d-flex flex-cln bg-#f7f7f7" id="scroll">
+            <scroll-view class="popup-container" :style="`height: calc(100vh - 208rpx)`" scroll-y>
+                <!-- 列表区域 -->
+                <view class="list-container">
+                    <template v-for="(item, index) in list" :key="item.id">
+                        <processing-output-item :item="item" :index="index" :selectable="true" :selected="selectedIds.includes(item.id)" :showIndex="true" @click="toggleSelect(item)" />
+                    </template>
+                </view>
+                <!-- 底部按钮 -->
+                <view class="w-700 bg-#fff h-100 d-flex a-c gap-20 pt-24 pb-24 bottom-btns z-index-20" style="position: fixed; bottom: 0; right: 0">
+                    <up-button @click="handleCancel" :customStyle="{ flex: 1, marginRight: '10rpx' }">取消</up-button>
+                    <up-button @click="handleConfirm" type="primary" :customStyle="{ flex: 1, marginLeft: '10rpx' }">确认选择</up-button>
+                </view>
+            </scroll-view>
+        </view>
+    </up-popup>
+</template>
+
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+import ProcessingOutputItem from '@/plant/processing/processing-detail-list/models/processing-output-item.vue';
+const instance = getCurrentInstance();
+const props = defineProps({
+    modelValue: {
+        type: Boolean,
+        default: false,
+    },
+    processId: {
+        type: [Number, String],
+        default: '',
+    },
+});
+
+const emit = defineEmits<{
+    'update:modelValue': [value: boolean];
+    confirm: [ids: number[]];
+}>();
+const top = ref(0);
+const visible = computed({
+    get: () => props.modelValue,
+    set: (val) => emit('update:modelValue', val),
+});
+
+const list = ref<any[]>([]);
+const selectedIds = ref<number[]>([]);
+
+// 获取种子列表
+const getList = async () => {
+    try {
+        const res = await useClientRequest.get('/plt-api/app/processOutPut/pageList', {
+            pageNum: 1,
+            pageSize: 100,
+            processId: props.processId,
+        });
+        if (res && res.code === 200) {
+            list.value = res.rows || [];
+            // 默认全部选中
+            selectedIds.value = list.value.map((item) => item.id);
+        }
+    } catch (error) {
+        console.error(error);
+    }
+};
+
+// 切换选中状态
+const toggleSelect = (item: any) => {
+    const index = selectedIds.value.indexOf(item.id);
+    if (index > -1) {
+        selectedIds.value.splice(index, 1);
+    } else {
+        selectedIds.value.push(item.id);
+    }
+};
+
+// 取消
+const handleCancel = () => {
+    visible.value = false;
+};
+
+// 确认选择
+const handleConfirm = () => {
+    if (selectedIds.value.length === 0) {
+        uni.showToast({
+            title: '请至少选择一个种子',
+            icon: 'none',
+        });
+        return;
+    }
+    emit('confirm', selectedIds.value);
+    visible.value = false;
+};
+
+// 监听弹窗打开,加载数据
+watch(
+    () => visible.value,
+    (val) => {
+        if (val) {
+            getList();
+        }
+    },
+    { immediate: true },
+);
+onMounted(() => {
+    const querys = uni.createSelectorQuery().in(instance?.proxy);
+    querys
+        .select('#scroll')
+        .boundingClientRect((data: any) => {
+            top.value = data.top;
+            console.log(top.value, 'top');
+        })
+        .exec();
+});
+</script>
+
+<style lang="scss" scoped>
+.popup-container {
+    height: 70vh;
+    display: flex;
+    flex-direction: column;
+}
+
+.list-container {
+    flex: 1;
+    overflow-y: auto;
+    padding: 24rpx;
+    padding-bottom: 120rpx;
+    background-color: #f7f7f7;
+}
+
+.bottom-btns {
+    background-color: #fff;
+    border-top: 1rpx solid #eee;
+}
+</style>

+ 24 - 3
src/plant/processing/processing-detail-list/index.vue

@@ -4,7 +4,7 @@
             <ut-navbar title="加工任务详情" :fixed="false"> </ut-navbar>
         </template>
         <view class="pd-24">
-            <view class="bg-#fff pd-24 pt-16 b-radius p-rtv">
+            <view class="bg-#fff pd-24 pt-16 b-radius p-rtv" @click="gotoDetail">
                 <!-- 任务类型标签 -->
                 <view v-if="+taskDetail?.processType == 1 && +taskDetail?.processMedType == 1" class="bg-#91C747 c-#fff f-w-5 pd-10 pt-4 pb-4 f-s-20" style="border-radius: 16rpx 0 16rpx 0; width: max-content; position: absolute; top: 0rpx; left: 0rpx">种子初加工</view>
                 <view v-if="+taskDetail?.processType == 1 && +taskDetail?.processMedType == 2" class="bg-#C7A962 c-#fff f-w-5 pd-10 pt-4 pb-4 f-s-20" style="border-radius: 16rpx 0 16rpx 0; width: max-content; position: absolute; top: 0rpx; left: 0rpx">药材初加工</view>
@@ -50,7 +50,7 @@
                     </view>
                     <!-- 去修改按钮 -->
                     <view class="d-flex a-c j-ed pd2-4-0">
-                        <view class="c-primary f-s-28 d-flex a-c" @click="goEdit">
+                        <view class="c-primary f-s-28 d-flex a-c" @click.stop="goEdit">
                             <span>去修改</span>
                             <up-icon name="arrow-right" size="24rpx" class="ml-5"></up-icon>
                         </view>
@@ -148,7 +148,7 @@
                     <view class="c-#999 f-s-28">产出物:</view>
                     <view class="c-#999 f-s-28">{{ outputList.length }}个</view>
                     <view class="flex1"></view>
-                    <up-button color="#18BECA" style="width: 210rpx; height: 60rpx; margin-right: 20rpx">单个/批量入库</up-button>
+                    <up-button v-if="+taskDetail?.processType == 1 && +taskDetail?.processMedType == 1" color="#18BECA" style="width: 210rpx; height: 60rpx; margin-right: 20rpx" @click="goToBatchInstore">单个/批量入库</up-button>
                     <up-button type="primary" style="width: 160rpx; height: 60rpx" @click="handleShowOutputModel">添加产出</up-button>
                 </view>
                 <up-swipe-action>
@@ -213,6 +213,7 @@ const query = async (pageNum: number, pageSize: number) => {
             const { rows } = res;
             paging.value.complete(rows);
         }
+        getOutputList();
     } catch (error) {
         console.error('加载原料列表失败:', error);
         paging.value.complete([]);
@@ -264,6 +265,15 @@ const goEdit = () => {
     });
 };
 
+// 跳转到详情页
+const gotoDetail = () => {
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/processing/processing-detail/index',
+        params: { id: taskId.value },
+    });
+};
+
 // 监听修改成功事件,重新加载任务详情
 const handleUpdateTaskDetail = () => {
     loadTaskDetail(); // 重新加载任务详情
@@ -385,6 +395,17 @@ const handleDeleteOutput = async (outPutId: string | number, item: any) => {
         console.error('删除失败:', error);
     }
 };
+
+// 跳转到单个/批量入库页面
+const goToBatchInstore = () => {
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/processing/processing-depstock/index',
+        params: {
+            processId: taskId.value,
+        },
+    });
+};
 </script>
 
 <style scoped lang="scss">

+ 26 - 23
src/plant/processing/processing-detail-list/models/outputInfo.vue

@@ -1,7 +1,7 @@
 <template>
     <up-popup :show="show" mode="bottom" @close="handleClose" :round="20" closeable>
         <view class="d-flex flex-cln h-100%" style="max-height: 70vh">
-            <view class="f-s-34 f-w-5 pd-24 pb-0">{{ getTitle() }}</view>
+            <view class="f-s-34 f-w-5 pd-24 pb-16">{{ getTitle() }}</view>
             <scroll-view scroll-y class="h-0 flex1">
                 <view class="pd-24">
                     <up-form ref="formRef" :model="formData" :rules="rules" labelPosition="top" labelWidth="auto">
@@ -16,13 +16,29 @@
                                 </view>
                             </up-form-item>
                             <!-- 产量 -->
-                            <up-form-item borderBottom label="产量" prop="capacity" required>
-                                <view class="d-flex a-c w-100%">
-                                    <up-input v-model="formData.capacity" type="number" placeholder="请输入产量" border="none" clearable></up-input>
-                                    <ut-action-sheet v-model="formData.unit" :tabs="unitList" title="选择单位" style="margin-left: 10rpx"></ut-action-sheet>
+                            <up-form-item label="产量" prop="capacity" required>
+                                <view class="flex1 d-flex">
+                                    <view class="flex1 ov-hd" id="capacitypppp">
+                                        <up-form-item border-bottom prop="capacity" class="form-item-top-padding-0">
+                                            <up-input v-model="formData.capacity" type="number" placeholder="请输入产量" border="none" clearable></up-input>
+                                        </up-form-item>
+                                    </view>
+                                    <view class="pd-5"></view>
+                                    <view class="min-w-100">
+                                        <ut-action-sheet v-model="formData.unit" :tabs="pt_out_put_unit" title="选择单位">
+                                            <up-form-item border-bottom prop="unit" class="form-item-top-padding-0">
+                                                <view class="flex1" style="line-height: 24px">
+                                                    <view v-if="formData?.unit" class="f-s-30 c-#333 f-w-5 flex1">{{ formData?.unit }}</view>
+                                                    <view v-else class="f-s-30 c-ccc f-w-4 flex1">单位</view>
+                                                </view>
+                                                <template #right>
+                                                    <up-icon size="22rpx" color="#2A6D52" name="arrow-down-fill"></up-icon>
+                                                </template>
+                                            </up-form-item>
+                                        </ut-action-sheet>
+                                    </view>
                                 </view>
                             </up-form-item>
-
                             <!-- 产出物图片 -->
                             <up-form-item borderBottom label="产出物图片">
                                 <ut-upload v-model="formData.imgs" :max-count="6" valueType="array" accept="image" width="210rpx" height="210rpx" style="card"></ut-upload>
@@ -46,7 +62,7 @@
                                 </view>
                             </up-form-item>
                             <!-- 产量 -->
-                            <up-form-item borderBottom label="产量" prop="capacity" required>
+                            <up-form-item label="产量" prop="capacity" required>
                                 <view class="flex1 d-flex">
                                     <view class="flex1 ov-hd" id="capacitypppp">
                                         <up-form-item border-bottom prop="capacity" class="form-item-top-padding-0">
@@ -55,7 +71,7 @@
                                     </view>
                                     <view class="pd-5"></view>
                                     <view class="min-w-100">
-                                        <ut-action-sheet v-model="formData.unit" :tabs="unitList" title="选择单位">
+                                        <ut-action-sheet v-model="formData.unit" :tabs="pt_out_put_unit" title="选择单位">
                                             <up-form-item border-bottom prop="unit" class="form-item-top-padding-0">
                                                 <view class="flex1" style="line-height: 24px">
                                                     <view v-if="formData?.unit" class="f-s-30 c-#333 f-w-5 flex1">{{ formData?.unit }}</view>
@@ -134,7 +150,7 @@
 <script setup lang="ts">
 import { useClientRequest } from '@/utils/request';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { pt_final_form_type, pt_final_unit } = toRefs<any>(proxy?.useDict('pt_final_form_type', 'pt_final_unit'));
+const { pt_final_form_type, pt_final_unit, pt_out_put_unit } = toRefs<any>(proxy?.useDict('pt_final_form_type', 'pt_final_unit', 'pt_out_put_unit'));
 const props = defineProps<{
     show: boolean;
     type: number; // 1: 初加工,2: 趁鲜切制
@@ -146,21 +162,8 @@ const emit = defineEmits<{
     'update:show': [value: boolean];
     confirm: [data: any];
 }>();
-setTimeout(() => {
-    console.log(pt_final_unit);
-}, 2000);
+
 const formRef = ref();
-const unitList = ref<any[]>([
-    {
-        label: 'kg',
-        value: 'kg',
-    },
-    {
-        label: '吨',
-        value: '吨',
-    },
-]); // 单位列表(先空着)
-const finalFormTypeList = ref<any[]>([]); // 切制形态列表 (pt_final_form_type)
 
 // 表单数据
 const formData = ref({

+ 19 - 6
src/plant/processing/processing-detail-list/models/processing-output-item.vue

@@ -1,5 +1,5 @@
 <template>
-    <view class="relative bg-#fff b-radius pd-24 d-flex a-c" :class="{ 'bg-#EDF7F0': selected && selectable }" @click="handleClick">
+    <view class="relative b-radius pd-24 d-flex a-c bg-#fff select-item" :class="{ actives: selected && selectable }" @click="handleClick">
         <!-- 序号标签 -->
         <view v-if="showIndex" class="absolute top-0 left-0 w-60 h-60 c-#fff f-s-20 f-w-5 pd-4 pt-4 pb-4 z-index-10" style="border-radius: 16rpx 0 0rpx 0; background: linear-gradient(135deg, #22c55e 50%, transparent 50%)">
             <span class="w-30 h-30 f-s-24 f-w-5" style="transform: rotate(-45deg); display: block">{{ String(index + 1).padStart(2, '0') }}</span>
@@ -13,7 +13,7 @@
             <!-- 左侧:品名和规格 -->
             <view class="flex flex-cln">
                 <view class="f-s-34 f-w-5 c-#333 mb-4">{{ item?.specnLevel }}</view>
-                <view class="f-s-24 c-#999">{{ item?.finalSpecn }}{{ item?.finalUnit }}{{ item?.finalFormType }}</view>
+                <view class="f-s-24 c-#999">{{ item?.finalSpecn }}{{ item?.finalUnit }}{{ selectDictLabel(pt_final_form_type, item?.finalFormType) }}</view>
             </view>
             <!-- 中间:重量和检验状态 -->
             <view class="flex flex-cln a-c">
@@ -28,13 +28,14 @@
             </view>
         </view>
         <!-- 选中对勾图标 -->
-        <view v-if="selected && selectable" class="absolute bottom-24 right-24 w-40 h-40 bg-#37a954 d-flex a-c j-c radius-8">
-            <up-icon name="checkmark" color="#fff" size="24rpx"></up-icon>
-        </view>
+        <image v-if="selected && selectable" class="w-40 h-40 checked-icon" src="/static/images/common/btn_checked_icon.png" mode="widthFix" />
     </view>
+    <view class="h-16"></view>
 </template>
 
 <script setup lang="ts">
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_final_form_type } = toRefs<any>(proxy?.useDict('pt_final_form_type'));
 const props = defineProps({
     // 单个产出项数据
     item: {
@@ -78,5 +79,17 @@ const handleClick = () => {
 </script>
 
 <style scoped lang="scss">
-// 组件样式使用 UnoCSS 原子类,无需额外样式
+.select-item {
+    border: 1rpx solid transparent;
+
+    .checked-icon {
+        position: absolute;
+        right: 0rpx;
+        bottom: 0rpx;
+    }
+}
+.actives {
+    background-color: #ebf6ee;
+    border: 1rpx solid #37a954;
+}
 </style>

+ 194 - 0
src/plant/processing/processing-detail/index.vue

@@ -0,0 +1,194 @@
+<template>
+    <z-paging ref="paging" bgColor="#f7f7f7" safe-area-inset-bottom>
+        <template #top>
+            <ut-navbar title="任务信息详情" :fixed="false"></ut-navbar>
+        </template>
+        <template>
+            <!-- 加工信息区块 -->
+            <view class="bg-#fff pd-24 mb-16">
+                <view class="pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">加工方式:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.processType ? selectDictLabel(pt_process_type, form?.processType) : '--' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">加工对象:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.processMedType ? selectDictLabel(pt_stock_type, form?.processMedType) : '--' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">加工{{ +form?.processMedType == 1 ? '植物/品种' : '品种' }}:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.varietyName || '--' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">加工日期:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.processingDate || '--' }}</text>
+                </view>
+
+                <view v-if="+form?.processType == 2" class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">是否属于趁鲜切制目录品种:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.freshCatalogueStatus ? selectDictLabel(yes_no, form?.freshCatalogueStatus) : '--' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">{{ +form?.processType == 2 ? '生产' : '加工' }}批号:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.processCode || '--' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">{{ +form?.processType == 2 ? '执行' : '加工执行' }}标准:</text>
+                    <text class="c-#333 f-s-30 f-w-5">
+                        <template v-if="+form?.processType == 1">
+                            {{ form?.standardType ? selectDictLabel(pt_standard_type, form?.standardType) : '--' }}
+                        </template>
+                        <template v-else>
+                            {{ form?.standardDetailName || '--' }}
+                        </template>
+                    </text>
+                </view>
+
+                <view v-if="+form?.processType == 1" class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">具体标准名称:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.standardDetailName || '--' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">加工负责人:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.contactName || '--' }}</text>
+                </view>
+
+                <view class="d-flex flex-cln pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30 mb-10">加工工艺及流程:</text>
+                    <view v-if="form?.ptech" class="d-flex a-c flex-wrap gap-10">
+                        <template v-for="(item, index) in form?.ptech?.split(',')" :key="index">
+                            <span v-if="index !== 0" class="c-#999 f-s-32 ml-10 mr-10">→ </span>
+                            <span class="f-s-32">{{ item }}</span>
+                        </template>
+                    </view>
+                    <text v-else class="c-#999 f-s-30">--</text>
+                </view>
+
+                <view class="d-flex flex-cln pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30 mb-10">加工图片:</text>
+                    <ut-album v-if="form?.imgs?.length > 0" :urls="form?.imgs"></ut-album>
+                    <text v-else class="c-#999 f-s-30">-</text>
+                </view>
+
+                <view class="d-flex flex-cln pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30 mb-10">加工视频:</text>
+                    <ut-album v-if="form?.videos?.length > 0" :urls="form?.videos" :video="true"></ut-album>
+                    <text v-else class="c-#999 f-s-30">-</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">最新修改人:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.operatorName || '-' }}</text>
+                </view>
+
+                <view class="pt-16 pb-16 info-border-bottom">
+                    <text class="c-#666 f-s-30">最新修改时间:</text>
+                    <text class="c-#333 f-s-30 f-w-5">{{ form?.operatorTime || '-' }}</text>
+                </view>
+
+                <view class="d-flex j-c pt-32">
+                    <up-button type="primary" class="b-radius w-300 h-80 f-s-32" @click="handleEdit">修改</up-button>
+                </view>
+            </view>
+        </template>
+    </z-paging>
+</template>
+
+<script setup lang="ts">
+import { ref, getCurrentInstance, type ComponentInternalInstance } from 'vue';
+import { useClientRequest } from '@/utils/request';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_process_type, pt_stock_type, pt_standard_type, yes_no } = toRefs<any>(proxy?.useDict('pt_process_type', 'pt_stock_type', 'pt_standard_type', 'yes_no'));
+
+// 表单数据
+const form = ref<any>({
+    processType: '',
+    processMedType: '',
+    varietyName: '',
+    processingDate: '',
+    processCode: '',
+    standardType: '',
+    standardDetailName: '',
+    contactName: '',
+    ptech: '',
+    imgs: [],
+    videos: [],
+    freshCatalogueStatus: '',
+    operatorName: '',
+    updateTime: '',
+    createTime: '',
+});
+
+const processId = ref('');
+
+// 获取详情
+const getDetail = async () => {
+    try {
+        const res = await useClientRequest.get(`/plt-api/app/processe/getInfoById/${processId.value}`);
+        if (res.code === 200 && res.data) {
+            const data = res.data;
+            form.value = {
+                processType: data.processType || '',
+                processMedType: data.processMedType || '',
+                varietyName: data.variety || data.medicineName || '',
+                processingDate: data.processingDate || '',
+                processCode: data.processCode || '',
+                standardType: data.standardType || '',
+                standardDetailName: data.standardDetailName || '',
+                contactName: data.contactName || '',
+                ptech: data.ptech || '',
+                imgs: data.processImages ? (typeof data.processImages === 'string' ? JSON.parse(data.processImages) : data.processImages) : [],
+                videos: data.processVideos ? (typeof data.processVideos === 'string' ? JSON.parse(data.processVideos) : data.processVideos) : [],
+                freshCatalogueStatus: data.freshCatalogueStatus !== undefined ? data.freshCatalogueStatus : '',
+                operatorName: data.operatorName || '',
+                updateTime: data.updateTime || '',
+                createTime: data.createTime || '',
+            };
+        }
+    } catch (error) {
+        console.error('获取详情失败:', error);
+        uni.showToast({
+            title: '获取详情失败',
+            icon: 'none',
+        });
+    }
+};
+
+// 修改
+const handleEdit = () => {
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/processing/processing-create/index',
+        params: {
+            id: processId.value,
+            edit: '1',
+            taskType: form.value.processType,
+        },
+    });
+};
+
+onLoad((options: any) => {
+    processId.value = options?.id || '';
+    if (processId.value) {
+        getDetail();
+    }
+});
+</script>
+
+<style scoped lang="scss">
+.breadcrumb-box {
+    background-color: #e8f5e9;
+    padding-top: 16rpx;
+    padding-bottom: 16rpx;
+}
+
+.info-border-bottom {
+    border-bottom: 1rpx solid #f0f0f0;
+}
+</style>

+ 21 - 47
src/tools/species-info-process/index.vue

@@ -17,16 +17,10 @@
             </view>
         </view>
         <template v-for="(item, index) in list" :key="index">
-            <info-card :item="item" :selected="selectedItems.has(item.id)" @click="toggleSelection(item)" />
+            <info-card :item="item" :selected="selectedItems?.id === item.id" @click="toggleSelection(item)" />
         </template>
         <template #bottom>
-            <view v-if="formDate.inputs.length > 0" class="bg-#EBF6EE c-primary f-s-24 pd-10 pl-24">
-                已选择种源:
-                <template v-for="(item, index) in formDate.inputs" :key="index">
-                    <text v-if="index !== 0">、</text>
-                    {{ item.variety }}
-                </template>
-            </view>
+            <view v-if="selectedItems" class="bg-#EBF6EE c-primary f-s-24 pd-10 pl-24"> 已选择种源:{{ selectedItems.variety }} </view>
             <view class="pd-20 d-flex">
                 <up-button type="primary" @click="open">确认选择</up-button>
             </view>
@@ -45,9 +39,7 @@
                 <up-form class="p-rtv" labelPosition="top" :model="formDate" :rules="rules" labelWidth="auto" ref="upFormRef">
                     <up-form-item :borderBottom="false" prop="inputs" id="inputspppp">
                         <view class="d-flex flex-cln" style="width: 100%">
-                            <template v-for="(item, index) in Array.from(selectedItems.values())" :key="index">
-                                <souceinfo showClose :data="item" :index="index" v-model:inputs="formDate.inputs[index]" @close="handleSourceClose" />
-                            </template>
+                            <souceinfo v-if="selectedItems" :data="selectedItems" :index="0" v-model:inputs="formDate.inputs[0]" @close="handleSourceClose" />
                         </view>
                     </up-form-item>
                 </up-form>
@@ -125,7 +117,8 @@ const rules = ref({
     inputs: [{ validator: validateInputs, trigger: 'blur' }],
 });
 
-const selectedItems = ref(new Map<string | number, SeedItem>());
+// 单选模式:存储当前选中的单个项目
+const selectedItems = ref<SeedItem | null>(null);
 const query = async (pageNo: number, pageSize: number) => {
     const params = {
         pageNo,
@@ -141,25 +134,22 @@ const changeSeach = () => {
 };
 
 const toggleSelection = (item: SeedItem) => {
-    const newMap = new Map(selectedItems.value);
-    if (newMap.has(item.id)) {
-        // 取消选择
-        newMap.delete(item.id);
-        formDate.value.inputs = formDate.value.inputs.filter((inputItem: any) => inputItem.storageId !== item.id);
+    if (selectedItems.value?.id === item.id) {
+        // 如果点击的是已选项,则取消选择
+        selectedItems.value = null;
+        formDate.value.inputs = [];
     } else {
-        // 防止重复添加
-        if (!formDate.value.inputs.some((inputItem: any) => inputItem.storageId === item.id)) {
-            formDate.value.inputs.push({
+        // 选择新项(自动取消之前的选择)
+        selectedItems.value = item;
+        formDate.value.inputs = [
+            {
                 storageId: item.id,
                 inputAmount: '',
                 variety: item?.variety,
-            });
-        }
-        newMap.set(item.id, item);
+            },
+        ];
     }
-
-    selectedItems.value = newMap;
-    console.log('当前选中的种子:', Array.from(newMap.keys()));
+    console.log('当前选中的种子:', selectedItems.value);
     console.log('表单数据:', formDate.value.inputs);
 };
 
@@ -169,10 +159,8 @@ const show = ref(false);
 const open = () => {
     // 打开逻辑,比如设置 show 为 true
     show.value = true;
-    // 获取所有选中的完整对象
-    const selectedArray = Array.from(selectedItems.value.values());
-    console.log('选中的完整项目:', selectedArray);
-    // 这里可以使用 selectedArray 进行后续处理
+    // 获取当前选中的单个对象
+    console.log('选中的项目:', selectedItems.value);
 };
 
 const close = () => {
@@ -181,24 +169,10 @@ const close = () => {
     // console.log('close');
 };
 
-// 处理种源信息关闭事件
+// 处理种源信息关闭事件(单选模式:直接取消选择)
 const handleSourceClose = (index: number) => {
-    // 根据索引找到对应的项目
-    const selectedArray = Array.from(selectedItems.value.values());
-    if (index >= 0 && index < selectedArray.length) {
-        const item = selectedArray[index];
-        console.log(item, 'item');
-
-        const newMap = new Map(selectedItems.value);
-
-        // 从 selectedItems 中删除对应的项目
-        newMap.delete(item.id);
-        selectedItems.value = newMap;
-
-        // 从 formDate.inputs 中删除对应的数据
-        // 注意:由于删除后数组索引会变化,我们需要根据 storageId 来过滤
-        formDate.value.inputs = formDate.value.inputs.filter((input: any) => input.storageId !== item.id);
-    }
+    selectedItems.value = null;
+    formDate.value.inputs = [];
 };
 const upFormRef = ref();
 //校验表单然后提交