HuRongxin 1 ヶ月 前
コミット
4c212a04e3

+ 83 - 0
src/api/warehouse/suppliesManage/index.ts

@@ -0,0 +1,83 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { SuppliesManageVO, SuppliesManageForm, SuppliesManageQuery } from '@/api/warehouse/suppliesManage/types';
+
+/**
+ * 查询耗材管理列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listSuppliesManage = (query?: SuppliesManageQuery): AxiosPromise<SuppliesManageVO[]> => {
+  return request({
+    url: '/warehouse/suppliesManage/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询耗材管理详细
+ * @param id
+ */
+export const getSuppliesManage = (id: string | number): AxiosPromise<SuppliesManageVO> => {
+  return request({
+    url: '/warehouse/suppliesManage/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增耗材管理
+ * @param data
+ */
+export const addSuppliesManage = (data: SuppliesManageForm) => {
+  return request({
+    url: '/warehouse/suppliesManage',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改耗材管理
+ * @param data
+ */
+export const updateSuppliesManage = (data: SuppliesManageForm) => {
+  return request({
+    url: '/warehouse/suppliesManage',
+    method: 'put',
+    data: data
+  });
+};
+
+export function batchUpdateSuppliesManage(data) {
+  return request({
+    url: '/warehouse/suppliesManage/batchUpdate',
+    method: 'post',
+    data
+  });
+}
+
+/**
+ * 删除耗材管理
+ * @param id
+ */
+export const delSuppliesManage = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/warehouse/suppliesManage/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 更新上架状态
+ * @param id
+ * @param flag
+ */
+export const updatePutFlag = (id: string | number, flag: string) => {
+  return request({
+    url: `/warehouse/suppliesManage/${id}/putFlag/${flag}`,
+    method: 'put'
+  });
+};

+ 357 - 0
src/api/warehouse/suppliesManage/types.ts

@@ -0,0 +1,357 @@
+export interface SuppliesManageVO {
+    /**
+     * 主键ID
+     */
+    id: string | number;
+
+    /**
+     * 耗材名称
+     */
+    suppliesName: string;
+
+    /**
+     * 院方系统编码
+     */
+    hospitalSystemCode: string;
+
+    /**
+     * 商品编码
+     */
+    suppliesCode: string;
+
+    /**
+     * 生产厂商
+     */
+    manufacturer: string;
+
+    /**
+     * 供应商
+     */
+    supplier: string;
+
+    /**
+     * 许可证有效期提醒
+     */
+    licenseExpiryReminder: string;
+
+    /**
+     * 保质期
+     */
+    shelfLife: string;
+
+    /**
+     * 商品资质
+     */
+    productQualification: string;
+
+    /**
+     * 批准文号
+     */
+    approvalNumber: string;
+
+    /**
+     * 所属分类
+     */
+    suppliesCategoryId: string | number;
+
+    suppliesCategoryList: string[];
+
+    /**
+     * 保质期临期提醒
+     */
+    shelfLifeReminder: string;
+
+    productLicenseExpiry: string;
+
+    /**
+     * 品牌
+     */
+    brand: string;
+
+    /**
+     * 产品所属标签
+     */
+    productLabel: string;
+
+    /**
+     * 产品适用科室
+     */
+    applicableDepartment: string;
+
+    /**
+     * 入货价格
+     */
+    purchasePrice: number;
+
+    /**
+     * 耗材单位
+     */
+    suppliesUnit: string;
+
+    /**
+     * 销售价格
+     */
+    sellPrice: number;
+
+    /**
+     * 耗材规格
+     */
+    suppliesSpec: string;
+
+    /**
+     * 耗材规格单位
+     */
+    suppliesSpecUnit: string;
+
+    /**
+     * 上架 
+     */
+    putFlag: string;
+
+}
+
+export interface SuppliesManageForm extends BaseEntity {
+    /**
+     * 主键ID
+     */
+    id?: string | number;
+
+    /**
+     * 耗材名称
+     */
+    suppliesName?: string;
+
+    /**
+     * 院方系统编码
+     */
+    hospitalSystemCode?: string;
+
+    /**
+     * 商品编码
+     */
+    suppliesCode?: string;
+
+    /**
+     * 生产厂商
+     */
+    manufacturer?: string;
+
+    /**
+     * 供应商
+     */
+    supplier?: string;
+
+    /**
+     * 许可证有效期提醒
+     */
+    licenseExpiryReminder?: string;
+
+    productLicenseExpiry?: string;
+
+    /**
+     * 保质期
+     */
+    shelfLife?: string;
+
+    /**
+     * 商品资质
+     */
+    productQualification?: string;
+
+    /**
+     * 批准文号
+     */
+    approvalNumber?: string;
+
+    /**
+     * 所属分类
+     */
+    suppliesCategoryId?: string | number;
+
+    /**
+     * 所属分类列表
+     */
+    suppliesCategoryList?: any[];
+
+    /**
+     * 保质期临期提醒
+     */
+    shelfLifeReminder?: string;
+
+    /**
+     * 品牌
+     */
+    brand?: string;
+
+    /**
+     * 产品所属标签
+     */
+    productLabel?: string;
+
+    /**
+     * 产品所属标签列表
+     */
+    productLabelList?: Array<{
+        labelId: string | number;
+        labelName: string;
+    }>;
+
+    /**
+     * 产品适用科室
+     */
+    applicableDepartment?: string;
+
+    /**
+     * 产品适用科室列表
+     */
+    applicableDepartmentList?: Array<string | number>;
+
+    /**
+     * 入货价格
+     */
+    purchasePrice?: number;
+
+    /**
+     * 耗材单位
+     */
+    suppliesUnit?: string;
+
+    /**
+     * 销售价格
+     */
+    sellPrice?: number;
+
+    /**
+     * 耗材规格
+     */
+    suppliesSpec?: string;
+
+    /**
+     * 耗材规格单位
+     */
+    suppliesSpecUnit?: string;
+
+    /**
+     * 上架状态
+     */
+    putFlag?: string;
+
+}
+
+export interface SuppliesManageQuery extends PageQuery {
+
+    /**
+     * 耗材名称
+     */
+    suppliesName?: string;
+
+    /**
+     * 院方系统编码
+     */
+    hospitalSystemCode?: string;
+
+    /**
+     * 商品编码
+     */
+    suppliesCode?: string;
+
+    /**
+     * 生产厂商
+     */
+    manufacturer?: string;
+
+    /**
+     * 供应商
+     */
+    supplier?: string;
+
+    /**
+     * 许可证有效期提醒
+     */
+    licenseExpiryReminder?: string;
+
+    /**
+   * 商品许可证有效期至
+   */
+    productLicenseExpiry?: string;
+
+    /**
+     * 保质期
+     */
+    shelfLife?: string;
+
+    /**
+     * 商品资质
+     */
+    productQualification?: string;
+
+    /**
+     * 批准文号
+     */
+    approvalNumber?: string;
+
+    /**
+     * 所属分类
+     */
+    suppliesCategoryId?: string | number;
+
+    suppliesCategoryList?: string[];
+
+    /**
+     * 保质期临期提醒
+     */
+    shelfLifeReminder?: string;
+
+    /**
+     * 品牌
+     */
+    brand?: string;
+
+    /**
+     * 产品所属标签
+     */
+    productLabel?: string;
+
+    /**
+     * 产品适用科室
+     */
+    applicableDepartment?: string;
+
+    /**
+     * 入货价格
+     */
+    purchasePrice?: number;
+
+    /**
+     * 耗材单位
+     */
+    suppliesUnit?: string;
+
+    /**
+     * 销售价格
+     */
+    sellPrice?: number;
+
+    /**
+     * 耗材规格
+     */
+    suppliesSpec?: string;
+
+    /**
+     * 耗材规格单位
+     */
+    suppliesSpecUnit?: string;
+
+    /**
+     * 上架 
+     */
+    putFlag?: string;
+
+    /**
+     * 日期范围参数
+     */
+    params?: any;
+}
+
+
+

+ 557 - 540
src/views/warehouse/nutriProduct/index.vue

@@ -5,7 +5,7 @@
                 <el-card shadow="hover">
                     <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="150px">
                         <el-form-item label="产品分类" prop="productCategory">
-                            <el-cascader v-model="queryParams.productCategoryList" :options="categoryOptions" :props="{ checkStrictly: false, emitPath: true, value: 'value', label: 'label', children: 'children' }" placeholder="请选择" clearable filterable style="width: 200px" />
+                            <el-cascader v-model="queryParams.productCategoryList" :options="categoryOptions" :props="{ checkStrictly: true, emitPath: true, value: 'value', label: 'label', children: 'children' }" placeholder="请选择" clearable filterable style="width: 200px" />
                         </el-form-item>
                         <el-form-item>
                             <el-input v-model="queryParams.productName" placeholder="请输入名称/编码" clearable @keyup.enter="handleQuery" style="margin-left: 30px;" />
@@ -32,9 +32,9 @@
                         <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['warehouse:nutrition:remove']">删除</el-button>
                     </el-col> -->
 
-                    <el-col :span="1.5">
+                    <!-- <el-col :span="1.5">
                         <el-button type="warning" plain @click="handleImport" v-hasPermi="['system:diseaseLabel:export']">导入</el-button>
-                    </el-col>
+                    </el-col> -->
                     <el-col :span="1.5">
                         <el-button type="warning" plain @click="handleExport" v-hasPermi="['warehouse:nutrition:export']">导出</el-button>
                     </el-col>
@@ -146,7 +146,7 @@
                             <el-row :gutter="20">
                                 <el-col :span="12">
                                     <el-form-item label="产品所属分类:" prop="productCategory">
-                                        <el-cascader v-model="form.productCategoryList" :options="categoryOptions" :props="{ checkStrictly: false, emitPath: true, value: 'value', label: 'label', children: 'children' }" placeholder="请选择" clearable filterable style="width: 100%" />
+                                        <el-cascader v-model="form.productCategoryList" :options="categoryOptions" :props="{ checkStrictly: true, emitPath: true, value: 'value', label: 'label', children: 'children' }" placeholder="请选择" clearable filterable style="width: 100%" />
                                     </el-form-item>
                                 </el-col>
                                 <el-col :span="12">
@@ -194,12 +194,11 @@
                             <el-row :gutter="20">
                                 <el-col :span="12">
                                     <el-form-item label="产品所属标签:" prop="productLabelList">
-                                        <el-select v-model="form.productLabelList" multiple placeholder="请选择" style="width: 100%;" :disabled="true" @mousedown.prevent="diseaseLabelDialogVisible = true" class="custom-label-select" value-key="labelId">
+                                        <el-select v-model="form.productLabelList" multiple placeholder="请选择" style="width: 100%;" :disabled="true" @click="diseaseLabelDialogVisible = true" class="custom-label-select" value-key="labelId">
                                             <el-option v-for="item in form.productLabelList" :key="item.labelId" :label="item.labelName" :value="item">
                                                 <el-tag type="info" size="small">{{ item.labelName }}</el-tag>
                                             </el-option>
                                         </el-select>
-                                        <lableDialog :model-value="diseaseLabelDialogVisible" @update:modelValue="val => diseaseLabelDialogVisible = val" @confirm="onLabelConfirm" />
                                     </el-form-item>
                                 </el-col>
                                 <el-col :span="12">
@@ -209,7 +208,6 @@
                                                 <el-tag type="info" size="small">{{ item.labelName }}</el-tag>
                                             </el-option>
                                         </el-select>
-                                        <lableDialog :model-value="contraindicationLabelDialogVisible" @update:modelValue="val => contraindicationLabelDialogVisible = val" @confirm="onContraindicationLabelConfirm" />
                                     </el-form-item>
                                 </el-col>
                             </el-row>
@@ -1009,13 +1007,13 @@
             </template>
         </el-dialog>
         <el-dialog title="批量设置" v-model="batchSetDialogVisible" width="400px" append-to-body>
-            <el-form :model="batchSetForm" label-width="120px">
-                <el-form-item label="保质期临期提醒">
+            <el-form :model="batchSetForm" label-width="120px" :rules="batchRules">
+                <el-form-item label="保质期临期提醒" prop="shelfLifeReminder">
                     <el-input v-model="batchSetForm.shelfLifeReminder" min="1" placeholder="请输入" style="width: 200px;">
                         <template #append>个月</template>
                     </el-input>
                 </el-form-item>
-                <el-form-item label="许可证临期提醒">
+                <el-form-item label="许可证临期提醒" prop="licenseExpiryReminder">
                     <el-input v-model="batchSetForm.licenseExpiryReminder" min="1" placeholder="请输入" style="width: 200px;">
                         <template #append>个月</template>
                     </el-input>
@@ -1034,10 +1032,10 @@
                         <el-divider content-position="left">基本信息:</el-divider>
                         <el-row :gutter="40" style="margin-top: 30px">
                             <el-col :span="12">
-                                <div><b>产品名称:</b>{{ form.productName || '--' }}</div>
-                                <div><b>院方系统编码:</b>{{ form.hospitalSystemCode || '--' }}</div>
-                                <div><b>商品编码:</b>{{ form.productCode || '--' }}</div>
-                                <div><b>产品所属分类:</b>{{ form.productCategory || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>产品名称:</b>{{ form.productName || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>院方系统编码:</b>{{ form.hospitalSystemCode || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>商品编码:</b>{{ form.productCode || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>产品所属分类:</b>{{ form.productCategory || '--' }}</div>
                                 <div><b>生产厂商:</b>{{ getDictLabel(product_manufacturer, form.manufacturer) || '--' }}</div>
                                 <div><b>品牌:</b>{{ form.brand || '--' }}</div>
                                 <div><b>产品所属标签:</b>{{ form.productLabel || '--' }}</div>
@@ -1045,33 +1043,33 @@
                                 <div><b>商品许可证有效期至:</b>{{ form.productLicenseExpiry ? (form.productLicenseExpiry.slice(0, 10)) : '--' }}</div>
                             </el-col>
                             <el-col :span="12">
-                                <div><b>商品资质:</b>{{ getDictLabel(product_qualification, form.productQualification) || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>商品资质:</b>{{ getDictLabel(product_qualification, form.productQualification) || '--' }}</div>
                                 <div><b>批准文号:</b>{{ form.approvalNumber || '--' }}</div>
                                 <div><b>口味:</b>{{ form.taste || '--' }}</div>
                                 <div><b>剂型/形态:</b>{{ getDictLabel(dosage_form, form.dosageForm) || '--' }}</div>
                                 <div><b>供应商:</b>{{ getDictLabel(product_supplier, form.supplier) || '--' }}</div>
                                 <div><b>产品适用科室:</b>{{ form.applicableDepartment|| '--'  }}</div>
                                 <div><b>禁忌症所属标签:</b>{{ form.contraindicationLabel || '--' }}</div>
-                                <div><b>保质期临期提醒:</b>{{ form.shelfLifeReminder || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>保质期临期提醒:</b>{{ form.shelfLifeReminder || '--' }}</div>
                                 <div><b>保质期:</b>{{ form.shelfLife || '--' }}</div>
                             </el-col>
                         </el-row>
                         <el-divider content-position="left">入货信息:</el-divider>
                         <el-row :gutter="40" style="margin-top: 30px">
                             <el-col :span="12">
-                                <div><b>入货价格:</b>{{ form.purchasePrice || '--' }} 元</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>入货价格:</b>{{ form.purchasePrice || '--' }} 元</div>
                                 <div><b>默认用法:</b>{{ getDictLabel(default_usage, form.defaultUsage) || '--' }}</div>
-                                <div><b>商品规格:</b>{{ form.productSpec || '--' }}{{getDictLabel(product_spec_unit ,form.productSpecUnit )|| '--' }}/{{getDictLabel(product_package_unit ,form.packageUnit )|| '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>商品规格:</b>{{ form.productSpec || '--' }}{{getDictLabel(product_spec_unit ,form.productSpecUnit )|| '--' }}/{{getDictLabel(product_package_unit ,form.packageUnit )|| '--' }}</div>
                             </el-col>
                             <el-col :span="12">
-                                <div><b>入货单位:</b>{{ getDictLabel(product_package_unit, form.purchaseUnit) || '--' }}</div>
-                                <div><b>预包装单位:</b>{{ getDictLabel(product_package_unit, form.packageUnit) || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>入货单位:</b>{{ getDictLabel(product_package_unit, form.purchaseUnit) || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>预包装单位:</b>{{ getDictLabel(product_package_unit, form.packageUnit) || '--' }}</div>
                             </el-col>
                         </el-row>
                         <el-divider content-position="left">预包装销售设置:</el-divider>
                         <el-row :gutter="40" style="margin-top: 30px">
                             <el-col :span="12">
-                                <div><b>预包装销售价:</b>{{ form.packagePrice || '--' }}元/{{ getDictLabel(product_package_unit, form.packageUnit) || '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>预包装销售价:</b>{{ form.packagePrice || '--' }}元/{{ getDictLabel(product_package_unit, form.packageUnit) || '--' }}</div>
                                 <div><b>最小包装规格:</b>{{ form.minSpec || '--' }} {{getDictLabel(product_spec_unit ,form.productSpecUnit )|| '--' }}/{{ getDictLabel(product_package_unit, form.minUnit) || '--' }}</div>
                             </el-col>
                             <el-col :span="12">
@@ -1082,7 +1080,7 @@
                         <el-divider content-position="left">配置销售设置:</el-divider>
                         <el-row :gutter="40" style="margin-top: 30px">
                             <el-col :span="12">
-                                <div><b>配置销售价格:</b>{{ form.configSalePrice || '--' }} 元/{{getDictLabel(product_spec_unit ,form.productSpecUnit )|| '--' }}</div>
+                                <div><b><span style="color:red;margin-right: 3px">*</span>配置销售价格:</b>{{ form.configSalePrice || '--' }} 元/{{getDictLabel(product_spec_unit ,form.productSpecUnit )|| '--' }}</div>
                             </el-col>
                             <el-col :span="12">
                                 <div><b>配置损耗率:</b>{{ form.configLossRate || '--' }} %</div>
@@ -1339,7 +1337,7 @@
                     <el-tab-pane label="其他" name="others">
                         <span style="color: red; font-size: 16px; margin-bottom: 10px">注:每100(g/ml) 含量</span>
                         <el-row :gutter="40" style="margin-top: 30px">
-                            <el-col :span="6" >
+                            <el-col :span="6">
                                 <div><b>血糖生成指数:</b>{{ form.bloodGlucoseIndex || '--' }} mg</div>
                             </el-col>
                             <el-col :span="6">
@@ -1431,555 +1429,574 @@
                 请上传 .xls , .xlsx 标准格式文件
             </div>
         </el-dialog>
+        <!-- 添加疾病标签弹窗 -->
+        <LabelDialog
+            v-model="diseaseLabelDialogVisible"
+            :initial-selected-labels="form.productLabelList || []"
+            @confirm="onLabelConfirm"
+        />
+        <!-- 添加禁忌症标签弹窗 -->
+        <LabelDialog
+            v-model="contraindicationLabelDialogVisible"
+            :initial-selected-labels="form.contraindicationLabelList || []"
+            @confirm="onContraindicationLabelConfirm"
+        />
     </div>
 </template>
 
-<script setup name="Nutrition" lang="ts">
-    import { listNutrition, getNutrition, delNutrition, addNutrition, updateNutrition, batchUpdateNutrition } from '@/api/warehouse/productNutrition/index';
-    import { NutritionVO, NutritionQuery, NutritionForm } from '@/api/warehouse/productNutrition/types';
-    import { listCategory } from '@/api/warehouse/productCategory/index';
-    import { listDept } from '@/api/system/dept';
-    import { globalHeaders } from '@/utils/request';
-    import { FormInstance, ElMessageBox, UploadFile, UploadFiles } from 'element-plus';
-    import { getCurrentInstance, ComponentInternalInstance, ref, reactive, toRefs, onMounted } from 'vue';
-    import { log } from 'console';
-    import lableDialog from './labelDialog.vue';
-    import FileUpload from '@/components/FileUpload/index.vue';
-    const diseaseLabelDialogVisible = ref(false);
-    const contraindicationLabelDialogVisible = ref(false);
-
-    const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-    const { product_qualification, dosage_form, product_package_unit, product_supplier, put_flag, product_manufacturer, default_usage, product_spec_unit } = toRefs < any > (proxy ?.useDict('product_qualification', 'dosage_form', 'product_package_unit', 'product_supplier', 'put_flag', 'product_manufacturer', 'default_usage', 'product_spec_unit'));
-
-
-    const nutritionList = ref < NutritionVO[] > ([]);
-    const baseUrl =
-        import.meta.env.VITE_APP_BASE_API; // 上传文件地址
-    const uploadFileUrl = ref(baseUrl + 'warehouse/nutrition/importExcel');
-    const buttonLoading = ref(false);
-    const loading = ref(true);
-    const showSearch = ref(true);
-    const ids = ref < Array < string | number >> ([]);
-    const single = ref(true);
-    const multiple = ref(true);
-    const total = ref(0);
-    const headers = ref(globalHeaders()); // 请求头设置
-
-    const activeTab = ref('basic');
-    const detailDialogVisible = ref(false);
-    const batchSetDialogVisible = ref(false);
-    const fileList = ref([]); // 用于Excel导入的文件列表
-    const batchSetForm = reactive({
-        shelfLifeReminder: '',
-        licenseExpiryReminder: ''
+<script setup lang="ts">
+import { ref, reactive, onMounted, getCurrentInstance } from 'vue';
+import { listNutrition, getNutrition, delNutrition, addNutrition, updateNutrition, batchUpdateNutrition } from '@/api/warehouse/productNutrition/index';
+import { NutritionVO, NutritionQuery, NutritionForm } from '@/api/warehouse/productNutrition/types';
+import { listCategory } from '@/api/warehouse/productCategory/index';
+import { listDept } from '@/api/system/dept';
+import { globalHeaders } from '@/utils/request';
+import { FormInstance, ElMessageBox, UploadFile, UploadFiles } from 'element-plus';
+import { log } from 'console';
+import LabelDialog from './labelDialog.vue';
+import FileUpload from '@/components/FileUpload/index.vue';
+
+const diseaseLabelDialogVisible = ref(false);
+const contraindicationLabelDialogVisible = ref(false);
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { product_qualification, dosage_form, product_package_unit, product_supplier, put_flag, product_manufacturer, default_usage, product_spec_unit } = toRefs < any > (proxy ?.useDict('product_qualification', 'dosage_form', 'product_package_unit', 'product_supplier', 'put_flag', 'product_manufacturer', 'default_usage', 'product_spec_unit'));
+
+
+const nutritionList = ref < NutritionVO[] > ([]);
+const baseUrl =
+    import.meta.env.VITE_APP_BASE_API; // 上传文件地址
+const uploadFileUrl = ref(baseUrl + 'warehouse/nutrition/importExcel');
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref < Array < string | number >> ([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const headers = ref(globalHeaders()); // 请求头设置
+
+const activeTab = ref('basic');
+const detailDialogVisible = ref(false);
+const batchSetDialogVisible = ref(false);
+const fileList = ref([]); // 用于Excel导入的文件列表
+const batchSetForm = reactive({
+    shelfLifeReminder: '',
+    licenseExpiryReminder: ''
+});
+
+const batchRules = {
+    shelfLifeReminder: [{ required: true, message: "保质期临期提醒不能为空", trigger: "blur" }],
+    licenseExpiryReminder: [{ required: true, message: "许可证临期提醒不能为空", trigger: "blur" }],
+
+};
+
+const treeData = ref([]); // 定义 treeData
+const deptList = ref([]); // 定义 科室list
+
+const queryFormRef = ref < FormInstance > ();
+const nutritionFormRef = ref < FormInstance > ();
+
+const dialog = reactive < DialogOption > ({
+    visible: false,
+    title: ''
+});
+const dialogFile = reactive < DialogOption > ({
+    visible: false,
+    title: '请上传'
+});
+
+const initFormData: NutritionForm = {
+    id: undefined,
+    ids: undefined,
+    productName: undefined,
+    hospitalSystemCode: undefined,
+    productCode: undefined,
+    productCategory: undefined,
+    productCategoryList: undefined,
+    manufacturer: undefined,
+    brand: undefined,
+    licenseExpiryReminder: undefined,
+    productLicenseExpiry: undefined,
+    productQualification: undefined,
+    approvalNumber: undefined,
+    taste: undefined,
+    dosageForm: undefined,
+    supplier: undefined,
+    applicableDepartment: undefined,
+    applicableDepartmentList: undefined,
+    contraindicationLabel: undefined,
+    shelfLifeReminder: undefined,
+    shelfLife: undefined,
+    purchasePrice: undefined,
+    purchaseUnit: '2',
+    defaultUsage: '2',
+    packageUnit: '2',
+    productSpec: undefined,
+    productSpecValue: undefined,
+    productSpecUnit: '1',
+    packagePrice: undefined,
+    minUnit: '3',
+    minSpec: undefined,
+    netContent: undefined,
+    configSalePrice: undefined,
+    configLossRate: undefined,
+    calorie: undefined,
+    carbohydrate: undefined,
+    heatEnergy: undefined,
+    protein: undefined,
+    fat: undefined,
+    moisture: undefined,
+    ca: undefined,
+    p: undefined,
+    k: undefined,
+    na: undefined,
+    mg: undefined,
+    cl: undefined,
+    fe: undefined,
+    zn: undefined,
+    se: undefined,
+    cu: undefined,
+    mn: undefined,
+    i: undefined,
+    f: undefined,
+    cr: undefined,
+    mo: undefined,
+    isoleucine: undefined,
+    tryptophan: undefined,
+    sulfurAminoAcid: undefined,
+    histidine: undefined,
+    aromaticAminoAcid: undefined,
+    glutamicAcid: undefined,
+    threonine: undefined,
+    serine: undefined,
+    arginine: undefined,
+    lysine: undefined,
+    asparticAcid: undefined,
+    cysteine: undefined,
+    proline: undefined,
+    tyrosine: undefined,
+    leucine: undefined,
+    valine: undefined,
+    methionine: undefined,
+    alanine: undefined,
+    phenylalanine: undefined,
+    glycine: undefined,
+    fattyAcid: undefined,
+    saturatedFattyAcid: undefined,
+    monounsaturatedFattyAcid: undefined,
+    polyunsaturatedFattyAcid: undefined,
+    vitaminA: undefined,
+    vitaminACarotene: undefined,
+    vitaminAAlcohol: undefined,
+    vitaminD: undefined,
+    vitaminE: undefined,
+    vitaminETocopherol: undefined,
+    vitaminK: undefined,
+    vitaminBOne: undefined,
+    vitaminBTwo: undefined,
+    vitaminBSix: undefined,
+    vitaminBTwelve: undefined,
+    niacin: undefined,
+    vitaminC: undefined,
+    folicAcid: undefined,
+    choline: undefined,
+    biotin: undefined,
+    pantothenicAcid: undefined,
+    cholesterol: undefined,
+    bloodGlucoseIndex: undefined,
+    insolubleDietaryFiber: undefined,
+    dietaryFiber: undefined,
+    ash: undefined,
+    solubleDietaryFiber: undefined,
+    applicableCrowd: undefined,
+    unsuitableCrowd: undefined,
+    osmoticPressure: undefined,
+    rawMaterial: undefined,
+    indicationsContraindications: undefined,
+    usageAndDosage: undefined,
+    productFeatures: undefined,
+    storageConditions: undefined,
+    warningInstructions: undefined,
+    productAttachments: undefined,
+    productAttachmentsList: [],
+    status: undefined,
+    putFlag: undefined,
+    outboundNumber: undefined,
+    productLabel: undefined,
+    productLabelList: [],
+    contraindicationLabelList: [],
+};
+
+const data = reactive < PageData < NutritionForm,
+    NutritionQuery >> ({
+        form: { ...initFormData },
+        queryParams: {
+            pageNum: 1,
+            pageSize: 10,
+            productName: undefined,
+            productCategory: undefined,
+            productCategoryList: [],
+        },
+        rules: {
+            productName: [
+                { required: true, message: "产品名称不能为空", trigger: "blur" }
+            ],
+            hospitalSystemCode: [
+                { required: true, message: "院方系统编码不能为空", trigger: "blur" }
+            ],
+            productCode: [
+                { required: true, message: "商品编码不能为空", trigger: "blur" }
+            ],
+            productCategory: [
+                { required: true, message: "产品所属分类不能为空", trigger: "blur" }
+            ],
+            productQualification: [
+                { required: true, message: "商品资质不能为空", trigger: "blur" }
+            ],
+            shelfLifeReminder: [
+                { required: true, message: "保质期临期提醒不能为空", trigger: "blur" }
+            ],
+            shelfLife: [
+                { required: true, message: "保质期不能为空", trigger: "blur" }
+            ],
+            purchasePrice: [
+                { required: true, message: "入货价格不能为空", trigger: "blur" }
+            ],
+            purchaseUnit: [
+                { required: true, message: "入货单位不能为空", trigger: "blur" }
+            ],
+            productSpec: [
+                { required: true, message: "商品规格不能为空", trigger: "blur" }
+            ],
+            configSalePrice: [
+                { required: true, message: "配置销售价格不能为空", trigger: "blur" }
+            ],
+            packagePrice: [
+                { required: true, message: "预包装价格不能为空", trigger: "blur" }
+            ],
+        }
     });
 
-    const treeData = ref([]); // 定义 treeData
-    const deptList = ref([]); // 定义 科室list
+const { queryParams, form, rules } = toRefs(data);
 
-    const queryFormRef = ref < FormInstance > ();
-    const nutritionFormRef = ref < FormInstance > ();
+const categoryOptions = ref([]);
 
-    const dialog = reactive < DialogOption > ({
-        visible: false,
-        title: ''
+function buildCategoryTree(flatList) {
+    const idMap = {};
+    const tree = [];
+    flatList.forEach(item => {
+        idMap[item.categoryId] = {
+            label: item.categoryName,
+            value: item.categoryId,
+            children: []
+        };
     });
-    const dialogFile = reactive < DialogOption > ({
-        visible: false,
-        title: '请上传'
+    flatList.forEach(item => {
+        if (item.parentId && item.parentId !== 0 && idMap[item.parentId]) {
+            idMap[item.parentId].children.push(idMap[item.categoryId]);
+        } else if (item.parentId === 0) {
+            tree.push(idMap[item.categoryId]);
+        }
     });
-
-    const initFormData: NutritionForm = {
-        id: undefined,
-        ids: undefined,
-        productName: undefined,
-        hospitalSystemCode: undefined,
-        productCode: undefined,
-        productCategory: undefined,
-        productCategoryList: undefined,
-        manufacturer: undefined,
-        brand: undefined,
-        licenseExpiryReminder: undefined,
-        productLicenseExpiry: undefined,
-        productQualification: undefined,
-        approvalNumber: undefined,
-        taste: undefined,
-        dosageForm: undefined,
-        supplier: undefined,
-        applicableDepartment: undefined,
-        applicableDepartmentList: undefined,
-        contraindicationLabel: undefined,
-        shelfLifeReminder: undefined,
-        shelfLife: undefined,
-        purchasePrice: undefined,
-        purchaseUnit: '2',
-        defaultUsage: '2',
-        packageUnit: '2',
-        productSpec: undefined,
-        productSpecValue: undefined,
-        productSpecUnit: '1',
-        packagePrice: undefined,
-        minUnit: '3',
-        minSpec: undefined,
-        netContent: undefined,
-        configSalePrice: undefined,
-        configLossRate: undefined,
-        calorie: undefined,
-        carbohydrate: undefined,
-        heatEnergy: undefined,
-        protein: undefined,
-        fat: undefined,
-        moisture: undefined,
-        ca: undefined,
-        p: undefined,
-        k: undefined,
-        na: undefined,
-        mg: undefined,
-        cl: undefined,
-        fe: undefined,
-        zn: undefined,
-        se: undefined,
-        cu: undefined,
-        mn: undefined,
-        i: undefined,
-        f: undefined,
-        cr: undefined,
-        mo: undefined,
-        isoleucine: undefined,
-        tryptophan: undefined,
-        sulfurAminoAcid: undefined,
-        histidine: undefined,
-        aromaticAminoAcid: undefined,
-        glutamicAcid: undefined,
-        threonine: undefined,
-        serine: undefined,
-        arginine: undefined,
-        lysine: undefined,
-        asparticAcid: undefined,
-        cysteine: undefined,
-        proline: undefined,
-        tyrosine: undefined,
-        leucine: undefined,
-        valine: undefined,
-        methionine: undefined,
-        alanine: undefined,
-        phenylalanine: undefined,
-        glycine: undefined,
-        fattyAcid: undefined,
-        saturatedFattyAcid: undefined,
-        monounsaturatedFattyAcid: undefined,
-        polyunsaturatedFattyAcid: undefined,
-        vitaminA: undefined,
-        vitaminACarotene: undefined,
-        vitaminAAlcohol: undefined,
-        vitaminD: undefined,
-        vitaminE: undefined,
-        vitaminETocopherol: undefined,
-        vitaminK: undefined,
-        vitaminBOne: undefined,
-        vitaminBTwo: undefined,
-        vitaminBSix: undefined,
-        vitaminBTwelve: undefined,
-        niacin: undefined,
-        vitaminC: undefined,
-        folicAcid: undefined,
-        choline: undefined,
-        biotin: undefined,
-        pantothenicAcid: undefined,
-        cholesterol: undefined,
-        bloodGlucoseIndex: undefined,
-        insolubleDietaryFiber: undefined,
-        dietaryFiber: undefined,
-        ash: undefined,
-        solubleDietaryFiber: undefined,
-        applicableCrowd: undefined,
-        unsuitableCrowd: undefined,
-        osmoticPressure: undefined,
-        rawMaterial: undefined,
-        indicationsContraindications: undefined,
-        usageAndDosage: undefined,
-        productFeatures: undefined,
-        storageConditions: undefined,
-        warningInstructions: undefined,
-        productAttachments: undefined,
-        productAttachmentsList: [],
-        status: undefined,
-        putFlag: undefined,
-        outboundNumber: undefined,
-        productLabel: undefined,
-        productLabelList: [],
-        contraindicationLabelList: [],
-    };
-
-    const data = reactive < PageData < NutritionForm,
-        NutritionQuery >> ({
-            form: { ...initFormData },
-            queryParams: {
-                pageNum: 1,
-                pageSize: 10,
-                productName: undefined,
-                productCategory: undefined,
-                productCategoryList: [],
-            },
-            rules: {
-                productName: [
-                    { required: true, message: "产品名称不能为空", trigger: "blur" }
-                ],
-                hospitalSystemCode: [
-                    { required: true, message: "院方系统编码不能为空", trigger: "blur" }
-                ],
-                productCode: [
-                    { required: true, message: "商品编码不能为空", trigger: "blur" }
-                ],
-                productCategory: [
-                    { required: true, message: "产品所属分类不能为空", trigger: "blur" }
-                ],
-                productQualification: [
-                    { required: true, message: "商品资质不能为空", trigger: "blur" }
-                ],
-                shelfLifeReminder: [
-                    { required: true, message: "保质期临期提醒不能为空", trigger: "blur" }
-                ],
-                shelfLife: [
-                    { required: true, message: "保质期不能为空", trigger: "blur" }
-                ],
-                purchasePrice: [
-                    { required: true, message: "入货价格不能为空", trigger: "blur" }
-                ],
-                purchaseUnit: [
-                    { required: true, message: "入货单位不能为空", trigger: "blur" }
-                ],
-                productSpec: [
-                    { required: true, message: "商品规格不能为空", trigger: "blur" }
-                ],
-                configSalePrice: [
-                    { required: true, message: "配置销售价格不能为空", trigger: "blur" }
-                ],
-                packagePrice: [
-                    { required: true, message: "预包装价格不能为空", trigger: "blur" }
-                ],
-            }
-        });
-
-    const { queryParams, form, rules } = toRefs(data);
-
-    const categoryOptions = ref([]);
-
-    function buildCategoryTree(flatList) {
-        const idMap = {};
-        const tree = [];
-        flatList.forEach(item => {
-            idMap[item.categoryId] = {
-                label: item.categoryName,
-                value: item.categoryId,
-                children: []
-            };
-        });
-        flatList.forEach(item => {
-            if (item.parentId && item.parentId !== 0 && idMap[item.parentId]) {
-                idMap[item.parentId].children.push(idMap[item.categoryId]);
-            } else if (item.parentId === 0) {
-                tree.push(idMap[item.categoryId]);
-            }
-        });
-        // 去除没有children的children字段
-        function clean(node) {
-            if (node.children && node.children.length === 0) {
-                delete node.children;
-            } else if (node.children) {
-                node.children.forEach(clean);
-            }
+    // 去除没有children的children字段
+    function clean(node) {
+        if (node.children && node.children.length === 0) {
+            delete node.children;
+        } else if (node.children) {
+            node.children.forEach(clean);
         }
-        tree.forEach(clean);
-        return tree;
-    }
-
-    /** 查询营养产品信息列表 */
-    const getList = async () => {
-
-        loading.value = true;
-        const res = await listNutrition(queryParams.value);
-        nutritionList.value = res.rows;
-        total.value = res.total;
-        loading.value = false;
     }
-
-    const getDeptList = async () => {
-        loading.value = true;
-        try {
-            const res = await listDept({});
-            if (!res.data) {
-                console.warn("部门数据为空");
-                deptList.value = [];
-                return;
-            }
-
-            // 处理树形数据
-            const processedData = proxy ?.handleTree(res.data, 'deptId');
-            if (!processedData) {
-                console.warn("树形数据处理失败");
-                deptList.value = [];
-                return;
-            }
-
-            deptList.value = processedData;
-
-        } catch (error) {
-            console.error('获取部门列表失败:', error);
+    tree.forEach(clean);
+    return tree;
+}
+
+/** 查询营养产品信息列表 */
+const getList = async () => {
+
+    loading.value = true;
+    const res = await listNutrition(queryParams.value);
+    nutritionList.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+}
+
+const getDeptList = async () => {
+    loading.value = true;
+    try {
+        const res = await listDept({});
+        if (!res.data) {
+            console.warn("部门数据为空");
             deptList.value = [];
-        } finally {
-            loading.value = false;
-        }
-    };
-
-    /** 导出按钮操作 */
-    const downLoadTemplate = () => {
-        proxy ?.getDownload('warehouse/nutrition/downLoadTemplate', {}, `营养产品模版.xlsx`)
-    }
-
-    /** 导入按钮操作 */
-    const handleImport = () => {
-        dialogFile.visible = true;
-        fileList.value = [];
-    }
-
-    // 上传失败
-    const handleUploadError = () => {
-        proxy ?.$modal.msgError('上传Excel失败');
-        proxy ?.$modal.closeLoading();
-    };
-
-    // 上传成功回调
-    const handleUploadSuccess = (res: any, file: UploadFile) => {
-        if (res.code === 200) {
-            dialogFile.visible = false;
-            fileList.value = [];
-            proxy ?.$modal.closeLoading();
-        } else {
-            proxy ?.$modal.msgError(res.msg);
-            proxy ?.$modal.closeLoading();
-        }
-        fileList.value = [];
-    };
-
-
-    /** 上传前loading加载 */
-    const handleBeforeUpload = (file: any) => {
-        const isLt = file.size / 1024 / 1024 < 10;
-        if (!isLt) {
-            proxy ?.$modal.msgError(`上传头像图片大小不能超过10MB!`);
-            return false;
+            return;
         }
-        proxy ?.$modal.loading('正在上传文件,请稍候...');
-        return true;
-    };
 
-    function openBatchSetDialog() {
-        if (!ids.value.length) {
-            proxy ?.$modal.msgWarning('请先选择要批量设置的产品');
+        // 处理树形数据
+        const processedData = proxy ?.handleTree(res.data, 'deptId');
+        if (!processedData) {
+            console.warn("树形数据处理失败");
+            deptList.value = [];
             return;
         }
-        batchSetForm.shelfLifeReminder = '';
-        batchSetForm.licenseExpiryReminder = '';
-        batchSetDialogVisible.value = true;
-    }
 
-    async function handleBatchSetSubmit() {
-        const params = {
-            ids: ids.value,
-            shelfLifeReminder: batchSetForm.shelfLifeReminder,
-            licenseExpiryReminder: batchSetForm.licenseExpiryReminder
-        };
+        deptList.value = processedData;
 
-        try {
-            await batchUpdateNutrition(params);
-            proxy ?.$modal.msgSuccess('批量设置成功');
-            batchSetDialogVisible.value = false;
-            getList();
-        } catch (e) {
-            proxy ?.$modal.msgError('批量设置失败');
-        }
-    }
-    /** 取消按钮 */
-    const cancel = () => {
-        reset();
-        dialog.visible = false;
+    } catch (error) {
+        console.error('获取部门列表失败:', error);
+        deptList.value = [];
+    } finally {
+        loading.value = false;
     }
-
-    /** 表单重置 */
-    const reset = () => {
-        form.value = { ...initFormData };
-        nutritionFormRef.value ?.resetFields();
+};
+
+/** 下载模板按钮操作 */
+const downLoadTemplate = () => {
+    proxy ?.getDownload('warehouse/nutrition/downLoadTemplate', {}, `营养产品模版.xlsx`)
+}
+
+/** 导入按钮操作 */
+const handleImport = () => {
+    dialogFile.visible = true;
+    fileList.value = [];
+}
+
+// 上传失败
+const handleUploadError = () => {
+    proxy ?.$modal.msgError('上传Excel失败');
+    proxy ?.$modal.closeLoading();
+};
+
+// 上传成功回调
+const handleUploadSuccess = (res: any, file: UploadFile) => {
+    if (res.code === 200) {
+        dialogFile.visible = false;
         fileList.value = [];
+        proxy ?.$modal.closeLoading();
+    } else {
+        proxy ?.$modal.msgError(res.msg);
+        proxy ?.$modal.closeLoading();
     }
+    fileList.value = [];
+};
 
-    /** 搜索按钮操作 */
-    const handleQuery = () => {
-        // 取最后一级分类ID传给后端
-        if (queryParams.value.productCategoryList && queryParams.value.productCategoryList.length) {
-            queryParams.value.productCategory = queryParams.value.productCategoryList.slice(-1)[0];
-        } else {
-            queryParams.value.productCategory = undefined;
-        }
-        queryParams.value.pageNum = 1;
-        getList();
-    }
 
-    /** 重置按钮操作 */
-    const resetQuery = () => {
-        queryFormRef.value ?.resetFields();
-        queryParams.value.productCategoryList = [];
-        queryParams.value.productCategory = undefined;
-        queryParams.value.productName = undefined;
-        handleQuery();
+/** 上传前loading加载 */
+const handleBeforeUpload = (file: any) => {
+    const isLt = file.size / 1024 / 1024 < 10;
+    if (!isLt) {
+        proxy ?.$modal.msgError(`上传头像图片大小不能超过10MB!`);
+        return false;
     }
-
-    /** 多选框选中数据 */
-    const handleSelectionChange = (selection: NutritionVO[]) => {
-        ids.value = selection.map(item => item.id);
-        single.value = selection.length != 1;
-        multiple.value = !selection.length;
+    proxy ?.$modal.loading('正在上传文件,请稍候...');
+    return true;
+};
+
+function openBatchSetDialog() {
+    if (!ids.value.length) {
+        proxy ?.$modal.msgWarning('请先选择要批量设置的产品');
+        return;
     }
+    batchSetForm.shelfLifeReminder = '';
+    batchSetForm.licenseExpiryReminder = '';
+    batchSetDialogVisible.value = true;
+}
+
+async function handleBatchSetSubmit() {
+    const params = {
+        ids: ids.value,
+        shelfLifeReminder: batchSetForm.shelfLifeReminder,
+        licenseExpiryReminder: batchSetForm.licenseExpiryReminder
+    };
 
-    /** 新增按钮操作 */
-    const handleAdd = () => {
-        reset();
-        dialog.visible = true;
-        dialog.title = "添加营养产品信息";
+    try {
+        await batchUpdateNutrition(params);
+        proxy ?.$modal.msgSuccess('批量设置成功');
+        batchSetDialogVisible.value = false;
+        getList();
+    } catch (e) {
+        proxy ?.$modal.msgError('批量设置失败');
     }
-
-    /** 修改按钮操作 */
-    const handleUpdate = async (row ? : NutritionVO) => {
-        reset();
-        const _id = row ?.id || ids.value[0]
-        const res = await getNutrition(_id);
-        Object.assign(form.value, res.data);
-        dialog.visible = true;
-        dialog.title = "修改营养产品信息";
+}
+/** 取消按钮 */
+const cancel = () => {
+    reset();
+    dialog.visible = false;
+}
+
+/** 表单重置 */
+const reset = () => {
+    form.value = { ...initFormData };
+    nutritionFormRef.value ?.resetFields();
+    fileList.value = [];
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+    // 取最后一级分类ID传给后端
+    if (queryParams.value.productCategoryList && queryParams.value.productCategoryList.length) {
+        queryParams.value.productCategory = queryParams.value.productCategoryList.slice(-1)[0];
+    } else {
+        queryParams.value.productCategory = undefined;
     }
-
-    /** 提交按钮 */
-    const submitForm = () => {
-        nutritionFormRef.value ?.validate(async (valid: boolean) => {
-            if (valid) {
-                buttonLoading.value = true;
-                // form.value.productSpec = form.value.productSpec && form.value.productSpecUnit ? `${form.value.productSpec}${form.value.productSpecUnit}` : '';
-                if (form.value.id) {
-                    await updateNutrition(form.value).finally(() => buttonLoading.value = false);
-                } else {
-                    await addNutrition(form.value).finally(() => buttonLoading.value = false);
-                }
-                proxy ?.$modal.msgSuccess("操作成功");
-                dialog.visible = false;
-                await getList();
+    queryParams.value.pageNum = 1;
+    getList();
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+    queryFormRef.value ?.resetFields();
+    queryParams.value.productCategoryList = [];
+    queryParams.value.productCategory = undefined;
+    queryParams.value.productName = undefined;
+    handleQuery();
+}
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: NutritionVO[]) => {
+    ids.value = selection.map(item => item.id);
+    single.value = selection.length != 1;
+    multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+    reset();
+    dialog.visible = true;
+    dialog.title = "添加营养产品信息";
+}
+
+/** 修改按钮操作 */
+const handleUpdate = async (row ? : NutritionVO) => {
+    reset();
+    const _id = row ?.id || ids.value[0]
+    const res = await getNutrition(_id);
+    Object.assign(form.value, res.data);
+    dialog.visible = true;
+    dialog.title = "修改营养产品信息";
+}
+
+/** 提交按钮 */
+const submitForm = () => {
+    nutritionFormRef.value ?.validate(async (valid: boolean) => {
+        if (valid) {
+            buttonLoading.value = true;
+            // form.value.productSpec = form.value.productSpec && form.value.productSpecUnit ? `${form.value.productSpec}${form.value.productSpecUnit}` : '';
+            if (form.value.id) {
+                await updateNutrition(form.value).finally(() => buttonLoading.value = false);
+            } else {
+                await addNutrition(form.value).finally(() => buttonLoading.value = false);
             }
-        });
-    }
-
-    /** 保存并上架按钮操作 */
-    const submitFormAndPutaway = () => {
-        nutritionFormRef.value ?.validate(async (valid: boolean) => {
-            if (valid) {
-                buttonLoading.value = true;
-                form.value.putFlag = '1';
-                // form.value.productSpec = form.value.productSpec && form.value.productSpecUnit ? `${form.value.productSpec}${form.value.productSpecUnit}` : '';
-                if (form.value.id) {
-                    await updateNutrition(form.value).finally(() => buttonLoading.value = false);
-                } else {
-                    await addNutrition(form.value).finally(() => buttonLoading.value = false);
-                }
-                proxy ?.$modal.msgSuccess("操作成功");
-                dialog.visible = false;
-                await getList();
+            proxy ?.$modal.msgSuccess("操作成功");
+            dialog.visible = false;
+            await getList();
+        }
+    });
+}
+
+/** 保存并上架按钮操作 */
+const submitFormAndPutaway = () => {
+    nutritionFormRef.value ?.validate(async (valid: boolean) => {
+        if (valid) {
+            buttonLoading.value = true;
+            form.value.putFlag = '1';
+            // form.value.productSpec = form.value.productSpec && form.value.productSpecUnit ? `${form.value.productSpec}${form.value.productSpecUnit}` : '';
+            if (form.value.id) {
+                await updateNutrition(form.value).finally(() => buttonLoading.value = false);
+            } else {
+                await addNutrition(form.value).finally(() => buttonLoading.value = false);
             }
-        });
-    }
-
-    /** 删除按钮操作 */
-    const handleDelete = async (row ? : NutritionVO) => {
-        const _ids = row ?.id || ids.value;
-        await proxy ?.$modal.confirm('是否确认删除营养产品信息编号为"' + _ids + '"的数据项?');
-        await delNutrition(_ids);
-        proxy ?.$modal.msgSuccess("删除成功");
-        await getList();
-    }
-
-    /** 导出按钮操作 */
-    const handleExport = () => {
-        proxy ?.download('warehouse/nutrition/export', {
-            ...queryParams.value
-        }, `nutrition_${new Date().getTime()}.xlsx`)
-    }
-
-
-
-    const onSpecUnitChange = () => {
-        if (!form.value.productSpecUnit) form.value.productSpecUnit = 'g';
-    }
-
-    // 详情弹窗逻辑
-    const handleDetail = async (row: NutritionVO) => {
-        reset();
-        const res = await getNutrition(row.id);
-        Object.assign(form.value, res.data);
-        detailDialogVisible.value = true;
-        activeTab.value = 'basic';
-    };
-
-    // 上下架切换
-    const handlePutFlag = async (row: NutritionVO, flag: string) => {
-        await proxy ?.$modal.confirm(`是否确认${flag === '1' ? '上架' : '下架'}该产品?`);
-        const updateData = { ...row, putFlag: flag };
-        await updateNutrition(updateData);
-        proxy ?.$modal.msgSuccess(`${flag === '1' ? '上架' : '下架'}成功`);
-        await getList();
-    };
-
-    onMounted(async () => {
-        getList();
-        getDeptList(); // 初始化时加载部门数据
-        const res = await listCategory();
-        categoryOptions.value = buildCategoryTree(res.rows || []);
-        if (!form.value.productSpecUnit) form.value.productSpecUnit = 'g';
+            proxy ?.$modal.msgSuccess("操作成功");
+            dialog.visible = false;
+            await getList();
+        }
     });
-
-    const getCategoryName = (categoryIds) => {
-        if (!categoryIds) return '--';
-
-        // 处理多个分类ID的情况
-        const ids = categoryIds.toString().split(',');
-        const categoryNames = ids.map(id => {
-            const findCategory = (categories, targetId) => {
-                for (const category of categories) {
-                    if (category.value.toString() === targetId.toString()) {
-                        return category.label;
-                    }
-                    if (category.children) {
-                        const found = findCategory(category.children, targetId);
-                        if (found) return found;
-                    }
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (row ? : NutritionVO) => {
+    const _ids = row ?.id || ids.value;
+    await proxy ?.$modal.confirm('是否确认删除营养产品信息编号为"' + _ids + '"的数据项?');
+    await delNutrition(_ids);
+    proxy ?.$modal.msgSuccess("删除成功");
+    await getList();
+}
+
+/** 导出按钮操作 */
+const handleExport = () => {
+    proxy ?.download('warehouse/nutrition/export', {
+        ...queryParams.value
+    }, `nutrition_${new Date().getTime()}.xlsx`)
+}
+
+
+
+const onSpecUnitChange = () => {
+    if (!form.value.productSpecUnit) form.value.productSpecUnit = 'g';
+}
+
+// 详情弹窗逻辑
+const handleDetail = async (row: NutritionVO) => {
+    reset();
+    const res = await getNutrition(row.id);
+    Object.assign(form.value, res.data);
+    detailDialogVisible.value = true;
+    activeTab.value = 'basic';
+};
+
+// 上下架切换
+const handlePutFlag = async (row: NutritionVO, flag: string) => {
+    await proxy ?.$modal.confirm(`是否确认${flag === '1' ? '上架' : '下架'}该产品?`);
+    const updateData = { ...row, putFlag: flag };
+    await updateNutrition(updateData);
+    proxy ?.$modal.msgSuccess(`${flag === '1' ? '上架' : '下架'}成功`);
+    await getList();
+};
+
+onMounted(async () => {
+    getList();
+    getDeptList(); // 初始化时加载部门数据
+    const res = await listCategory();
+    categoryOptions.value = buildCategoryTree(res.rows || []);
+    if (!form.value.productSpecUnit) form.value.productSpecUnit = 'g';
+});
+
+const getCategoryName = (categoryIds) => {
+    if (!categoryIds) return '--';
+
+    // 处理多个分类ID的情况
+    const ids = categoryIds.toString().split(',');
+    const categoryNames = ids.map(id => {
+        const findCategory = (categories, targetId) => {
+            for (const category of categories) {
+                if (category.value.toString() === targetId.toString()) {
+                    return category.label;
                 }
-                return null;
-            };
-            return findCategory(categoryOptions.value, id);
-        }).filter(name => name !== null);
-
-        return categoryNames.length > 0 ? categoryNames.join('/') : '--';
-    };
-
-    // 弹窗回填
-    function onLabelConfirm(selectedLabels) {
-        form.value.productLabelList = selectedLabels;
-    }
-
-    function onContraindicationLabelConfirm(selectedLabels) {
-        form.value.contraindicationLabelList = selectedLabels;
-    } // 字典label工具
-    function getDictLabel(dictList, value) {
-        if (!dictList || !Array.isArray(dictList)) return value || '--';
-        const found = dictList.find(item => item.value === value);
-        return found ? found.label : value || '--';
-    }
+                if (category.children) {
+                    const found = findCategory(category.children, targetId);
+                    if (found) return found;
+                }
+            }
+            return null;
+        };
+        return findCategory(categoryOptions.value, id);
+    }).filter(name => name !== null);
+
+    return categoryNames.length > 0 ? categoryNames.join('/') : '--';
+};
+
+// 弹窗回填
+function onLabelConfirm(selectedLabels) {
+    form.value.productLabelList = selectedLabels;
+}
+
+function onContraindicationLabelConfirm(selectedLabels) {
+    form.value.contraindicationLabelList = selectedLabels;
+} // 字典label工具
+function getDictLabel(dictList, value) {
+    if (!dictList || !Array.isArray(dictList)) return value || '--';
+    const found = dictList.find(item => item.value === value);
+    return found ? found.label : value || '--';
+}
 </script>
 
 <style lang="scss" scoped>

+ 124 - 101
src/views/warehouse/nutriProduct/labelDialog.vue

@@ -14,7 +14,7 @@
                     <el-button type="primary" class="search-btn" @click="fetchData">查询</el-button>
                     <el-button class="add-btn" @click="addDialogVisible = true">新增疾病标签</el-button>
                 </div>
-                <el-table :data="tableData" border class="disease-table" style="width: 100%; min-height: 360px" @selection-change="handleSelectionChange" :row-class-name="rowClassName">
+                <el-table :data="tableData" border class="disease-table" style="width: 100%; min-height: 360px" @selection-change="handleSelectionChange" :row-class-name="rowClassName" ref="tableRef">
                     <el-table-column type="selection" width="48" align="center" />
                     <el-table-column prop="labelName" label="疾病/部位名称" min-width="120" align="center" />
                     <el-table-column prop="categoryName" label="所属分类" min-width="100" align="center" />
@@ -70,117 +70,140 @@
 </template>
 
 <script setup lang="ts">
-    import { ref, watch, defineProps, defineEmits } from 'vue';
-    import { listDiseaseLabel, addDiseaseLabel } from '@/api/system/diseaseLabel';
-    const props = defineProps < { modelValue: boolean } > ();
-    const emit = defineEmits(['update:modelValue', 'confirm']);
-    const visible = ref(props.modelValue);
-    watch(() => props.modelValue, (v) => { visible.value = v; });
-    watch(visible, (v) => { emit('update:modelValue', v); });
-
-    const activeTab = ref('1');
-    const search = ref('');
-    const tableData = ref < any[] > ([]);
-    const total = ref(0);
-    const pageNum = ref(1);
-    const pageSize = ref(10);
-    const selectedLabels = ref < any[] > ([]);
-
-    // 新增弹窗相关
-    const addDialogVisible = ref(false);
-    const addFormRef = ref();
-    const addForm = ref({ labelName: '', category: '', labelCode: '' });
-    const addRules = {
-        labelName: [{ required: true, message: '请输入疾病/部位名称', trigger: 'blur' }],
-        category: [{ required: true, message: '请选择所属分类', trigger: 'change' }],
-        labelCode: [{ required: true, message: '请输入疾病/部位编码', trigger: 'blur' }],
-    };
-
-    function resetAddForm() {
-        addForm.value = { labelName: '', category: '', labelCode: '' };
-        addFormRef.value ?.resetFields();
-    }
-
-    function submitAddForm() {
-        addFormRef.value ?.validate(async (valid: boolean) => {
-            console.log(addForm.value);
-            if (valid) {
-                await addDiseaseLabel(addForm.value);
-                addDialogVisible.value = false;
-                fetchData();
-            }
-        });
-    }
-
-    function fetchData() {
-        listDiseaseLabel({
-            pageNum: pageNum.value,
-            pageSize: pageSize.value,
-            labelName: search.value,
-            labelCode: search.value,
-            category: activeTab.value,
-            params: {}
-        }).then((res) => {
-            let arr: any[] = [];
-            let t = 0;
-            if (Array.isArray(res.rows)) {
-                arr = res.rows;
-                t = res.total || arr.length || 0;
-            } else if (Array.isArray(res.data)) {
-                arr = res.data;
-                t = arr.length;
-            } else if (res.data && Array.isArray((res.data as any).rows)) {
-                arr = (res.data as any).rows;
-                t = (res.data as any).total || arr.length || 0;
-            }
-            tableData.value = arr;
-            total.value = t;
-        }).catch((error) => {
-            console.error('fetchData error:', error);
-            tableData.value = [];
-            total.value = 0;
+import { ref, watch, defineProps, defineEmits, nextTick } from 'vue';
+import { listDiseaseLabel, addDiseaseLabel } from '@/api/system/diseaseLabel';
+
+const props = defineProps<{ modelValue: boolean; initialSelectedLabels?: any[] }>();
+const emit = defineEmits(['update:modelValue', 'confirm']);
+const visible = ref(props.modelValue);
+const tableRef = ref();
+
+watch(() => props.modelValue, (v) => { 
+    visible.value = v;
+    if (v && props.initialSelectedLabels?.length) {
+        // 当弹窗打开且有初始选中标签时,设置选中状态
+        nextTick(() => {
+            selectedLabels.value = props.initialSelectedLabels;
+            props.initialSelectedLabels.forEach(label => {
+                const matchingRow = tableData.value.find(row => row.labelCode === label.labelCode);
+                if (matchingRow) {
+                    tableRef.value?.toggleRowSelection(matchingRow, true);
+                }
+            });
         });
     }
+});
+watch(visible, (v) => { emit('update:modelValue', v); });
+
+const activeTab = ref('1');
+const search = ref('');
+const tableData = ref < any[] > ([]);
+const total = ref(0);
+const pageNum = ref(1);
+const pageSize = ref(10);
+const selectedLabels = ref < any[] > ([]);
+
+// 新增弹窗相关
+const addDialogVisible = ref(false);
+const addFormRef = ref();
+const addForm = ref({ labelName: '', category: '', labelCode: '' });
+const addRules = {
+    labelName: [{ required: true, message: '请输入疾病/部位名称', trigger: 'blur' }],
+    category: [{ required: true, message: '请选择所属分类', trigger: 'change' }],
+    labelCode: [{ required: true, message: '请输入疾病/部位编码', trigger: 'blur' }],
+};
+
+function resetAddForm() {
+    addForm.value = { labelName: '', category: '', labelCode: '' };
+    addFormRef.value ?.resetFields();
+}
+
+function submitAddForm() {
+    addFormRef.value ?.validate(async (valid: boolean) => {
+        console.log(addForm.value);
+        if (valid) {
+            await addDiseaseLabel(addForm.value);
+            addDialogVisible.value = false;
+            fetchData();
+        }
+    });
+}
+
+function fetchData() {
+    listDiseaseLabel({
+        pageNum: pageNum.value,
+        pageSize: pageSize.value,
+        labelName: search.value,
+        labelCode: search.value,
+        category: activeTab.value,
+        params: {}
+    }).then((res) => {
+        let arr: any[] = [];
+        let t = 0;
+        if (Array.isArray(res.rows)) {
+            arr = res.rows;
+            t = res.total || arr.length || 0;
+        } else if (Array.isArray(res.data)) {
+            arr = res.data;
+            t = arr.length;
+        } else if (res.data && Array.isArray((res.data as any).rows)) {
+            arr = (res.data as any).rows;
+            t = (res.data as any).total || arr.length || 0;
+        }
+        tableData.value = arr;
+        total.value = t;
+    }).catch((error) => {
+        console.error('fetchData error:', error);
+        tableData.value = [];
+        total.value = 0;
+    });
+}
+
+function onTabChange() {
+    pageNum.value = 1;
+    fetchData();
+}
 
-    function onTabChange() {
-        pageNum.value = 1;
-        fetchData();
-    }
+function handleSelectionChange(val: any[]) {
+    selectedLabels.value = val;
+}
 
-    function handleSelectionChange(val: any[]) {
-        selectedLabels.value = val;
-    }
+function handleSizeChange(size: number) {
+    pageSize.value = size;
+    pageNum.value = 1;
+    fetchData();
+}
 
-    function handleSizeChange(size: number) {
-        pageSize.value = size;
-        pageNum.value = 1;
-        fetchData();
-    }
+function handlePageChange(page: number) {
+    pageNum.value = page;
+    fetchData();
+}
 
-    function handlePageChange(page: number) {
-        pageNum.value = page;
-        fetchData();
-    }
+function removeLabel(row: any) {
+    selectedLabels.value = selectedLabels.value.filter((l) => l.labelCode !== row.labelCode);
+}
 
-    function removeLabel(row: any) {
-        selectedLabels.value = selectedLabels.value.filter((l) => l.labelCode !== row.labelCode);
-    }
+function handleConfirm() {
+    emit('confirm', selectedLabels.value);
+    visible.value = false;
+}
 
-    function handleConfirm() {
-        emit('confirm', selectedLabels.value);
-        visible.value = false;
-    }
+function handleCancel() {
+    visible.value = false;
+}
 
-    function handleCancel() {
-        visible.value = false;
-    }
+function rowClassName({ rowIndex }: { rowIndex: number }) {
+    return rowIndex % 2 === 1 ? 'table-row-stripe' : '';
+}
 
-    function rowClassName({ rowIndex }: { rowIndex: number }) {
-        return rowIndex % 2 === 1 ? 'table-row-stripe' : '';
-    }
+// 初始化
+fetchData();
+</script>
 
-    // 初始化
-    fetchData();
+<script lang="ts">
+export default {
+    name: 'LabelDialog'
+};
 </script>
 
 <style scoped>

+ 488 - 0
src/views/warehouse/suppliesManage/addOrEditForm.vue

@@ -0,0 +1,488 @@
+<template>
+    <el-card shadow="always">
+        <el-button type="primary" plain size="large" @click="goBack">返回</el-button>
+        <span style="margin-left: 20px;">新增耗材</span>
+
+    </el-card>
+    <div class="add-or-edit-supplies-manage">
+        <el-form ref="SuppliesManageFormRef" :model="form" :rules="rules" label-width="160px" style="padding: 20px;">
+
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="耗材名称:" prop="suppliesName">
+                        <el-input v-model="form.suppliesName" placeholder="请输入" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="商品资质:" prop="productQualification">
+                        <el-select v-model="form.productQualification" placeholder="请选择" clearable>
+                            <el-option v-for="dict in product_qualification" :key="dict.value" :label="dict.label" :value="dict.value" />
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="商品编码:" prop="suppliesCode">
+                        <el-input v-model="form.suppliesCode" placeholder="请输入" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="批准文号:" prop="approvalNumber">
+                        <el-input v-model="form.approvalNumber" placeholder="请输入" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="院方系统编码:" prop="hospitalSystemCode">
+                        <el-input v-model="form.hospitalSystemCode" placeholder="请输入" />
+                    </el-form-item>
+                </el-col>
+
+                <el-col :span="12">
+                    <el-form-item label="所属分类:" prop="suppliesCategoryList">
+                        <el-cascader v-model="form.suppliesCategoryList" :options="categoryOptions" :props="{ 
+                                checkStrictly: true, 
+                                emitPath: true, 
+                                value: 'value', 
+                                label: 'label', 
+                                children: 'children' 
+                            }" placeholder="请选择" clearable filterable style="width: 100%" @change="handleCategoryChange" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="生产厂商:" prop="manufacturer">
+                        <el-select v-model="form.manufacturer" placeholder="请选择" clearable>
+                            <el-option v-for="dict in product_manufacturer" :key="dict.value" :label="dict.label" :value="dict.value" />
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="保质期临期提醒:" prop="shelfLifeReminder">
+                        <el-input v-model="form.shelfLifeReminder" placeholder="请输入">
+                            <template #append>个月</template>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+
+            </el-row>
+
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="供应商:" prop="supplier">
+                        <el-select v-model="form.supplier" placeholder="请选择" clearable>
+                            <el-option v-for="dict in product_supplier" :key="dict.value" :label="dict.label" :value="dict.value" />
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="品牌:" prop="brand">
+                        <el-input v-model="form.brand" placeholder="请输入" />
+                    </el-form-item>
+                </el-col>
+
+            </el-row>
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="许可证有效期提醒:" prop="licenseExpiryReminder">
+                        <el-input v-model="form.licenseExpiryReminder" placeholder="请输入">
+                            <template #append>个月</template>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+
+                <el-col :span="12">
+                    <el-form-item label="产品所属标签:" prop="productLabel">
+                        <el-select v-model="form.productLabelList" multiple placeholder="请选择" style="width: 100%;" :disabled="true" @click="labelDialogVisible = true" class="custom-label-select" value-key="labelId">
+                            <el-option v-for="item in form.productLabelList" :key="item.labelId" :label="item.labelName" :value="item">
+                                <el-tag type="info" size="small">{{ item.labelName }}</el-tag>
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+
+            </el-row>
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="商品许可证有效期至:" prop="productLicenseExpiry">
+                        <el-date-picker v-model="form.productLicenseExpiry" type="date" placeholder="选择一天" value-format="YYYY-MM-DD" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="产品适用科室:" prop="applicableDepartment">
+                        <el-cascader v-model="form.applicableDepartmentList" :options="deptList" :props="{
+                                            multiple: true,checkStrictly: true, // 允许任意层级选择emitPath: false,     // 只返回选中节点的 value 
+                                            value: 'deptId',label: 'deptName',children: 'children'
+                                           }" placeholder="请选择" clearable style="width: 100%" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+
+                <el-col :span="12">
+                    <el-form-item label="保质期:" prop="shelfLife">
+                        <el-input v-model="form.shelfLife" placeholder="请输入">
+                            <template #append>个月</template>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+
+            <el-divider content-position="left">入货信息:</el-divider>
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="入货价格:" prop="purchasePrice" required>
+                        <el-input v-model="form.purchasePrice" placeholder="请输入">
+                            <template #append>元</template>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+
+                <el-col :span="12">
+                    <el-form-item label="销售价格:" prop="sellPrice" required>
+                        <el-input v-model="form.sellPrice" placeholder="请输入">
+                            <template #append>元/{{getDictLabel(product_package_unit ,form.suppliesUnit )|| '--' }}</template>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="耗材单位:" prop="suppliesUnit" required>
+                        <el-select v-model="form.suppliesUnit" placeholder="请选择" clearable>
+                            <el-option v-for="dict in product_package_unit" :key="dict.value" :label="dict.label" :value="dict.value" />
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="耗材规格:" prop="suppliesSpec" required>
+                        <div class="spec-input-group">
+                            <el-input v-model="form.suppliesSpec" placeholder="请输入" style="width: 320px;" :maxlength="10" />
+                            <el-select v-model="form.suppliesSpecUnit" class="spec-unit-select">
+                                <el-option v-for="dict in product_spec_unit" :key="dict.value" :label="dict.label" :value="dict.value" />
+                            </el-select>
+                            <span class="spec-unit-text">/{{getDictLabel(product_package_unit ,form.suppliesUnit )|| '--' }}</span>
+                        </div>
+                    </el-form-item>
+
+                </el-col>
+            </el-row>
+            <div class="dialog-footer" style="text-align:center;margin-top:32px;">
+                <el-button type="primary" @click="submitForm">保存</el-button>
+                <el-button type="primary" @click="submitFormAndPutaway">保存并上架</el-button>
+            </div>
+        </el-form>
+        <LabelDialog v-model="labelDialogVisible" :initial-selected-labels="form.productLabelList || []" @confirm="onLabelConfirm" />
+    </div>
+</template>
+
+<script setup lang="ts">
+    import { ref, reactive, onMounted, getCurrentInstance, type ComponentInternalInstance } from 'vue';
+    import { useRouter, useRoute } from 'vue-router';
+    import { addSuppliesManage, updateSuppliesManage, getSuppliesManage } from '@/api/warehouse/suppliesManage/index';
+    import { SuppliesManageForm } from '@/api/warehouse/suppliesManage/types';
+    import { listSuppliesCategory } from '@/api/warehouse/suppliesCategory/index';
+    import { listDept } from '@/api/system/dept';
+    import { toRefs } from 'vue';
+    import LabelDialog from '@/views/warehouse/nutriProduct/labelDialog.vue';
+
+    const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+    const { product_qualification, product_package_unit, product_supplier, put_flag, product_manufacturer, product_spec_unit } = toRefs < any > (proxy ?.useDict('product_qualification', 'product_package_unit', 'product_supplier', 'put_flag', 'product_manufacturer', 'product_spec_unit'));
+
+    const loading = ref(true);
+    const router = useRouter();
+    const route = useRoute();
+    const buttonLoading = ref(false);
+    const SuppliesManageFormRef = ref();
+    const labelDialogVisible = ref(false);
+
+
+    // 选项数据
+    const categoryOptions = ref < any[] > ([]);
+    const deptList = ref < any[] > ([]);
+    const unit_options = ref < any[] > ([{ label: '个', value: '1' }]); // TODO: 替换为实际数据
+
+
+    const rules = {
+        suppliesName: [{ required: true, message: '耗材名称不能为空', trigger: 'blur' }],
+        hospitalSystemCode: [{ required: true, message: "院方系统编码不能为空", trigger: "blur" }],
+        shelfLifeReminder: [{ required: true, message: "保质期临期提醒不能为空", trigger: "blur" }],
+        productQualification: [{ required: true, message: "商品资质不能为空", trigger: "blur" }],
+        suppliesCode: [{ required: true, message: '商品编码不能为空', trigger: 'blur' }],
+        shelfLife: [{ required: true, message: '保质期不能为空', trigger: 'blur' }],
+        suppliesCategoryList: [{ required: true, message: '所属分类不能为空', trigger: 'change' }],
+        purchasePrice: [{ required: true, message: '入货价格不能为空', trigger: 'blur' }],
+        suppliesUnit: [{ required: true, message: '耗材单位不能为空', trigger: 'change' }],
+        suppliesSpec: [{ required: true, message: '耗材规格不能为空', trigger: 'blur' }],
+        sellPrice: [{ required: true, message: '销售价格不能为空', trigger: 'blur' }]
+    };
+
+    const form = reactive < SuppliesManageForm > ({
+        id: undefined,
+        suppliesName: undefined,
+        hospitalSystemCode: undefined,
+        suppliesCode: undefined,
+        manufacturer: undefined,
+        supplier: undefined,
+        licenseExpiryReminder: undefined,
+        shelfLife: undefined,
+        productQualification: undefined,
+        approvalNumber: undefined,
+        suppliesCategoryList: [],
+        shelfLifeReminder: undefined,
+        brand: undefined,
+        productLabel: undefined,
+        productLabelList: [],
+        applicableDepartment: undefined,
+        applicableDepartmentList: [],
+        purchasePrice: undefined,
+        suppliesUnit: '2',
+        sellPrice: undefined,
+        suppliesSpec: undefined,
+        suppliesSpecUnit: '1',
+        putFlag: undefined
+    });
+
+    const getCategoryName = (categoryIds) => {
+        if (!categoryIds) return '--';
+
+        // 处理多个分类ID的情况
+        const ids = categoryIds.toString().split(',');
+        const categoryNames = ids.map(id => {
+            const findCategory = (categories, targetId) => {
+                for (const category of categories) {
+                    if (category.value.toString() === targetId.toString()) {
+                        return category.label;
+                    }
+                    if (category.children) {
+                        const found = findCategory(category.children, targetId);
+                        if (found) return found;
+                    }
+                }
+                return null;
+            };
+            return findCategory(categoryOptions.value, id);
+        }).filter(name => name !== null);
+
+        return categoryNames.length > 0 ? categoryNames.join('/') : '--';
+    };
+    const getDeptList = async () => {
+        loading.value = true;
+        try {
+            const res = await listDept({
+                pageNum: 1,
+                pageSize: 999
+            });
+            if (!res.data) {
+                console.warn("部门数据为空");
+                deptList.value = [];
+                return;
+            }
+
+            // 处理树形数据
+            const processedData = proxy ?.handleTree(res.data, 'deptId');
+            if (!processedData) {
+                console.warn("树形数据处理失败");
+                deptList.value = [];
+                return;
+            }
+
+            deptList.value = processedData;
+
+        } catch (error) {
+            console.error('获取部门列表失败:', error);
+            deptList.value = [];
+        } finally {
+            loading.value = false;
+        }
+    };
+
+
+    // 构建分类树
+    function buildCategoryTree(flatList: any[]) {
+        const idMap: Record < string, any > = {};
+        const tree = [];
+
+        flatList.forEach(item => {
+            idMap[item.categoryId] = {
+                label: item.categoryName,
+                value: item.categoryId,
+                children: []
+            };
+        });
+
+        flatList.forEach(item => {
+            if (item.parentId && item.parentId !== 0 && idMap[item.parentId]) {
+                idMap[item.parentId].children.push(idMap[item.categoryId]);
+            } else if (item.parentId === 0) {
+                tree.push(idMap[item.categoryId]);
+            }
+        });
+
+        // 去除没有children的children字段
+        function clean(node: any) {
+            if (node.children && node.children.length === 0) {
+                delete node.children;
+            } else if (node.children) {
+                node.children.forEach(clean);
+            }
+        }
+        tree.forEach(clean);
+        return tree;
+    }
+    // 标签确认回调
+    function onLabelConfirm(selectedLabels: Array < { labelId: string | number;labelName: string } > ) {
+        form.productLabelList = selectedLabels;
+    }
+
+    // 字典label工具
+    function getDictLabel(dictList: any[], value: string) {
+        if (!dictList || !Array.isArray(dictList)) return value || '--';
+        const found = dictList.find(item => item.value === value);
+        return found ? found.label : value || '--';
+    }
+
+    // 判断是新增还是编辑
+    const id = route.params.id;
+    if (id) {
+        // 编辑,获取详情
+        getSuppliesManage(id.toString()).then(res => {
+            Object.assign(form, res.data);
+            // 如果有分类ID,需要设置级联选择器的值
+            if (res.data.suppliesCategoryId) {
+                // 这里需要根据后端返回的数据结构调整
+                form.suppliesCategoryList = [res.data.suppliesCategoryId];
+            }
+        });
+    }
+
+    // 初始化数据
+    onMounted(async () => {
+        getDeptList(); // 初始化时加载部门数据
+        const res = await listSuppliesCategory();
+        categoryOptions.value = buildCategoryTree(res.rows || []);
+    });
+
+    // 添加分类选择处理函数
+    const handleCategoryChange = (value: any[]) => {
+        if (value && value.length > 0) {
+            form.suppliesCategoryId = value[value.length - 1];
+        } else {
+            form.suppliesCategoryId = undefined;
+        }
+    };
+
+    // 修改提交函数
+    function submitForm() {
+        SuppliesManageFormRef.value ?.validate(async (valid: boolean) => {
+            if (valid) {
+                buttonLoading.value = true;
+                try {
+                    // 确保设置了 suppliesCategoryId
+                    if (form.suppliesCategoryList && form.suppliesCategoryList.length > 0) {
+                        form.suppliesCategoryId = form.suppliesCategoryList[form.suppliesCategoryList.length - 1];
+                    }
+
+                    if (form.id) {
+                        await updateSuppliesManage(form);
+                    } else {
+                        await addSuppliesManage(form);
+                    }
+                    proxy ?.$modal.msgSuccess('操作成功');
+                    goToList();
+                } catch (error) {
+                    console.error('提交失败:', error);
+                    proxy ?.$modal.msgError('操作失败');
+                } finally {
+                    buttonLoading.value = false;
+                }
+            }
+        });
+    }
+
+    /** 保存并上架按钮操作 */
+    const submitFormAndPutaway = () => {
+        SuppliesManageFormRef.value ?.validate(async (valid: boolean) => {
+            if (valid) {
+                buttonLoading.value = true;
+                try {
+                    form.putFlag = '1';
+                    if (form.id) {
+                        await updateSuppliesManage(form);
+                    } else {
+                        await addSuppliesManage(form);
+                    }
+                    proxy ?.$modal.msgSuccess('操作成功');
+                    goToList();
+                } catch (error) {
+                    console.error('提交失败:', error);
+                    proxy ?.$modal.msgError('操作失败');
+                } finally {
+                    buttonLoading.value = false;
+                }
+            }
+        });
+    };
+
+    // 返回按钮
+    const goBack = () => {
+        router.back();
+    };
+
+    // 统一的列表页跳转函数
+    const goToList = () => {
+        router.push('/warehouse/suppliesManage');
+    };
+</script>
+
+<style scoped>
+    .add-or-edit-supplies-manage {
+        padding: 20px;
+        background-color: #fff;
+    }
+
+    .el-form {
+        max-width: 1200px;
+        margin: 0 auto;
+    }
+
+    .el-row {
+        margin-bottom: 20px;
+    }
+
+    :deep(.el-form-item__label) {
+        font-weight: 500;
+    }
+
+    :deep(.el-input-group__append) {
+        padding: 0 15px;
+    }
+
+    .custom-label-select :deep(.el-select__tags) {
+        max-width: calc(100% - 30px);
+    }
+
+    .spec-input-group {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+    }
+
+    .spec-unit-select {
+        width: 80px;
+    }
+
+    .spec-unit-text {
+        color: #606266;
+        font-size: 14px;
+        white-space: nowrap;
+    }
+</style>

+ 175 - 0
src/views/warehouse/suppliesManage/detailForm.vue

@@ -0,0 +1,175 @@
+<template>
+    <div class="supplies-detail">
+        <el-card shadow="always" class="back-card">
+            <el-button type="primary" plain size="large" @click="goBack">返回</el-button>
+            <span style="margin-left: 20px;">查看耗材</span>
+        </el-card>
+
+        <el-card shadow="never" class="detail-card">
+            <el-row :gutter="40" style="margin-top: 30px;">
+                <el-col :span="12">
+                    <div><b><span style="color:red;margin-right: 3px">*</span>耗材名称:</b>{{ formData.suppliesName || '--' }}</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>商品编码:</b>{{ formData.suppliesCode || '--' }}</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>院方系统编码:</b>{{ formData.hospitalSystemCode || '--' }}</div>
+                    <div><b>生产厂商:</b>{{ getDictLabel(product_manufacturer, formData.manufacturer) || '--' }}</div>
+                    <div><b>供应商:</b>{{ getDictLabel(product_supplier, formData.supplier) || '--' }}</div>
+                    <div class="long-label"><b>许可证有效期提醒:</b>{{ formData.licenseExpiryReminder ? formData.licenseExpiryReminder + '个月' : '--' }}</div>
+                    <div class="long-label"><b>商品许可证有效期至:</b>{{ formData.productLicenseExpiry ? formData.productLicenseExpiry.slice(0, 10) : '--' }}</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>保质期:</b>{{ formData.shelfLife ? formData.shelfLife + '个月' : '--' }}</div>
+
+                </el-col>
+                <el-col :span="12">
+                    <div><b><span style="color:red;margin-right: 3px">*</span>商品资质:</b>{{ getDictLabel(product_qualification, formData.productQualification) || '--' }}</div>
+                    <div><b>批准文号:</b>{{ formData.approvalNumber || '--' }}</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>所属分类:</b>{{ formData.suppliesCategoryId || '--' }}</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>保质期临期提醒:</b>{{ formData.shelfLifeReminder ? formData.shelfLifeReminder + '个月' : '--' }}</div>
+                    <div><b>品牌:</b>{{ formData.brand || '--' }}</div>
+                    <div><b>产品所属标签:</b>{{ formData.productLabel || '--' }}</div>
+                    <div><b>产品适用科室:</b>{{ formData.applicableDepartment || '--' }}</div>
+                </el-col>
+            </el-row>
+
+            <el-divider content-position="left">入货信息:</el-divider>
+            <el-row :gutter="40" style="margin-top: 50px">
+                <el-col :span="12">
+                    <div><b><span style="color:red;margin-right: 3px">*</span>入货价格:</b>{{ formData.purchasePrice || '--' }} 元</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>耗材单位:</b>{{ getDictLabel(product_package_unit, formData.suppliesUnit) || '--' }}</div>
+                </el-col>
+                <el-col :span="12">
+                    <div><b><span style="color:red;margin-right: 3px">*</span>销售价格:</b>{{ formData.sellPrice || '--' }} 元/{{ getDictLabel(product_package_unit, formData.suppliesUnit) || '--' }}</div>
+                    <div><b><span style="color:red;margin-right: 3px">*</span>耗材规格:</b>{{ formData.suppliesSpec || '--' }}{{ getDictLabel(product_spec_unit, formData.suppliesSpecUnit) || '--' }}/{{ getDictLabel(product_package_unit, formData.suppliesUnit) || '--' }}</div>
+                </el-col>
+            </el-row>
+        </el-card>
+    </div>
+</template>
+
+<script setup lang="ts">
+    import { ref, onMounted } from 'vue';
+    import { useRouter, useRoute } from 'vue-router';
+    import { getSuppliesManage } from '@/api/warehouse/suppliesManage';
+    import { listSuppliesCategory } from '@/api/warehouse/suppliesCategory';
+    import { getCurrentInstance } from 'vue';
+
+    const router = useRouter();
+    const route = useRoute();
+    const { proxy } = getCurrentInstance();
+    if (!proxy) {
+        throw new Error('getCurrentInstance() returned null');
+    }
+
+    // 字典数据
+    const product_qualification = ref([]);
+    const product_package_unit = ref([]);
+    const product_supplier = ref([]);
+    const product_manufacturer = ref([]);
+    const product_spec_unit = ref([]);
+
+    // 加载字典数据
+    const loadDict = async () => {
+        const dictData = await proxy.useDict(
+            'product_qualification',
+            'product_package_unit',
+            'product_supplier',
+            'product_manufacturer',
+            'product_spec_unit'
+        );
+        product_qualification.value = dictData.product_qualification;
+        product_package_unit.value = dictData.product_package_unit;
+        product_supplier.value = dictData.product_supplier;
+        product_manufacturer.value = dictData.product_manufacturer;
+        product_spec_unit.value = dictData.product_spec_unit;
+    };
+
+    const formData = ref < any > ({});
+
+    // 字典label工具
+    function getDictLabel(dictList: any[], value: string) {
+        if (!dictList || !Array.isArray(dictList)) return value || '--';
+        const found = dictList.find((item) => item.value === value);
+        return found ? found.label : value || '--';
+    }
+
+    // 返回按钮
+    const goBack = () => {
+        router.back();
+    };
+
+    // 获取详情数据
+    const getDetail = async (id: string) => {
+        try {
+            const res = await getSuppliesManage(id);
+            formData.value = res.data;
+        } catch (error) {
+
+        }
+    };
+
+    onMounted(async () => {
+        try {
+            const id = route.params.id;
+            if (id) {
+                // 先加载字典数据
+                await loadDict();
+                // 再加载分类和详情数据
+                await Promise.all([
+                    getDetail(id.toString())
+                ]);
+            }
+        } catch (error) {
+            console.error('页面加载失败:', error);
+            proxy.$modal.msgError('页面加载失败');
+        }
+    });
+</script>
+
+<style scoped>
+    .supplies-detail {
+        padding: 20px;
+    }
+
+    .back-card {
+        margin-bottom: 20px;
+    }
+
+    .detail-card {
+        background-color: #fff;
+    }
+
+    .el-row {
+        margin-left: 30px;
+        margin-bottom: 20px;
+    }
+
+    .el-col {
+        margin-bottom: 20px;
+    }
+
+    .el-col div {
+        line-height: 40px;
+        display: flex;
+        align-items: center;
+        gap: 24px;
+        margin-bottom: 8px;
+    }
+
+    .el-col div b {
+        display: inline-block;
+        min-width: 140px;
+        color: #606266;
+        white-space: nowrap;
+        text-align: right;
+        padding-right: 12px;
+        flex-shrink: 0;
+    }
+
+    .long-label b {
+        min-width: 160px;
+    }
+
+    .long-label {
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+    }
+</style>

+ 315 - 0
src/views/warehouse/suppliesManage/index.vue

@@ -0,0 +1,315 @@
+<template>
+    <div class="p-2">
+        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+            <div v-show="showSearch" class="mb-[10px]">
+                <el-card shadow="hover">
+                    <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="150px">
+                        <el-form-item label="耗材分类" prop="suppliesCategoryId">
+                            <el-cascader v-model="queryParams.suppliesCategoryList" :options="categoryOptions" :props="{
+                                    checkStrictly: true,
+                                    emitPath: true,
+                                    value: 'value',
+                                    label: 'label',
+                                    children: 'children'
+                                }" placeholder="请选择" clearable filterable style="width: 200px" />
+                        </el-form-item>
+                        <el-form-item>
+                            <el-input v-model="queryParams.suppliesName" placeholder="请输入名称/编码" clearable @keyup.enter="handleQuery" style="margin-left: 30px" />
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+                            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+                        </el-form-item>
+                    </el-form>
+                </el-card>
+            </div>
+        </transition>
+
+        <el-card shadow="never">
+            <template #header>
+                <el-row :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                        <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['warehouse:suppliesManage:add']">新增耗材</el-button>
+                    </el-col>
+                    <!-- <el-col :span="1.5">
+                        <el-button type="warning" plain @click="handleImport" v-hasPermi="['warehouse:suppliesManage:import']">导入</el-button>
+                    </el-col> -->
+                    <el-col :span="1.5">
+                        <el-button type="warning" plain @click="handleExport" v-hasPermi="['warehouse:suppliesManage:export']">导出</el-button>
+                    </el-col>
+                    <el-col :span="1.5">
+                        <el-button type="warning" plain @click="downLoadTemplate" v-hasPermi="['warehouse:suppliesManage:export']">下载模板</el-button>
+                    </el-col>
+                    <el-col :span="1.5">
+                        <el-button type="warning" plain @click="openBatchSetDialog">批量设置</el-button>
+                    </el-col>
+                    <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+                </el-row>
+            </template>
+
+            <el-table v-loading="loading" border :data="manageList" @selection-change="handleSelectionChange">
+                <el-table-column type="selection" width="55" align="center" />
+                <el-table-column label="耗材名称" align="center" prop="suppliesName" />
+                <el-table-column label="商品编码" align="center" prop="suppliesCode" />
+                <el-table-column label="耗材分类" align="center">
+                    <template #default="{ row }">
+                        {{ getCategoryName(row.suppliesCategoryId) }}
+                    </template>
+                </el-table-column>
+                <el-table-column label="规格" align="center">
+                    <template #default="scope">
+                        {{ scope.row.suppliesSpec}}{{ product_spec_unit.find(item => item.value === scope.row.suppliesSpecUnit)?.label || '--' }}/{{ product_package_unit.find(item => item.value === scope.row.suppliesUnit)?.label || '--' }}
+                    </template>
+                </el-table-column>
+                <el-table-column label="许可证临期提醒" align="center" prop="licenseExpiryReminder" width="180">
+                    <template #default="scope">
+                        <span v-if="scope.row.licenseExpiryReminder > 0">{{ scope.row.licenseExpiryReminder + '个月' }}</span>
+                        <span v-else>{{ '--' }}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="保质期临期提醒" align="center" prop="shelfLifeReminder" width="180">
+                    <template #default="scope">
+                        <span>{{ scope.row.shelfLifeReminder }}个月</span>
+                    </template>
+                </el-table-column>
+                <el-table-column label="上架状态" align="center" prop="putFlag" width="100">
+                    <template #default="{ row }">
+                        {{ put_flag.find(item => item.value === row.putFlag)?.label || row.putFlag }}
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
+                    <template #default="scope">
+                        <el-button v-if="scope.row.putFlag === '1'" link type="danger" @click="handlePutFlag(scope.row, '0')">下架</el-button>
+                        <el-button v-else link type="success" @click="handlePutFlag(scope.row, '1')">上架</el-button>
+                        <el-button link type="primary" @click="handleDetail(scope.row)">详情</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+
+            <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+            <el-dialog title="批量设置" v-model="batchSetDialogVisible" width="400px" append-to-body>
+                <el-form :model="batchSetForm" label-width="120px" :rules="rules">
+                    <el-form-item label="保质期临期提醒" prop="shelfLifeReminder">
+                        <el-input v-model="batchSetForm.shelfLifeReminder" min="1" placeholder="请输入" style="width: 200px;">
+                            <template #append>个月</template>
+                        </el-input>
+                    </el-form-item>
+                    <el-form-item label="许可证临期提醒" prop="licenseExpiryReminder">
+                        <el-input v-model="batchSetForm.licenseExpiryReminder" min="1" placeholder="请输入" style="width: 200px;">
+                            <template #append>个月</template>
+                        </el-input>
+                    </el-form-item>
+                </el-form>
+                <template #footer>
+                    <el-button type="primary" @click="handleBatchSetSubmit">提交</el-button>
+                    <el-button @click="batchSetDialogVisible = false">取消</el-button>
+                </template>
+            </el-dialog>
+        </el-card>
+    </div>
+</template>
+
+<script setup name="SuppliesManage" lang="ts">
+    import { ref, reactive, onMounted, getCurrentInstance, type ComponentInternalInstance } from 'vue';
+    import { listSuppliesManage, delSuppliesManage, batchUpdateSuppliesManage, updateSuppliesManage } from '@/api/warehouse/suppliesManage';
+    import { SuppliesManageVO, SuppliesManageQuery } from '@/api/warehouse/suppliesManage/types';
+    import { listSuppliesCategory } from '@/api/warehouse/suppliesCategory';
+    import { useRouter } from 'vue-router';
+    import type { FormInstance } from 'element-plus';
+
+    const router = useRouter();
+    const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+    const { product_package_unit, put_flag, product_spec_unit } = toRefs < any > (proxy ?.useDict('product_package_unit', 'put_flag', 'product_spec_unit'));
+
+    const manageList = ref < SuppliesManageVO[] > ([]);
+    const loading = ref(true);
+    const showSearch = ref(true);
+    const ids = ref < Array < string | number >> ([]);
+    const single = ref(true);
+    const multiple = ref(true);
+    const total = ref(0);
+    const batchSetDialogVisible = ref(false);
+
+    const rules = {
+        shelfLifeReminder: [{ required: true, message: "保质期临期提醒不能为空", trigger: "blur" }],
+        licenseExpiryReminder: [{ required: true, message: "许可证临期提醒不能为空", trigger: "blur" }],
+
+    };
+
+
+    // 分类选项
+    const categoryOptions = ref < any[] > ([]);
+
+    const queryFormRef = ref < FormInstance > ();
+
+    const queryParams = reactive < SuppliesManageQuery > ({
+        pageNum: 1,
+        pageSize: 10,
+        suppliesName: '',
+        suppliesCategoryId: '',
+        suppliesCategoryList: [],
+    });
+    const batchSetForm = reactive({
+        shelfLifeReminder: '',
+        licenseExpiryReminder: ''
+    });
+    /** 查询耗材管理列表 */
+    const getList = async () => {
+        loading.value = true;
+        try {
+            const res = await listSuppliesManage(queryParams);
+            manageList.value = res.rows;
+            total.value = res.total;
+        } finally {
+            loading.value = false;
+        }
+    };
+
+    /** 搜索按钮操作 */
+    const handleQuery = () => {
+        // 取最后一级分类ID传给后端
+        if (queryParams.suppliesCategoryList && queryParams.suppliesCategoryList.length) {
+            queryParams.suppliesCategoryId = queryParams.suppliesCategoryList.slice(-1)[0];
+        } else {
+            queryParams.suppliesCategoryId = undefined;
+        }
+        queryParams.pageNum = 1;
+        getList();
+    };
+
+    onMounted(async () => {
+        getList();
+        const res = await listSuppliesCategory();
+        categoryOptions.value = buildCategoryTree(res.rows || []);
+    });
+
+    function openBatchSetDialog() {
+        if (!ids.value.length) {
+            proxy ?.$modal.msgWarning('请先选择要批量设置的产品');
+            return;
+        }
+        batchSetForm.shelfLifeReminder = '';
+        batchSetForm.licenseExpiryReminder = '';
+        batchSetDialogVisible.value = true;
+    };
+    async function handleBatchSetSubmit() {
+        const params = {
+            ids: ids.value,
+            shelfLifeReminder: batchSetForm.shelfLifeReminder,
+            licenseExpiryReminder: batchSetForm.licenseExpiryReminder
+        };
+
+        try {
+            await batchUpdateSuppliesManage(params);
+            proxy ?.$modal.msgSuccess('批量设置成功');
+            batchSetDialogVisible.value = false;
+            getList();
+        } catch (e) {
+            proxy ?.$modal.msgError('批量设置失败');
+        }
+    }
+    /** 重置按钮操作 */
+    const resetQuery = () => {
+        queryFormRef.value ?.resetFields();
+        queryParams.suppliesCategoryList = [];
+        queryParams.suppliesName = undefined;
+        handleQuery();
+    };
+
+    /** 新增按钮操作 */
+    const handleAdd = () => {
+        router.push('/warehouse/suppliesAddOrEdit');
+    };
+
+    /** 导入按钮操作 */
+    const handleImport = () => {
+        // TODO: 实现导入功能
+    };
+
+    /** 导出按钮操作 */
+    const handleExport = () => {
+        proxy ?.download('warehouse/suppliesManage/export', {
+            ...queryParams
+        }, `suppliesManage_${new Date().getTime()}.xlsx`);
+    };
+
+    /** 下载模板按钮操作 */
+    const downLoadTemplate = () => {
+        proxy ?.getDownload('warehouse/suppliesManage/downLoadTemplate', {}, `耗材模版.xlsx`)
+    }
+
+    /** 获取分类名称 */
+    const getCategoryName = (categoryIds) => {
+        if (!categoryIds) return '--';
+
+        // 处理多个分类ID的情况
+        const ids = categoryIds.toString().split(',');
+        const categoryNames = ids.map(id => {
+            const findCategory = (categories, targetId) => {
+                for (const category of categories) {
+                    if (category.value.toString() === targetId.toString()) {
+                        return category.label;
+                    }
+                    if (category.children) {
+                        const found = findCategory(category.children, targetId);
+                        if (found) return found;
+                    }
+                }
+                return null;
+            };
+            return findCategory(categoryOptions.value, id);
+        }).filter(name => name !== null);
+
+        return categoryNames.length > 0 ? categoryNames.join('/') : '--';
+    };
+
+    function buildCategoryTree(flatList: any[]) {
+        const idMap: Record < string, any > = {};
+        const tree = [];
+        flatList.forEach((item) => {
+            idMap[item.categoryId] = {
+                label: item.categoryName,
+                value: item.categoryId,
+                children: []
+            };
+        });
+        flatList.forEach((item) => {
+            if (item.parentId && item.parentId !== 0 && idMap[item.parentId]) {
+                idMap[item.parentId].children.push(idMap[item.categoryId]);
+            } else if (item.parentId === 0) {
+                tree.push(idMap[item.categoryId]);
+            }
+        });
+        // 去除没有children的children字段
+        function clean(node: any) {
+            if (node.children && node.children.length === 0) {
+                delete node.children;
+            } else if (node.children) {
+                node.children.forEach(clean);
+            }
+        }
+        tree.forEach(clean);
+        return tree;
+    }
+
+    // 上下架切换
+    const handlePutFlag = async (row: SuppliesManageVO, flag: string) => {
+        await proxy ?.$modal.confirm(`是否确认${flag === '1' ? '上架' : '下架'}该耗材?`);
+        const updateData = { ...row, putFlag: flag };
+        await updateSuppliesManage(updateData);
+        proxy ?.$modal.msgSuccess(`${flag === '1' ? '上架' : '下架'}成功`);
+        await getList();
+    };
+
+    /** 查看详情 */
+    const handleDetail = (row: SuppliesManageVO) => {
+        router.push(`/warehouse/suppliesManageDetail/${row.id}`);
+    };
+
+    /** 多选框选中数据 */
+    const handleSelectionChange = (selection: SuppliesManageVO[]) => {
+        ids.value = selection.map((item) => item.id);
+        single.value = selection.length !== 1;
+        multiple.value = !selection.length;
+    };
+</script>

+ 23 - 1
src/views/workbench/treatmentUser/index.vue

@@ -133,7 +133,7 @@
                         <el-col :span="12">
                             <el-form-item label="病区" prop="inpatientWard">
                                 <el-select v-model="form.inpatientWard" placeholder="请选择">
-
+                                    <el-option v-for="item in inpatientWardList" :key="item.value" :label="item.label" :value="item.value" />
                                 </el-select>
                             </el-form-item>
                         </el-col>
@@ -242,6 +242,7 @@
 <script setup name="TreatmentUser" lang="ts">
     import { listTreatmentUser, getTreatmentUser, delTreatmentUser, addTreatmentUser, updateTreatmentUser } from '@/api/workbench/treatmentUser';
     import { listDept } from '@/api/system/dept';
+    import { listWard } from '@/api/system/ward';
     import { TreatmentUserVo, TreatmentUserForm, TreatmentUserQuery } from '@/api/workbench/treatmentUser/types';
     import { log } from 'console';
     import { get } from 'http';
@@ -256,6 +257,26 @@
     const multiple = ref(true);
     const total = ref(0);
     const treeData = ref([]); // 定义 treeData
+    const inpatientWardList = ref([]);
+
+    // 获取病区列表数据
+    const getWardList = async () => {
+        try {
+            const res = await listWard({
+                pageNum: 1,
+                pageSize: 999
+            });
+            if (res.rows && Array.isArray(res.rows)) {
+                inpatientWardList.value = res.rows.map(item => ({
+                    value: item.wardId,
+                    label: item.wardName
+                }));
+            }
+        } catch (error) {
+            console.error('获取病区列表失败:', error);
+            inpatientWardList.value = [];
+        }
+    };
 
     const waitingCount = ref(0);
     const treatingCount = ref(0);
@@ -604,6 +625,7 @@
     onMounted(() => {
         getList();
         getDeptList(); // 初始化时加载部门数据
+        getWardList(); // 初始化时加载病区数据
     });
 
     const showDetail = ref(false);