Explorar o código

营养产品相关

HuRongxin hai 1 mes
pai
achega
973c003764

+ 8 - 0
src/api/warehouse/productNutrition/index.ts

@@ -51,6 +51,14 @@ export const updateNutrition = (data: NutritionForm) => {
   });
 };
 
+export function batchUpdateNutrition(data) {
+  return request({
+    url: '/warehouse/nutrition/batchUpdate',
+    method: 'post',
+    data
+  });
+}
+
 /**
  * 删除营养产品信息
  * @param id

+ 25 - 1
src/api/warehouse/productNutrition/types.ts

@@ -4,6 +4,8 @@ export interface NutritionVO {
      */
     id: string | number;
 
+    ids: string | number[];
+
     /**
      * 产品名称
      */
@@ -24,7 +26,7 @@ export interface NutritionVO {
      */
     productCategory: string;
 
-    productCategoryList?: string[];
+    productCategoryList: string[];
 
     /**
      * 生产厂商
@@ -81,6 +83,12 @@ export interface NutritionVO {
      */
     applicableDepartment: string;
 
+    applicableDepartmentList: string[];
+
+     productLabelList: string[];
+
+     contraindicationLabelList: string[];
+
     /**
      * 禁忌症所属标签
      */
@@ -564,6 +572,8 @@ export interface NutritionForm extends BaseEntity {
      */
     id?: string | number;
 
+    ids?: number[];
+
     /**
      * 产品名称
      */
@@ -641,11 +651,19 @@ export interface NutritionForm extends BaseEntity {
      */
     applicableDepartment?: string;
 
+    applicableDepartmentList?: string[];
+
+    productLabelList?: string[];
+
+    contraindicationLabelList?: string[];
+
     /**
      * 禁忌症所属标签
      */
     contraindicationLabel?: string;
 
+    contraindicationLabelList?: string[];
+
     /**
      * 保质期临期提醒
      */
@@ -1207,6 +1225,12 @@ export interface NutritionQuery extends PageQuery {
      */
     applicableDepartment?: string;
 
+    applicableDepartmentList?: string[];
+
+     productLabelList?: string[];
+
+     contraindicationLabelList?: string[];
+
     /**
      * 禁忌症所属标签
      */

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 381 - 180
src/views/warehouse/nutriProduct/index.vue


+ 337 - 0
src/views/warehouse/nutriProduct/labelDialog.vue

@@ -0,0 +1,337 @@
+<template>
+    <el-dialog :title="'添加疾病标签'" v-model="visible" width="1300px" append-to-body class="disease-label-dialog" :close-on-click-modal="false" :destroy-on-close="true" top="40px">
+        <div class="dialog-header-tabs">
+            <el-tabs v-model="activeTab" @tab-click="onTabChange" class="custom-tabs">
+                <el-tab-pane label="常见营养诊断" name="1" />
+                <el-tab-pane label="ICD诊断" name="2" />
+                <el-tab-pane label="营养诊断" name="3" />
+            </el-tabs>
+        </div>
+        <div class="dialog-body-flex">
+            <div class="left-panel">
+                <div class="search-bar">
+                    <el-input v-model="search" placeholder="疾病名称/疾病编码" class="search-input" clearable @keyup.enter="fetchData" />
+                    <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-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" />
+                    <el-table-column prop="labelCode" label="疾病/部位编码" min-width="120" align="center" />
+                </el-table>
+                <div v-if="!tableData.length" class="no-data">暂无数据</div>
+                <el-pagination v-if="total > 0" class="custom-pagination" background layout="total, sizes, prev, pager, next" :total="total" :page-size="pageSize" :current-page="pageNum" :page-sizes="[10, 20, 50]" @size-change="handleSizeChange" @current-change="handlePageChange" />
+            </div>
+            <div class="right-panel">
+                <div class="right-title">已选疾病标签</div>
+                <el-table :data="selectedLabels" border class="selected-table" style="width: 100%; min-height: 360px">
+                    <el-table-column prop="labelName" label="疾病/部位名称" min-width="120" align="center" />
+                    <el-table-column prop="categoryName" label="所属分类" min-width="100" align="center" />
+                    <el-table-column prop="labelCode" label="疾病/部位编码" min-width="120" align="center" />
+                    <el-table-column label="操作" width="60" align="center">
+                        <template #default="{ row }">
+                            <el-button link type="danger" size="small" @click="removeLabel(row)">删除</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <div v-if="!selectedLabels.length" class="no-data">暂无数据</div>
+            </div>
+        </div>
+        <div class="dialog-footer-btns">
+            <el-button type="primary" class="confirm-btn" @click="handleConfirm">确定</el-button>
+            <el-button class="cancel-btn" @click="handleCancel">取消</el-button>
+        </div>
+        <!-- 新增疾病标签弹窗 -->
+        <el-dialog :title="'新增疾病标签'" v-model="addDialogVisible" width="500px" append-to-body @closed="resetAddForm">
+            <el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="150px">
+                <el-form-item label="疾病/部位名称" prop="labelName">
+                    <el-input v-model="addForm.labelName" placeholder="请输入" />
+                </el-form-item>
+                <el-form-item label="所属分类" prop="category">
+                    <el-select v-model="addForm.category" placeholder="请选择">
+                        <el-option label="常见营养诊断" value="1" />
+                        <el-option label="ICD诊断" value="2" />
+                        <el-option label="营养诊断" value="3" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="疾病/部位编码" prop="labelCode">
+                    <el-input v-model="addForm.labelCode" placeholder="请输入" />
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button type="primary" @click="submitAddForm">确 定</el-button>
+                    <el-button @click="addDialogVisible = false">取 消</el-button>
+                </div>
+            </template>
+        </el-dialog>
+    </el-dialog>
+</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;
+        });
+    }
+
+    function onTabChange() {
+        pageNum.value = 1;
+        fetchData();
+    }
+
+    function handleSelectionChange(val: any[]) {
+        selectedLabels.value = val;
+    }
+
+    function handleSizeChange(size: number) {
+        pageSize.value = size;
+        pageNum.value = 1;
+        fetchData();
+    }
+
+    function handlePageChange(page: number) {
+        pageNum.value = page;
+        fetchData();
+    }
+
+    function removeLabel(row: any) {
+        selectedLabels.value = selectedLabels.value.filter((l) => l.labelCode !== row.labelCode);
+    }
+
+    function handleConfirm() {
+        emit('confirm', selectedLabels.value);
+        visible.value = false;
+    }
+
+    function handleCancel() {
+        visible.value = false;
+    }
+
+    function rowClassName({ rowIndex }: { rowIndex: number }) {
+        return rowIndex % 2 === 1 ? 'table-row-stripe' : '';
+    }
+
+    // 初始化
+    fetchData();
+</script>
+
+<style scoped>
+    .disease-label-dialog {
+        --el-dialog-padding-primary: 0;
+    }
+
+    .dialog-header-tabs {
+        padding: 0 32px 0 24px;
+        border-bottom: 1px solid #f0f0f0;
+        background: #fafbfc;
+    }
+
+    .custom-tabs {
+        margin-bottom: 0;
+    }
+
+    .custom-tabs .el-tabs__nav {
+        border: none;
+    }
+
+    .custom-tabs .el-tabs__item {
+        font-size: 16px;
+        padding: 0 32px;
+        height: 48px;
+        line-height: 48px;
+        color: #333;
+        border-radius: 6px 6px 0 0;
+        margin-right: 8px;
+    }
+
+    .custom-tabs .el-tabs__item.is-active {
+        background: #fff;
+        color: #409eff;
+        border-bottom: 2px solid #409eff;
+        font-weight: 600;
+    }
+
+    .dialog-body-flex {
+        display: flex;
+        padding: 24px 32px 0 24px;
+        min-height: 400px;
+    }
+
+    .left-panel {
+        flex: 3;
+        margin-right: 16px;
+        background: #fff;
+        border: 1px solid #f0f0f0;
+        border-radius: 6px;
+        padding: 16px 16px 0 16px;
+        display: flex;
+        flex-direction: column;
+    }
+
+    .right-panel {
+        flex: 2;
+        background: #fff;
+        border: 1px solid #f0f0f0;
+        border-radius: 6px;
+        padding: 16px 16px 0 16px;
+        display: flex;
+        flex-direction: column;
+    }
+
+    .right-title {
+        font-size: 15px;
+        font-weight: 600;
+        margin-bottom: 8px;
+        color: #333;
+    }
+
+    .search-bar {
+        display: flex;
+        align-items: center;
+        margin-bottom: 12px;
+    }
+
+    .search-input {
+        width: 220px;
+        margin-right: 12px;
+    }
+
+    .search-btn {
+        margin-right: 8px;
+        background: #409eff;
+        color: #fff;
+        border-radius: 4px;
+        border: none;
+    }
+
+    .add-btn {
+        background: #f5f7fa;
+        color: #409eff;
+        border-radius: 4px;
+        border: 1px solid #dcdfe6;
+    }
+
+    .disease-table,
+    .selected-table {
+        margin-bottom: 0;
+        border-radius: 4px;
+        font-size: 14px;
+    }
+
+    .disease-table .el-table__header th,
+    .selected-table .el-table__header th {
+        background: #f8f9fa;
+        color: #666;
+        font-weight: 500;
+        border-bottom: 1px solid #ebeef5;
+    }
+
+    .disease-table .el-table__row.table-row-stripe {
+        background: #fafbfc;
+    }
+
+    .no-data {
+        text-align: center;
+        color: #bfbfbf;
+        font-size: 15px;
+        margin: 32px 0;
+    }
+
+    .custom-pagination {
+        margin: 12px 0 0 0;
+        text-align: right;
+    }
+
+    .dialog-footer-btns {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding: 24px 0 16px 0;
+        background: #fafbfc;
+        border-top: 1px solid #f0f0f0;
+    }
+
+    .confirm-btn {
+        min-width: 96px;
+        background: #409eff;
+        color: #fff;
+        border-radius: 4px;
+        margin-right: 16px;
+    }
+
+    .cancel-btn {
+        min-width: 96px;
+        background: #fff;
+        color: #606266;
+        border-radius: 4px;
+        border: 1px solid #dcdfe6;
+    }
+</style>

+ 1 - 1
src/views/warehouse/productCategory/index.vue

@@ -2,7 +2,7 @@
     <div class="p-2">
         <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
             <div v-show="showSearch">
-                <el-form ref="queryFormRef" :model="queryParams" :inline="true" class="bg-[#f8f8f9] p-[10px] mb-[10px]">
+                <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="150px" class="bg-[#f8f8f9] p-[10px] mb-[10px]">
                     <el-form-item label="分类名称" prop="categoryName">
                         <el-input v-model="queryParams.categoryName" placeholder="请输入" clearable style="width: 180px" @keyup.enter="handleQuery" />
                     </el-form-item>

+ 1 - 1
src/views/warehouse/suppliesCategory/index.vue

@@ -2,7 +2,7 @@
   <div class="p-2">
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true" class="bg-[#f8f8f9] p-[10px] mb-[10px]">
+        <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="150px" class="bg-[#f8f8f9] p-[10px] mb-[10px]">
           <el-form-item label="分类名称" prop="categoryName">
             <el-input v-model="queryParams.categoryName" placeholder="请输入" clearable style="width: 180px" @keyup.enter="handleQuery" />
           </el-form-item>

+ 36 - 33
src/views/workbench/treatmentUser/index.vue

@@ -3,7 +3,7 @@
         <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">
+                    <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="150px">
                         <el-form-item label="患者类型" prop="type">
                             <el-select v-model="queryParams.type" clearable>
                                 <el-option v-for="dict in treatment_user_type" :key="dict.value" :label="dict.label" :value="dict.value" />
@@ -209,7 +209,7 @@
         <el-dialog v-model="showDetail" :visible="showDetail" title="查看门诊患者信息" width="900px" append-to-body>
             <div style="padding: 20px 30px;">
                 <el-row :gutter="24">
-                    
+
                     <el-col :span="12">
                         <div><b>看诊类型:</b>{{ detailData.type === '0' ? '门诊' : '住院' }}</div>
                         <div><b>诊疗卡号:</b>{{ detailData.treatNum || '--' }}</div>
@@ -244,7 +244,7 @@
     import { listDept } from '@/api/system/dept';
     import { TreatmentUserVo, TreatmentUserForm, TreatmentUserQuery } from '@/api/workbench/treatmentUser/types';
     import { log } from 'console';
-import { get } from 'http';
+    import { get } from 'http';
     const { proxy } = getCurrentInstance() as ComponentInternalInstance;
     const { treatment_user_type, treatment_user_status, evaluation_status, physical_activity, user_sex } = toRefs < any > (proxy ?.useDict('treatment_user_type', 'treatment_user_status', 'evaluation_status', 'physical_activity', 'user_sex'));
     const userList = ref < TreatmentUserVo[] > ([]);
@@ -269,7 +269,11 @@ import { get } from 'http';
     // 点击标签切换
     const handleTabClick = (tabType: string) => {
         activeTab.value = tabType;
-        getList(); // 重新加载数据
+        if (tabType === 'waiting') {
+            getList(); // 重新加载数据
+        } else {
+            userList.value = [];
+        }
     };
 
     const queryFormRef = ref < ElFormInstance > ();
@@ -362,7 +366,7 @@ import { get } from 'http';
                     });
                 }
             });
-            
+
             // 为每个患者添加科室名称
             userList.value = res.rows.map(patient => ({
                 ...patient,
@@ -376,33 +380,33 @@ import { get } from 'http';
             loading.value = false;
         }
     }
-   const getDeptList = async () => {
-    loading.value = true;
-    try {
-        const res = await listDept({});
-        if (!res.data) {
-            console.warn("部门数据为空");
-            treeData.value = [];
-            return;
-        }
-        
-        // 处理树形数据
-        const processedData = proxy?.handleTree(res.data, 'deptId');
-        if (!processedData) {
-            console.warn("树形数据处理失败");
+    const getDeptList = async () => {
+        loading.value = true;
+        try {
+            const res = await listDept({});
+            if (!res.data) {
+                console.warn("部门数据为空");
+                treeData.value = [];
+                return;
+            }
+
+            // 处理树形数据
+            const processedData = proxy ?.handleTree(res.data, 'deptId');
+            if (!processedData) {
+                console.warn("树形数据处理失败");
+                treeData.value = [];
+                return;
+            }
+
+            treeData.value = processedData;
+
+        } catch (error) {
+            console.error('获取部门列表失败:', error);
             treeData.value = [];
-            return;
+        } finally {
+            loading.value = false;
         }
-        
-        treeData.value = processedData;
-        
-    } catch (error) {
-        console.error('获取部门列表失败:', error);
-        treeData.value = [];
-    } finally {
-        loading.value = false;
-    }
-};
+    };
     const getDictLabel = (dictList, value) => {
         if (!Array.isArray(dictList)) return value || '--';
         const item = dictList.find(item => item.value === value);
@@ -605,12 +609,11 @@ import { get } from 'http';
     const showDetail = ref(false);
     const detailData = ref({});
     const showPatientDetail = async (patient) => {
-        
+
         // 这里可以根据需要请求详情接口,或直接用patient
         detailData.value = { ...patient };
         showDetail.value = true;
     };
-
 </script>
 <style scoped>
     .item {
@@ -729,7 +732,7 @@ import { get } from 'http';
 
     .gender-icon {
         font-size: 25px;
-        font-weight:bold;
+        font-weight: bold;
     }
 
     .gender-icon.female {

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio