Pārlūkot izejas kodu

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

huangxw 2 nedēļas atpakaļ
vecāks
revīzija
221638f527

+ 9 - 1
pnpm-lock.yaml

@@ -65,6 +65,9 @@ importers:
       dayjs:
         specifier: ^1.11.13
         version: 1.11.19
+      number-precision:
+        specifier: ^1.6.0
+        version: 1.6.0
       pinia:
         specifier: ^2.0.36
         version: 2.3.1(typescript@4.9.5)(vue@3.5.26(typescript@4.9.5))
@@ -3068,7 +3071,7 @@ packages:
 
   glob@7.2.3:
     resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
-    deprecated: Glob versions prior to v9 are no longer supported
+    deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
 
   global@4.4.0:
     resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==}
@@ -3701,6 +3704,9 @@ packages:
     resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
     engines: {node: '>=8'}
 
+  number-precision@1.6.0:
+    resolution: {integrity: sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==}
+
   nwsapi@2.2.23:
     resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==}
 
@@ -9527,6 +9533,8 @@ snapshots:
     dependencies:
       path-key: 3.1.1
 
+  number-precision@1.6.0: {}
+
   nwsapi@2.2.23: {}
 
   object-inspect@1.13.4: {}

+ 6 - 1
src/pages/plant/processing/index.vue

@@ -1,7 +1,9 @@
 <template>
     <z-paging ref="paging" bgColor="#F7F7F7">
         <template #top>
-            <up-navbar title="加工及包装赋码任务" :fixed="false" :isLeftBack="false" :breadcrumb="false"> </up-navbar>
+            <ut-navbar title="加工及包装赋码任务" :fixed="false" :breadcrumb="false">
+                <template #left> </template>
+            </ut-navbar>
         </template>
         <view class="base-content pd-20">
             <view class="bg-#fff d-flex a-c j-c radius-16 pd2-30-24 mb-20" @click="$u.route({ url: '/plant/processing/processing-index/index' })">
@@ -21,6 +23,9 @@
                 <up-icon name="arrow-right"></up-icon>
             </view>
         </view>
+        <template #bottom>
+            <ut-tabar activeTab="processing"></ut-tabar>
+        </template>
     </z-paging>
 </template>
 <script setup lang="ts"></script>

+ 3 - 27
src/plant/processing/processing-depstock/index.vue

@@ -142,16 +142,11 @@ const rules = reactive({
 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 handleSeedConfirm = (items: any[]) => {
+    selectedSeeds.value = items;
 };
 
-// 种子列表(用于过滤)
-const seedList = ref<any[]>([]);
-
 // 删除种子
 const deleteSeed = (index: number) => {
     selectedSeeds.value.splice(index, 1);
@@ -242,25 +237,6 @@ const generateBatchCode = async () => {
     }
 };
 
-// 监听弹窗打开,获取种子列表用于后续过滤
-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;

+ 7 - 6
src/plant/processing/processing-depstock/models/select-seed-dialog.vue

@@ -15,8 +15,8 @@
                 </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>
+                    <up-button @click="handleCancel" :customStyle="{ flex: 1, marginRight: '10rpx', marginLeft: '10rpx' }">取消</up-button>
+                    <up-button @click="handleConfirm" type="primary" :customStyle="{ flex: 1, marginRight: '10rpx', marginLeft: '10rpx' }">确认选择</up-button>
                 </view>
             </scroll-view>
         </view>
@@ -40,7 +40,7 @@ const props = defineProps({
 
 const emit = defineEmits<{
     'update:modelValue': [value: boolean];
-    confirm: [ids: number[]];
+    confirm: [items: any[]];
 }>();
 const top = ref(0);
 const visible = computed({
@@ -93,11 +93,13 @@ const handleConfirm = () => {
         });
         return;
     }
-    emit('confirm', selectedIds.value);
+    // 返回选中的完整对象数据
+    const selectedItems = list.value.filter((item) => selectedIds.value.includes(item.id));
+    emit('confirm', selectedItems);
     visible.value = false;
 };
 
-// 监听弹窗打开,加载数据
+// 监听弹窗打开,加载数据(弹窗打开时)
 watch(
     () => visible.value,
     (val) => {
@@ -105,7 +107,6 @@ watch(
             getList();
         }
     },
-    { immediate: true },
 );
 onMounted(() => {
     const querys = uni.createSelectorQuery().in(instance?.proxy);

+ 25 - 14
src/plant/processing/processing-detail-list/index.vue

@@ -59,11 +59,11 @@
             </view>
             <!-- Tab 切换 -->
             <view class="d-flex a-c bg-#f7f7f7 mb-16">
-                <ut-tabs v-model="activeTab" :tabs="tabs" @change="onTabChange"></ut-tabs>
+                <up-tabs :list="tabs" @change="onTabChange" :current="activeTab" lineWidth="60"></up-tabs>
             </view>
             <!-- 原料信息列表 -->
-            <view v-if="activeTab == '0'">
-                <view v-if="list.length === 0 && activeTab == '0'" class="d-flex flex-cln a-c pd-40">
+            <view v-if="+activeTab == 0">
+                <view v-if="list.length === 0 && +activeTab == 0" class="d-flex flex-cln a-c pd-40">
                     <ut-empty color="#ccc" size="28rpx" image=" https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/noEmpty.png">暂无加工原料信息</ut-empty>
                     <up-button type="primary" @click="goAssociate">去关联原料信息</up-button>
                 </view>
@@ -178,15 +178,15 @@ const taskId = ref('');
 const taskDetail = ref<any>({});
 const outputList = ref<any[]>([]);
 
-const activeTab = ref('0');
+const activeTab = ref(0);
 const tabs = [
     {
-        label: '原料信息',
-        value: '0',
+        name: '原料信息',
+        value: 0,
     },
     {
-        label: '产出信息',
-        value: '1',
+        name: '产出信息',
+        value: 1,
     },
 ];
 // 加载任务详情
@@ -231,8 +231,9 @@ const goAssociate = () => {
     });
 };
 // Tab 切换
-const onTabChange = () => {
-    if (activeTab.value === '1') {
+const onTabChange = (tabItem: any) => {
+    activeTab.value = tabItem?.value;
+    if (+activeTab.value === 1) {
         // 切换到产出信息,加载产出信息列表
         getOutputList();
     } else {
@@ -250,6 +251,7 @@ const getOutputList = async () => {
         if (res && res.rows) {
             outputList.value = res.rows;
         }
+        return res;
     } catch (error) {
         console.error('加载产出信息失败:', error);
         outputList.value = [];
@@ -277,7 +279,7 @@ const gotoDetail = () => {
 // 监听修改成功事件,重新加载任务详情
 const handleUpdateTaskDetail = () => {
     loadTaskDetail(); // 重新加载任务详情
-    if (activeTab.value === '0') {
+    if (+activeTab.value === 0) {
         paging.value?.reload(); // 刷新原料列表
     } else {
         getOutputList(); // 刷新产出列表
@@ -291,6 +293,10 @@ onLoad((options: any) => {
     if (taskId.value) {
         loadTaskDetail();
     }
+    if (options?.output) {
+        activeTab.value = 1;
+        getOutputList();
+    }
 });
 
 // 离开页面时卸载事件监听
@@ -309,6 +315,7 @@ const withdraw = async () => {
         const delRes = await useClientRequest.get(`/plt-api/app/processInputMaterial/callbackInput/${list.value?.[0]?.id}`);
         if (delRes && delRes.code === 200) {
             uni.showToast({ title: '删除成功', icon: 'none' });
+            uni.$emit(`updatesupervise-${taskId.value}`, []);
             paging.value?.reload();
         }
     }
@@ -326,8 +333,11 @@ const handleShowOutputModel = () => {
 };
 
 // 处理添加/修改成功
-const handleOutputConfirm = () => {
-    getOutputList();
+const handleOutputConfirm = async () => {
+    const res: any = await getOutputList();
+    console.log(res, 'res˝');
+
+    uni.$emit(`updateoutList-${taskId.value}`, res?.rows || []);
 };
 
 // 处理产出项点击
@@ -389,7 +399,8 @@ const handleDeleteOutput = async (outPutId: string | number, item: any) => {
         const delRes = await useClientRequest.get(`/plt-api/app/processOutPut/removeOutPut/${outPutId}`);
         if (delRes && delRes.code === 200) {
             uni.showToast({ title: '删除成功', icon: 'none' });
-            getOutputList();
+            const data = await getOutputList();
+            uni.$emit(`updateoutList-${taskId.value}`, data?.rows || []);
         }
     } catch (error) {
         console.error('删除失败:', error);

+ 178 - 57
src/plant/processing/processing-index/index.vue

@@ -4,16 +4,16 @@
             <up-navbar title="加工及包装赋码任务" :fixed="false"> </up-navbar>
         </template>
         <template>
-            <view class="pd3-24-24-0">
-                <view class="">
-                    <ut-tabs mode="subsection" v-model="form.restFlag" :tabs="tabs" @change="onRefresh"></ut-tabs>
-                </view>
-            </view>
             <view class="d-flex a-c pd-24 pb-0 bg-#f7f7f7">
-                <view class="min-w-170 flex1">
-                    <ut-action-sheet v-model="form.taskType" :tabs="[{ label: '全部', value: '' }, ...pt_process_type]" @change="onRefresh" title="选择原料类型">
+                <view class="min-w-220 flex1">
+                    <ut-action-sheet v-model="form.processType" :tabs="[{ label: '全部', value: '' }, ...pt_process_type]" @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_process_type, form.taskType) || '全部' }}</view>
+                            <view class="flex1 ov-hd f-s-28 c-333 text-center f-w-5 w-s-no d-flex a-c j-c">
+                                <view class="w-s-no">{{ selectDictLabel(pt_process_type, form.processType) || '全部' }}</view>
+                                <template v-for="(item, index) in processCountList" :key="index">
+                                    <view class="" v-if="form.processType == item?.type">({{ item?.num }})</view>
+                                </template>
+                            </view>
                             <up-icon size="24rpx" color="#333" name="arrow-down-fill" class="mr-5"></up-icon>
                         </view>
                     </ut-action-sheet>
@@ -23,53 +23,59 @@
                 </view>
             </view>
             <view class="pd-24">
-                <template v-for="(item, index) in list" :key="index">
-                    <view class="bg-#fff b-radius pd-24 p-rtv mb-16">
-                        <view v-if="+item?.processType == 1 && +item?.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="+item?.processType == 1 && +item?.processMedType == 2" class="bg-#C7A262 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="+item?.processType == 2" class="bg-#37A954 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="item?.processingDate || item?.processingDateEnd" class="d-flex a-c j-ed">
-                            <view class="c-#999 f-s-24">{{ item?.processingDate }} 至 {{ item?.processingDateEnd }}</view>
-                        </view>
-                        <view class="mb-10 d-flex a-c" @click="gotodetaillist(item)">
-                            <view class="">
-                                <span v-if="item?.variety" class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.variety }}</span>
-                                <span v-else class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.medicineName }}(鲜制)</span>
-                                <span class="f-s-24 c-#666" v-if="+item?.processMedType == 1">{{ selectDictLabel(pt_stock_type, item?.processMedType) }}</span>
+                <up-swipe-action>
+                    <up-swipe-action-item v-for="(item, index) in list" :key="index" :name="item?.id" :options="swipeOptions" class="mb-16" @click="handleSwipeClick">
+                        <template #default>
+                            <view class="bg-#fff b-radius pd-24 p-rtv">
+                                <view v-if="+item?.processType == 1 && +item?.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="+item?.processType == 1 && +item?.processMedType == 2" class="bg-#C7A262 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="+item?.processType == 2" class="bg-#37A954 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="item?.processingDate || item?.processingDateEnd" class="d-flex a-c j-ed">
+                                    <view class="c-#999 f-s-24">{{ item?.processingDate }} 至 {{ item?.processingDateEnd }}</view>
+                                </view>
+                                <view class="" @click="gotodetaillist(item)">
+                                    <view class="mb-10 d-flex a-c">
+                                        <view class="">
+                                            <span v-if="item?.variety" class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.variety }}</span>
+                                            <span v-else class="f-s-34 c-#333 f-w-500 mr-10">{{ item?.medicineName }}(鲜制)</span>
+                                            <span class="f-s-24 c-#666" v-if="+item?.processMedType == 1">{{ selectDictLabel(pt_stock_type, item?.processMedType) }}</span>
+                                        </view>
+                                        <view class="flex1"></view>
+                                        <up-icon name="arrow-right" size="26rpx"></up-icon>
+                                    </view>
+                                    <view class="pd2-4-0 f-s-28">
+                                        <span class="c-#666">加工批号:</span>
+                                        <span class="c-#333 f-w-500">{{ item?.processCode }}</span>
+                                    </view>
+                                    <view v-if="+item?.processType == 1" class="pd2-4-0 f-s-28">
+                                        <span class="c-#666">执行标准:</span>
+                                        <span class="c-#333 f-w-500">{{ selectDictLabel(pt_standard_type, item?.standardType) }}</span>
+                                        <span class="c-#666" v-if="item?.standardDetailName">({{ item?.standardDetailName }})</span>
+                                    </view>
+                                    <view v-else class="pd2-4-0 f-s-28">
+                                        <span class="c-#666">执行标准:</span>
+                                        <span class="c-#666" v-if="item?.standardDetailName">{{ item?.standardDetailName }}</span>
+                                    </view>
+                                    <view class="pd2-4-0 f-s-28">
+                                        <span class="c-#666">加工工艺:</span>
+                                        <template v-for="(items, indexs) in item?.ptech?.split(',')" v-if="item?.ptech" :key="indexs">
+                                            <span v-if="indexs !== 0" class="c-#999 f-s-32 ml-10 mr-10">→ </span>
+                                            <span class="f-s-32">{{ items }}</span>
+                                        </template>
+                                        <template v-else>
+                                            <span class="c-#999 f-s-32">-</span>
+                                        </template>
+                                    </view>
+                                    <view class="pd2-4-0 f-s-28">
+                                        <span class="c-#666">加工负责人:</span>
+                                        <span class="c-#333 f-w-500">{{ item?.contactName }}</span>
+                                    </view>
+                                </view>
+                                <Output :data="item" />
                             </view>
-                            <view class="flex1"></view>
-                            <up-icon name="arrow-right" size="26rpx"></up-icon>
-                        </view>
-                        <view class="pd2-4-0 f-s-28">
-                            <span class="c-#666">加工批号:</span>
-                            <span class="c-#333 f-w-500">{{ item?.processCode }}</span>
-                        </view>
-                        <view v-if="+item?.processType == 1" class="pd2-4-0 f-s-28">
-                            <span class="c-#666">执行标准:</span>
-                            <span class="c-#333 f-w-500">{{ selectDictLabel(pt_standard_type, item?.standardType) }}</span>
-                            <span class="c-#666" v-if="item?.standardDetailName">({{ item?.standardDetailName }})</span>
-                        </view>
-                        <view v-else class="pd2-4-0 f-s-28">
-                            <span class="c-#666">执行标准:</span>
-                            <span class="c-#666" v-if="item?.standardDetailName">{{ item?.standardDetailName }}</span>
-                        </view>
-                        <view class="pd2-4-0 f-s-28">
-                            <span class="c-#666">加工工艺:</span>
-                            <template v-for="(items, indexs) in item?.ptech?.split(',')" v-if="item?.ptech" :key="indexs">
-                                <span v-if="indexs !== 0" class="c-#999 f-s-32 ml-10 mr-10">→ </span>
-                                <span class="f-s-32">{{ items }}</span>
-                            </template>
-                            <template v-else>
-                                <span class="c-#999 f-s-32">-</span>
-                            </template>
-                        </view>
-                        <view class="pd2-4-0 f-s-28">
-                            <span class="c-#666">加工负责人:</span>
-                            <span class="c-#333 f-w-500">{{ item?.contactName }}</span>
-                        </view>
-                        <Output :data="item" />
-                    </view>
-                </template>
+                        </template>
+                    </up-swipe-action-item>
+                </up-swipe-action>
             </view>
         </template>
         <view class="h-210" v-if="list?.length"></view>
@@ -91,10 +97,10 @@
         <view class="" v-for="item in pt_process_type" :key="item?.value">
             <view style="border: 1rpx solid" :style="{ backgroundColor: item?.value == basetype ? '#EBF6EE' : '#f7f7f7', borderColor: item?.value == basetype ? '#37A954' : 'transparent' }" class="pr-30 d-flex a-c mb-20 radius-100" @click="handlechose(item.value)">
                 <view class="radius-50% mg-8 bg-#F0F0F0" v-if="item?.value == '1'">
-                    <up-avatar size="90rpx" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/port/TaskType_plant.png"></up-avatar>
+                    <up-avatar size="90rpx" src="/static/images/plant/processing/processType_initial.png"></up-avatar>
                 </view>
                 <view class="radius-50% mg-8 bg-#F0F0F0" v-if="item?.value == '2'">
-                    <up-avatar size="90rpx" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/port/TaskType_breeding.png"></up-avatar>
+                    <up-avatar size="90rpx" src="/static/images/plant/processing/processType_fresh.png"></up-avatar>
                 </view>
                 <view class="c-#333 f-s-34">
                     {{ item?.label }}
@@ -123,6 +129,7 @@ sus.value.left = systemInfo.windowWidth - 10;
 sus.value.bottom = systemInfo.windowHeight - 200;
 const showDeleteDialog = ref(false);
 const basetype = ref();
+const processCountList = ref<any>();
 const handlechose = (item: string) => {
     basetype.value = item;
 };
@@ -140,7 +147,7 @@ const handlechoseConfirm = () => {
         });
         return;
     }
-    uni.$u.route({ type: 'navigateTo', url: '/plant/processing/processing-create/index', params: { taskType: basetype.value } });
+    uni.$u.route({ type: 'navigateTo', url: '/plant/processing/processing-create/index', params: { processType: basetype.value } });
 };
 const paging = ref();
 const list = ref<any[]>([]);
@@ -156,7 +163,108 @@ const tabs = [
 ];
 const form = ref({
     storageType: '4',
+    processType: '',
+    keyword: '',
 });
+
+// 滑动操作选项
+const swipeOptions = reactive([
+    {
+        text: '复制',
+        style: {
+            backgroundColor: '#37A954',
+            width: '80rpx',
+            fontSize: '28rpx',
+        },
+    },
+    {
+        text: '修改',
+        style: {
+            backgroundColor: '#18BECA',
+            width: '80rpx',
+            fontSize: '28rpx',
+        },
+    },
+    {
+        text: '删除',
+        style: {
+            backgroundColor: '#F74C30',
+            width: '80rpx',
+            fontSize: '28rpx',
+        },
+    },
+]);
+
+// 处理滑动按钮点击
+const handleSwipeClick = async (event: any) => {
+    const { name, index } = event;
+    const item = list.value[index];
+
+    if (index === 0) {
+        // 点击复制
+        handleCopy(name, item);
+    } else if (index === 1) {
+        // 点击修改
+        handleEdit(item);
+    } else if (index === 2) {
+        // 点击删除
+        handleDelete(name, item);
+    }
+};
+
+// 处理复制
+const handleCopy = async (processId: string | number, item: any) => {
+    try {
+        const res = await uni.showModal({
+            title: '复制提示',
+            content: '确定复制该加工任务吗?',
+            confirmColor: '#37A954',
+        });
+        if (!res.confirm) return;
+
+        const copyRes = await useClientRequest.get(`/plt-api/app/processe/copyProcess/${processId}`);
+        if (copyRes && copyRes.code === 200) {
+            uni.showToast({ title: '复制成功', icon: 'success' });
+            paging.value?.reload();
+        }
+    } catch (error) {
+        console.error('复制失败:', error);
+    }
+};
+
+// 处理修改
+const handleEdit = (item: any) => {
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/processing/processing-create/index',
+        params: { id: item?.id, edit: 1 },
+    });
+};
+
+// 处理删除
+const handleDelete = async (processId: string | number, item: any) => {
+    try {
+        const res = await uni.showModal({
+            title: '删除提示',
+            content: '删除后不可恢复,请谨慎操作!',
+            confirmColor: '#F74C30',
+        });
+        if (!res.confirm) return;
+
+        const delRes = await useClientRequest.get(`/plt-api/app/processe/deleteProcess/${processId}`);
+        if (delRes && delRes.code === 200) {
+            uni.showToast({ title: '删除成功', icon: 'none' });
+            paging.value?.reload();
+        }
+    } catch (error) {
+        console.error('删除失败:', error);
+    }
+};
+
+const changeSeach = () => {
+    paging.value.reload();
+};
+
 const query = async (pageNum: number, pageSize: number) => {
     const params = {
         pageNum,
@@ -176,6 +284,16 @@ const gotodetaillist = (item: any) => {
         params: { id: item?.id },
     });
 };
+//获取所选类型的数量
+const selectNumber = async () => {
+    const res = await useClientRequest.get('/plt-api/app/processe/processCountList');
+    if (res) {
+        console.log(res);
+        processCountList.value = res?.data;
+        return res;
+    }
+};
+
 const onRefresh = () => {
     paging.value?.reload();
 };
@@ -184,6 +302,9 @@ onMounted(() => {
         paging.value?.reload();
     });
 });
+onShow(() => {
+    selectNumber();
+});
 </script>
 <style scoped lang="scss">
 .search-select-item {

+ 86 - 22
src/plant/processing/processing-index/models/output.vue

@@ -8,7 +8,7 @@
             <view class="d-flex flex1 f-s-26">
                 <view class="c-#999 ml-16"> 暂无关联原料信息 </view>
                 <view class="flex1"></view>
-                <view class="c-primary d-flex a-c" @click="goAssociate">
+                <view class="c-primary d-flex a-c" @click.stop="goAssociate">
                     <view>去关联</view>
                     <up-icon name="arrow-right" size="26rpx"></up-icon>
                 </view>
@@ -26,19 +26,19 @@
                     </view>
                 </ut-col>
                 <ut-col class="d-flex a-c c-#666" :span="10">{{ inputList?.quantity }}{{ inputList?.unit }}</ut-col>
-                <ut-col class="d-flex a-c j-ed" :span="5" @click.stop="withdraw">
+                <ut-col class="d-flex a-c j-ed" :span="5" @click.stop="handleWithdrawClick">
                     <span class="c-#666">撤回</span>
                     <up-icon name="arrow-right" size="26rpx"></up-icon>
                 </ut-col>
             </ut-row>
         </view>
     </view>
-    <view class="radius-10 bg-#f7f7f7 d-flex">
+    <view class="radius-10 bg-#f7f7f7 d-flex" @click="gotodetaillist(processId)">
         <view class="bg-#EBF4FD w-50 d-flex flex-cln a-c j-c c-#2289E0 f-w-5 f-s-24">
             <view class="">产</view>
             <view class="">出</view>
         </view>
-        <view class="bg-#F6FAFE flex1 d-flex a-c" v-if="data?.length === 0">
+        <view class="bg-#F6FAFE flex1 d-flex a-c h-110" v-if="outputList?.length === 0">
             <view class="d-flex flex1 f-s-26">
                 <view class="c-#999 ml-16"> 暂无产出信息 </view>
                 <view class="flex1"></view>
@@ -49,42 +49,73 @@
             </view>
         </view>
         <view class="bg-#F6FAFE flex1 f-s-22 pd-16" v-else>
-            <ut-row gap="10rpx">
-                <ut-col class="d-flex a-c c-#666" :span="2">01</ut-col>
-                <ut-col class="d-flex flex-cln j-c" :span="8">
-                    <span class="c-#666">统货2</span>
-                    <span class="c-#999">1mm极薄片</span>
-                </ut-col>
-                <ut-col class="d-flex a-c c-#666" :span="8">19999kg</ut-col>
-                <ut-col class="d-flex a-c" :span="3">
-                    <span class="c-#F74C30">未检</span>
-                    <span class="c-primary">已检</span>
-                </ut-col>
-                <ut-col class="d-flex a-c j-ed" :span="9">
-                    <span class="c-#666">已入药材库</span>
-                    <span class="c-#666">未入库</span>
-                    <up-icon name="arrow-right" size="26rpx"></up-icon>
-                </ut-col>
-            </ut-row>
-            <view class="d-flex a-c j-c pd-16 radius-10" style="border: 1rpx dashed #2289e0">
+            <view v-for="(item, index) in outputList" :key="item?.id || index" class="mb-6">
+                <ut-row gap="10rpx">
+                    <ut-col class="d-flex a-c c-#666" :span="2">{{ String(Number(index) + 1).padStart(2, '0') }}</ut-col>
+                    <ut-col class="d-flex flex-cln j-c" :span="8">
+                        <span class="c-#666">{{ item?.specnLevel }}</span>
+                        <span class="c-#999">{{ item?.finalSpecn }}{{ item?.finalUnit }}{{ selectDictLabel(pt_final_form_type, item?.finalFormType) }}</span>
+                    </ut-col>
+                    <ut-col class="d-flex a-c c-#666" :span="8">{{ item?.capacity }}{{ item?.unit }}</ut-col>
+                    <ut-col class="d-flex a-c" :span="3">
+                        <span v-if="item?.examinReport?.length > 0" class="c-primary">已检</span>
+                        <span v-else class="c-#F74C30">未检</span>
+                    </ut-col>
+                    <ut-col class="d-flex a-c j-ed" :span="9">
+                        <span v-if="Number(item?.status) !== 0" class="c-#37a954">已入药材库</span>
+                        <span v-else class="c-#666">未入库</span>
+                        <up-icon name="arrow-right" size="26rpx"></up-icon>
+                    </ut-col>
+                </ut-row>
+            </view>
+            <view class="d-flex a-c j-c pd-16 radius-10" style="border: 1rpx dashed #2289e0" @click.stop="handleShowOutputModel">
                 <up-icon name="plus" size="26rpx" color="#2289E0"></up-icon>
                 <span class="c-#2289E0 f-s-26">添加产出物</span>
             </view>
         </view>
     </view>
+    <!-- 添加/修改产出信息弹框 -->
+    <root-portal>
+        <OutputInfo v-if="showOutputModel" v-model:show="showOutputModel" :type="processType" :processId="processId" :isEdit="isEditOutput" :editData="editOutputData" @confirm="handleOutputConfirm" />
+    </root-portal>
 </template>
 <script setup lang="ts">
 import { useClientRequest } from '@/utils/request';
+import OutputInfo from './outputInfo.vue';
+
 const props = defineProps<{
     data: any;
 }>();
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { pt_final_form_type } = toRefs<any>(proxy?.useDict('pt_final_form_type'));
+
+// 从 data 中获取 processId 和 processType
+const processId = computed(() => props.data?.id);
+const processType = computed(() => props.data?.processType || 1);
+
+// 字典标签选择函数
+const selectDictLabel = (dict: any[], value: string | number) => {
+    const item = dict.find((item) => item.value == value);
+    return item ? item.label : '';
+};
+
 watch(
     () => props.data,
     (val) => {
         inputList.value = val?.inputList[0] || {};
+        outputList.value = val?.outputList || [];
     },
 );
+
 const inputList = ref<any>(props?.data?.inputList[0] || {});
+const outputList = ref<any>(props?.data?.outputList || []);
+
+// 弹框状态管理
+const showOutputModel = ref(false);
+const isEditOutput = ref(false); // 是否编辑模式
+const editOutputData = ref<any>({}); // 编辑的数据
+
 const goAssociate = () => {
     uni.$u.route({
         type: 'navigateTo',
@@ -92,9 +123,29 @@ const goAssociate = () => {
         params: { id: props?.data?.id, processMedType: props?.data?.processMedType },
     });
 };
+const gotodetaillist = (id: any) => {
+    uni.$u.route({
+        type: 'navigateTo',
+        url: '/plant/processing/processing-detail-list/index',
+        params: { id: id, output: true },
+    });
+};
 uni.$on(`updatesupervise-${props?.data?.id}`, function (data) {
+    console.log(data, 'data');
+
     inputList.value = data;
 });
+uni.$on(`updateoutList-${props?.data?.id}`, function (data) {
+    outputList.value = data;
+});
+// 处理撤回按钮点击,阻止事件冒泡
+const handleWithdrawClick = (event: any) => {
+    if (event) {
+        event.stopPropagation();
+    }
+    withdraw();
+};
+
 const withdraw = async () => {
     // 删除
     const res = await uni.showModal({
@@ -111,4 +162,17 @@ const withdraw = async () => {
         }
     }
 };
+
+// 显示添加产出信息弹框
+const handleShowOutputModel = () => {
+    isEditOutput.value = false;
+    editOutputData.value = {};
+    showOutputModel.value = true;
+};
+
+// 处理添加/修改成功回调
+const handleOutputConfirm = async () => {
+    const res = await useClientRequest.get(`/plt-api/app/processOutPut/pageList?processId=${processId?.value}`);
+    outputList.value = res?.rows || [];
+};
 </script>

+ 354 - 0
src/plant/processing/processing-index/models/outputInfo.vue

@@ -0,0 +1,354 @@
+<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-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">
+                        <template v-if="+type == 1">
+                            <!-- 规格等级 -->
+                            <up-form-item label="规格等级" required prop="specnLevel">
+                                <view class="flex1" @click="goToSpecLevel">
+                                    <up-input readonly v-model="formData.specnLevel" type="number" placeholder="请选择规格等级" style="padding-left: 0; padding-right: 0" border="bottom" clearable suffixIcon="arrow-down-fill" suffixIconStyle="color: #2A6D52;font-size: 22rpx"> </up-input>
+                                </view>
+                                <view class="ml-20">
+                                    <up-checkbox :customStyle="{ marginBottom: '8px' }" label="统货" name="agree" usedAlone :checked="formData.specnLevel == '统货'" @change="handleSpecnLevelChange"> </up-checkbox>
+                                </view>
+                            </up-form-item>
+                            <!-- 产量 -->
+                            <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>
+                            </up-form-item>
+
+                            <!-- 检验报告 -->
+                            <up-form-item borderBottom label="加工检验报告">
+                                <ut-upload v-model="formData.examinReport" :max-count="50" valueType="array" accept="image,file" width="210rpx" height="210rpx" style="card"></ut-upload>
+                            </up-form-item>
+                        </template>
+
+                        <!-- 类型 2 特有字段 -->
+                        <template v-else>
+                            <!-- 规格等级 -->
+                            <up-form-item label="规格等级" required prop="specnLevel">
+                                <view class="flex1" @click="goToSpecLevel">
+                                    <up-input readonly v-model="formData.specnLevel" type="number" placeholder="请选择规格等级" style="padding-left: 0; padding-right: 0" border="bottom" clearable suffixIcon="arrow-down-fill" suffixIconStyle="color: #2A6D52;font-size: 22rpx"> </up-input>
+                                </view>
+                                <view class="ml-20">
+                                    <up-checkbox :customStyle="{ marginBottom: '8px' }" label="统货" name="agree" usedAlone :checked="formData.specnLevel == '统货'" @change="handleSpecnLevelChange"> </up-checkbox>
+                                </view>
+                            </up-form-item>
+                            <!-- 产量 -->
+                            <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="#37A954" name="arrow-down-fill"></up-icon>
+                                                </template>
+                                            </up-form-item>
+                                        </ut-action-sheet>
+                                    </view>
+                                </view>
+                            </up-form-item>
+                            <!-- 切制形态 -->
+                            <ut-action-sheet v-model="formData.finalFormType" :tabs="pt_final_form_type" title="选择切制形态">
+                                <up-form-item borderBottom label="切制形态" prop="finalFormType" required>
+                                    <view v-if="formData?.finalFormType" class="f-s-30 c-#333 f-w-5 flex1">{{ selectDictLabel(pt_final_form_type, formData?.finalFormType) }}</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>
+                                    </template>
+                                </up-form-item>
+                            </ut-action-sheet>
+                            <!-- 具体切制形态 -->
+                            <up-form-item borderBottom label="具体切制形态" prop="finalFormOther" required>
+                                <up-input v-model="formData.finalFormOther" placeholder="请输入具体切制形态" border="none" clearable></up-input>
+                            </up-form-item>
+
+                            <!-- 切制尺寸 -->
+                            <up-form-item label="切制尺寸" required>
+                                <view class="flex1 d-flex">
+                                    <view class="flex1 ov-hd" id="finalSpecnpppp">
+                                        <up-form-item border-bottom prop="finalSpecn" class="form-item-top-padding-0">
+                                            <up-input v-model="formData.finalSpecn" 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.finalUnit" :tabs="pt_final_unit" title="选择切制单位">
+                                            <up-form-item border-bottom prop="finalUnit" class="form-item-top-padding-0">
+                                                <view class="flex1" style="line-height: 24px">
+                                                    <view v-if="formData?.finalUnit" class="f-s-30 c-#333 f-w-5 flex1">{{ selectDictLabel(pt_final_unit, formData?.finalUnit) }}</view>
+                                                    <view v-else class="f-s-30 c-ccc f-w-4 flex1">单位</view>
+                                                </view>
+                                                <template #right>
+                                                    <up-icon size="22rpx" color="#37A954" 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>
+                            </up-form-item>
+
+                            <!-- 检验报告 -->
+                            <up-form-item borderBottom label="加工检验报告">
+                                <ut-upload v-model="formData.examinReport" :max-count="50" valueType="array" accept="image,file" width="210rpx" height="210rpx" style="card"></ut-upload>
+                            </up-form-item>
+                        </template>
+                    </up-form>
+                </view>
+            </scroll-view>
+
+            <!-- 底部按钮 -->
+            <view class="d-flex gap-20 pd-24">
+                <up-button plain type="info" @click="handleClose">取消</up-button>
+                <up-button type="primary" @click="handleSubmit">确认</up-button>
+            </view>
+        </view>
+    </up-popup>
+</template>
+
+<script setup lang="ts">
+import { useClientRequest } from '@/utils/request';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+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 selectDictLabel = (dict: any[], value: string | number) => {
+    const item = dict.find((item) => item.value == value);
+    return item ? item.label : '';
+};
+const props = defineProps<{
+    show: boolean;
+    type: number; // 1: 初加工,2: 趁鲜切制
+    processId: string | number; // 加工任务 ID
+    isEdit: boolean; // 是否编辑模式
+    editData: any; // 要编辑的数据
+}>();
+const emit = defineEmits<{
+    'update:show': [value: boolean];
+    confirm: [data: any];
+}>();
+
+const formRef = ref();
+
+// 表单数据
+const formData = ref({
+    specnLevel: '',
+    capacity: '',
+    unit: '',
+    imgs: [] as any[],
+    examinReport: [] as any[],
+    finalFormType: '',
+    finalFormOther: '',
+    finalSpecn: '',
+    finalUnit: '',
+    id: '', // 编辑模式需要 id
+});
+
+// 监听 editData 变化,初始化表单数据
+watch(
+    () => props.editData,
+    (newVal) => {
+        if (newVal && props.isEdit) {
+            formData.value = {
+                specnLevel: newVal?.specnLevel || '',
+                capacity: newVal?.capacity || '',
+                unit: newVal?.unit || '',
+                imgs: newVal?.imgs ? newVal.imgs.split(',').map((url: string) => ({ url })) : [],
+                examinReport: newVal?.examinReport || [],
+                finalFormType: newVal?.finalFormType || '',
+                finalFormOther: newVal?.finalFormOther || '',
+                finalSpecn: newVal?.finalSpecn || '',
+                finalUnit: newVal?.finalUnit || '',
+                id: newVal?.id || '',
+            };
+        }
+    },
+    { immediate: true },
+);
+
+// 动态生成校验规则
+const getRules = () => {
+    const baseRules = {
+        specnLevel: [{ required: true, message: '请选择规格等级', trigger: 'change' }],
+        capacity: [
+            { required: true, message: '请输入产量', trigger: 'blur' },
+            { type: 'number', message: '产量必须为数字', trigger: 'blur' },
+        ],
+        unit: [{ required: true, message: '请选择单位', trigger: 'change' }],
+    };
+
+    if (type.value === 2) {
+        // 类型 2(趁鲜切制)所有字段必填
+        return {
+            ...baseRules,
+            finalFormType: [{ required: true, message: '请选择切制形态', trigger: 'change' }],
+            finalFormOther: [{ required: true, message: '请输入具体切制形态', trigger: 'blur' }],
+            finalSpecn: [{ required: true, message: '请输入切制尺寸', trigger: 'blur' }],
+            finalUnit: [{ required: true, message: '请选择切制单位', trigger: 'change' }],
+        };
+    } else {
+        // 类型 1(初加工)只有前三个必填
+        return baseRules;
+    }
+};
+
+// 根据 type 动态设置校验规则
+const type = ref(+props.type);
+const rules = ref(getRules());
+
+// 监听 type 变化,重新生成规则
+watch(
+    () => props.type,
+    (newVal) => {
+        type.value = newVal;
+        rules.value = getRules();
+    },
+);
+
+// 关闭弹框
+const handleClose = () => {
+    emit('update:show', false);
+    resetForm();
+};
+
+// 获取标题
+const getTitle = () => {
+    return props.isEdit ? '修改产出信息' : '添加产出信息';
+};
+
+// 重置表单
+const resetForm = () => {
+    formData.value = {
+        specnLevel: '',
+        capacity: '',
+        unit: '',
+        imgs: [],
+        examinReport: [],
+        finalFormType: '',
+        finalFormOther: '',
+        finalSpecn: '',
+        finalUnit: '',
+        id: '',
+    };
+    formRef.value?.clearValidate();
+};
+
+// 处理统货 checkbox 点击事件
+const handleSpecnLevelChange = (checked: boolean) => {
+    if (checked) {
+        formData.value.specnLevel = '统货';
+    } else {
+        formData.value.specnLevel = '';
+    }
+};
+
+// 跳转到规格等级选择页面
+const goToSpecLevel = () => {
+    uni.$once('updateSpecificationLevel', (res) => {
+        if (res?.data) {
+            formData.value.specnLevel = res.data;
+        }
+    });
+    uni.navigateTo({
+        url: '/tools/specification-level/index',
+    });
+};
+
+// 提交表单
+const handleSubmit = async () => {
+    try {
+        const valid = await formRef.value?.validate();
+        if (!valid) return;
+
+        // 准备提交数据
+        const submitData = {
+            processId: props.processId,
+            specnLevel: formData.value.specnLevel,
+            capacity: Number(formData.value.capacity),
+            unit: formData.value.unit,
+            imgs: formData.value.imgs.map((item: any) => item.url).join(','),
+            examinReport: formData.value.examinReport.map((item: any) => ({
+                fileName: item.fileName || '',
+                url: item.url || '',
+                fileSize: item.fileSize || 0,
+            })),
+            finalFormType: formData.value.finalFormType,
+            finalFormOther: formData.value.finalFormOther,
+            finalSpecn: formData.value.finalSpecn,
+            finalUnit: formData.value.finalUnit,
+        };
+
+        let res: any;
+        // 编辑模式调用修改接口
+        if (props.isEdit && formData.value.id) {
+            (submitData as any).id = formData.value.id;
+            res = await useClientRequest.post('/plt-api/app/processOutPut/outputEdit', submitData);
+        } else {
+            // 新增模式调用新增接口
+            res = await useClientRequest.post('/plt-api/app/processOutPut/output', submitData);
+        }
+
+        if (res && res.code === 200) {
+            uni.showToast({ title: props.isEdit ? '修改成功' : '添加成功', icon: 'success' });
+            handleClose();
+            emit('confirm', res.data);
+        }
+    } catch (error) {
+        console.error('提交失败:', error);
+    }
+};
+</script>
+
+<style scoped lang="scss">
+.search-select-item {
+    height: 86rpx;
+    background-color: #fff;
+    border-radius: 10rpx;
+    box-sizing: border-box;
+    padding-left: 16rpx;
+    padding-right: 16rpx;
+    padding-top: 14rpx;
+    padding-bottom: 14rpx;
+}
+</style>

BIN
src/static/images/plant/processing/processType_fresh.png


BIN
src/static/images/plant/processing/processType_initial.png