123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- <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>
|