删除以前的业务代码
This commit is contained in:
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* @description 药材管理接口
|
||||
*/
|
||||
|
||||
import { moduleRequest } from "@/api/request";
|
||||
import { ResPage } from "@/api/interface";
|
||||
|
||||
// 请求前缀,根据后端路由配置
|
||||
const http = moduleRequest("/biz/weibingju/medicinal/");
|
||||
|
||||
/**
|
||||
* 药材接口
|
||||
*/
|
||||
const medicinalApi = {
|
||||
/** 获取药材分页列表 */
|
||||
page(params: { name?: string; pageNum?: number; pageSize?: number }) {
|
||||
return http.get<ResPage<MedicinalInfo>>("list", params);
|
||||
},
|
||||
|
||||
/** 获取药材下拉字典 */
|
||||
getDictList() {
|
||||
return http.get<MedicinalInfo[]>("getmedicinaldictlist");
|
||||
},
|
||||
|
||||
/** 获取药材消耗记录 */
|
||||
getConsumptionRecords(params: { id: number; pageNum?: number; pageSize?: number }) {
|
||||
console.log("获取添加记录,请求参数=", params);
|
||||
return http.get<ResPage<any>>(`consumption-records`, params); // 透传分页参数
|
||||
},
|
||||
|
||||
/** 获取药材添加记录 */
|
||||
getAdditionRecords(params: { id: number; pageNum?: number; pageSize?: number }) {
|
||||
return http.get<ResPage<any>>(`addition-records`, params);
|
||||
},
|
||||
|
||||
/** 添加药材 */
|
||||
addMedicinal(params: AddMedicinalInput) {
|
||||
return http.post("add", params);
|
||||
},
|
||||
|
||||
/** 修改药材添加记录 */
|
||||
updateAdditionRecord(params: UpdateMedicinalAddLogInput) {
|
||||
return http.post(`addition-records`, params);
|
||||
},
|
||||
|
||||
/** 删除药材添加记录 */
|
||||
deleteAdditionRecord(params: { id: number }) {
|
||||
return http.post(`addition-delete`, params);
|
||||
}
|
||||
};
|
||||
|
||||
/** 药材信息 */
|
||||
export interface MedicinalInfo {
|
||||
id?: number;
|
||||
name: string;
|
||||
unit?: string;
|
||||
stock?: number;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
/** 添加药材 */
|
||||
export interface AddMedicinalInput {
|
||||
medicinalTypeId: number;
|
||||
addWeight: number;
|
||||
totalPrice: number;
|
||||
medicinalName: string;
|
||||
}
|
||||
|
||||
/** 修改添加记录 */
|
||||
export interface UpdateMedicinalAddLogInput {
|
||||
id: number;
|
||||
addWeight: number;
|
||||
totalPrice: number;
|
||||
}
|
||||
|
||||
export { medicinalApi };
|
||||
@@ -1,155 +0,0 @@
|
||||
import { moduleRequest } from "@/api/request";
|
||||
import { ResPage } from "@/api/interface";
|
||||
|
||||
const http = moduleRequest("/biz/weibingju/prescription/");
|
||||
|
||||
// -----------------------------
|
||||
// 类型定义(对应后端 DTO)
|
||||
// -----------------------------
|
||||
|
||||
/** 人员类型 */
|
||||
export enum PersonType {
|
||||
Employee = 1,
|
||||
Relative = 2
|
||||
}
|
||||
|
||||
/** 处方列表 DTO */
|
||||
export interface PrescriptionDto {
|
||||
id: number;
|
||||
personId: number;
|
||||
personName: string;
|
||||
personType: PersonType;
|
||||
employeeName?: string;
|
||||
visitDate?: string;
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
/** 处方药材 DTO */
|
||||
export interface PrescriptionHerbDto {
|
||||
Id: number;
|
||||
medicinalName: string;
|
||||
amountG: number;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
/** 人员详情 DTO */
|
||||
export interface PersonDetailDto {
|
||||
id?: number;
|
||||
name: string;
|
||||
age?: number;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
isEmployee: boolean;
|
||||
employeeId?: number;
|
||||
employeeName?: string;
|
||||
relationShip?: number;
|
||||
relationShipName?: string;
|
||||
}
|
||||
|
||||
/** 处方详情 DTO */
|
||||
export interface PrescriptionDetailDto {
|
||||
id: number;
|
||||
person: PersonDetailDto;
|
||||
diagnosisResult: string;
|
||||
userMedicinaAdvice: string;
|
||||
visitDate?: string;
|
||||
herbs: PrescriptionHerbDto[];
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
/** 保存处方输入 DTO */
|
||||
export interface SavePrescriptionInput {
|
||||
id?: number;
|
||||
person: PersonInputDto;
|
||||
diagnosisResult: string;
|
||||
userMedicinaAdvice: string;
|
||||
visitDate?: string;
|
||||
herbs: PrescriptionHerbInputDto[];
|
||||
}
|
||||
|
||||
/** 人员输入 DTO */
|
||||
export interface PersonInputDto {
|
||||
id?: number;
|
||||
name: string;
|
||||
age?: number;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
isEmployee: boolean;
|
||||
employeeId?: number;
|
||||
relationShip?: number;
|
||||
}
|
||||
|
||||
/** 处方药材输入 DTO */
|
||||
export interface PrescriptionHerbInputDto {
|
||||
Id: number;
|
||||
amountG: number;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
/** 人员 DTO(列表用) */
|
||||
export interface PersonDto {
|
||||
id: number;
|
||||
name: string;
|
||||
age?: number;
|
||||
employeeId?: number;
|
||||
}
|
||||
|
||||
/** 添加人员输入 DTO */
|
||||
export interface AddPersonInput {
|
||||
name: string;
|
||||
age?: number;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
isEmployee: boolean;
|
||||
employeeId?: number;
|
||||
relationShip?: number;
|
||||
}
|
||||
|
||||
/** 关系类型 DTO */
|
||||
export interface RelationTypeDto {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// API 方法(对应后端接口)
|
||||
// -----------------------------
|
||||
|
||||
const prescriptionApi = {
|
||||
/** 获取处方列表 */
|
||||
getList(params: any) {
|
||||
return http.get<ResPage<PrescriptionDto>>("list", params);
|
||||
},
|
||||
|
||||
/** 获取处方详情 */
|
||||
getDetail(id: number) {
|
||||
return http.get<PrescriptionDetailDto>(`getprescriptiondetile?id=${id}`);
|
||||
},
|
||||
|
||||
/** 保存处方(新增/编辑) */
|
||||
save(params: SavePrescriptionInput) {
|
||||
return http.post<number>("add", params);
|
||||
},
|
||||
|
||||
/** 获取人员列表 */
|
||||
getPersonList(params: { type?: PersonType; employeeId?: number }) {
|
||||
return http.get<PersonDto[]>("persons", params);
|
||||
},
|
||||
|
||||
/** 添加人员 */
|
||||
addPerson(params: AddPersonInput) {
|
||||
return http.post<number>("addpersons", params);
|
||||
},
|
||||
|
||||
/** 获取关系类型 */
|
||||
getRelationTypes() {
|
||||
return http.get<RelationTypeDto[]>("relation-types");
|
||||
},
|
||||
|
||||
/** 获取处方总价 */
|
||||
getTotalCost() {
|
||||
return http.get<number>("gettotalcost");
|
||||
}
|
||||
};
|
||||
|
||||
export { prescriptionApi };
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* @description 微病句统计分析接口
|
||||
*/
|
||||
|
||||
import { moduleRequest } from "@/api/request";
|
||||
|
||||
// 请求前缀
|
||||
const http = moduleRequest("/biz/weibingju/statistics/");
|
||||
|
||||
/**
|
||||
* 统计接口
|
||||
*/
|
||||
const statisticsApi = {
|
||||
/** 获取全量总览数据(不区分年份,含剩余药材库存价值) */
|
||||
getTotalOverview() {
|
||||
return http.get<TotalOverviewDto>("overview");
|
||||
},
|
||||
|
||||
/** 获取年度统计数据 */
|
||||
getYearlyStatistics(params: { year: string }) {
|
||||
return http.get<YearlyStatisticsDto>("yearly", params);
|
||||
},
|
||||
|
||||
/** 获取月度明细数据 */
|
||||
getMonthlyDetails(params: { year: string }) {
|
||||
return http.get<MonthlyDetailDto[]>("monthly", params);
|
||||
}
|
||||
};
|
||||
|
||||
/** 全量总览数据 DTO */
|
||||
export interface TotalOverviewDto {
|
||||
totalCost: number; // 历史处方总花费
|
||||
totalQty: number; // 历史处方总数量
|
||||
staffCost: number; // 员工花费
|
||||
familyCost: number; // 家属花费
|
||||
staffQty: number; // 员工处方数
|
||||
familyQty: number; // 家属处方数
|
||||
materialCost: number; // 药材采购总花费
|
||||
serviceCount: number; // 累计服务人数
|
||||
remainingMedicinalValue: number; // 当前剩余药材库存价值
|
||||
}
|
||||
|
||||
/** 年度统计数据 DTO */
|
||||
export interface YearlyStatisticsDto {
|
||||
year: string;
|
||||
totalCost: number; // 总花费
|
||||
totalQty: number; // 总数量
|
||||
staffCost: number; // 员工花费
|
||||
familyCost: number; // 家属花费
|
||||
staffQty: number; // 员工处方数
|
||||
familyQty: number; // 家属处方数
|
||||
materialCost: number; // 药材花费
|
||||
serviceCount: number; // 服务人数
|
||||
|
||||
// 同比趋势(百分比)
|
||||
totalCostTrend: number; // 处方总花费趋势
|
||||
totalQtyTrend: number; // 处方总数量趋势
|
||||
materialCostTrend: number; // 药材花费趋势
|
||||
serviceCountTrend: number; // 服务人数趋势
|
||||
}
|
||||
|
||||
/** 月度明细数据 DTO */
|
||||
export interface MonthlyDetailDto {
|
||||
month: string; // 月份
|
||||
staffCost: number; // 员工处方花费
|
||||
familyCost: number; // 家属处方花费
|
||||
staffQty: number; // 员工处方数量
|
||||
familyQty: number; // 家属处方数量
|
||||
materialCost: number; // 药材花费
|
||||
}
|
||||
|
||||
export { statisticsApi };
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
* @description
|
||||
* @license Apache License Version 2.0
|
||||
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
|
||||
@@ -15,6 +15,3 @@
|
||||
|
||||
export * from "./organization";
|
||||
export * from "./ops";
|
||||
export * from "./WeiBingJu/medicinal";
|
||||
export * from "./WeiBingJu/prescription";
|
||||
export * from "./WeiBingJu/statistics";
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
<template>
|
||||
<el-dialog :model-value="visible" @update:model-value="handleUpdateVisible" title="添加药材" width="600px"
|
||||
destroy-on-close :close-on-click-modal="false">
|
||||
<el-form :model="form" label-width="120px" ref="formRef" class="mt-2" :rules="formRules">
|
||||
<!-- 药材下拉 + 未找到按钮 -->
|
||||
<el-form-item v-if="!isAddingNew" label="药材名称" prop="Id" style="display: flex; align-items: center">
|
||||
<el-select v-model="form.Id" placeholder="请选择药材" filterable style="flex: 1; margin-right: 8px">
|
||||
<el-option v-for="item in medicinalList" :key="item.id" :label="item.medicinalName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button type="text" @click="handleNotFound">未找到</el-button>
|
||||
</el-form-item>
|
||||
<!-- 新药材输入框 -->
|
||||
<el-form-item label="新药材名称" v-if="isAddingNew" prop="medicinalName">
|
||||
<el-input v-model="form.medicinalName" placeholder="请输入新药材名称" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="添加量(g)" prop="addWeight">
|
||||
<el-input v-model.number="form.addWeight" type="number" min="0.01" step="0.01" placeholder="请输入添加量" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 改为总价输入 -->
|
||||
<el-form-item label="总价" prop="totalPrice">
|
||||
<el-input v-model.number="form.totalPrice" type="number" min="0" step="0.01" placeholder="请输入总价(元)" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确认添加</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, computed } from "vue";
|
||||
import { medicinalApi } from "@/api/modules/biz/weibingju/medicinal";
|
||||
import { ElMessage, ElForm, FormRules } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false }
|
||||
});
|
||||
const emit = defineEmits(["update:visible", "close", "refreshList"]);
|
||||
|
||||
const medicinalList = ref<any[]>([]);
|
||||
const isAddingNew = ref(false);
|
||||
|
||||
const formRef = ref<InstanceType<typeof ElForm>>();
|
||||
const form = reactive({
|
||||
Id: null as number | null,
|
||||
addWeight: 0,
|
||||
// 前端改为 totalPrice
|
||||
totalPrice: 0,
|
||||
medicinalName: ""
|
||||
});
|
||||
|
||||
// 动态表单校验(注意 totalPrice 字段)
|
||||
const formRules = computed<FormRules>(() => ({
|
||||
Id: [{ required: !isAddingNew.value, message: "请选择药材", trigger: "change" }],
|
||||
medicinalName: [{ required: isAddingNew.value, message: "请输入新药材名称", trigger: "blur" }],
|
||||
addWeight: [
|
||||
{ required: true, message: "请输入添加量", trigger: "blur" },
|
||||
{ type: "number", min: 0.01, message: "添加量不能小于0.01", trigger: "blur" }
|
||||
],
|
||||
totalPrice: [
|
||||
{ required: true, message: "请输入总价", trigger: "blur" },
|
||||
{ type: "number", min: 0, message: "总价不能为负", trigger: "blur" }
|
||||
]
|
||||
}));
|
||||
|
||||
const fetchMedicinalList = async () => {
|
||||
try {
|
||||
const res = await medicinalApi.getDictList();
|
||||
medicinalList.value = res.data || [];
|
||||
} catch (err) {
|
||||
medicinalList.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
async newVal => {
|
||||
if (newVal) {
|
||||
handleResetForm();
|
||||
await fetchMedicinalList();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const handleUpdateVisible = (newVisible: boolean) => {
|
||||
emit("update:visible", newVisible);
|
||||
if (!newVisible) {
|
||||
handleResetForm();
|
||||
emit("close");
|
||||
}
|
||||
};
|
||||
const handleCancel = () => emit("update:visible", false);
|
||||
const handleResetForm = () => {
|
||||
form.Id = null;
|
||||
form.addWeight = 0;
|
||||
form.totalPrice = 0;
|
||||
form.medicinalName = "";
|
||||
isAddingNew.value = false;
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
const handleNotFound = () => {
|
||||
isAddingNew.value = true;
|
||||
form.Id = null;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算单价,并校验 addWeight > 0
|
||||
if (!form.addWeight || form.addWeight <= 0) {
|
||||
ElMessage.warning("添加量需大于 0");
|
||||
return;
|
||||
}
|
||||
const payload: any = {
|
||||
Id: form.Id,
|
||||
addWeight: form.addWeight,
|
||||
totalPrice: form.totalPrice,
|
||||
medicinalName: form.medicinalName
|
||||
};
|
||||
|
||||
try {
|
||||
await medicinalApi.addMedicinal(payload);
|
||||
ElMessage.success("添加成功");
|
||||
emit("update:visible", false);
|
||||
emit("refreshList");
|
||||
} catch (err: any) {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,219 +0,0 @@
|
||||
<template>
|
||||
<el-dialog :model-value="props.visible" :title="`${props.medicinalName} - 添加记录`" width="1200px"
|
||||
@close="handleDialogClose" @update:model-value="handleUpdateVisible" append-to-body
|
||||
:body-class="'el-dialog__body-new'" :close-on-click-modal="false">
|
||||
<ProTable ref="proTableRef" title="添加记录" :columns="columns" :request-api="getAdditionRecordsApi" :row-key="rowKey"
|
||||
:border="true" :show-selection="false">
|
||||
<!-- 行内列 slot:addWeight -->
|
||||
<template #addWeight="{ row }">
|
||||
<template v-if="editingId === row.id">
|
||||
<el-input-number v-model.number="editModel.addWeight" :min="0.01" :step="0.01" controls-position="right"
|
||||
size="small" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ row.addWeight }}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- unitPrice 列:只展示单价,不编辑 -->
|
||||
<template #unitPrice="{ row }">
|
||||
{{ (row.unitPrice ?? 0).toFixed(5) }}
|
||||
</template>
|
||||
|
||||
<!-- totalPrice 列:查看时显示合计,编辑时可以修改 -->
|
||||
<template #totalPrice="{ row }">
|
||||
<template v-if="editingId === row.id">
|
||||
<el-input-number v-model.number="editModel.totalPrice" :min="0" :step="0.01" controls-position="right"
|
||||
size="small" placeholder="输入总价(元)" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ row.totalPrice }}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- addTime 格式化 -->
|
||||
<template #addTime="{ row }">
|
||||
{{ row.addTime ? formatDate(row.addTime) : "-" }}
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<template #operation="{ row }">
|
||||
<template v-if="editingId === row.id">
|
||||
<el-button size="small" type="primary" @click="saveRowEdit(row)" :loading="saving">保存</el-button>
|
||||
<el-button size="small" @click="cancelRowEdit">取消</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button v-if="row.canEdit" type="text" size="small" @click="startRowEdit(row)">编辑</el-button>
|
||||
<el-button v-if="row.canEdit" type="text" size="small" style="color: #ff4d4f"
|
||||
@click="handleDeleteRecord(row.id)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</ProTable>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 单行行内编辑版本(总价 totalPrice 输入):
|
||||
* - 点击「编辑」:将该行复制到 editModel(editModel.addWeight & editModel.totalPrice),记录 editingId(只允许单行编辑)
|
||||
* - 取消:不调用后端,直接清除 editingId(恢复显示)
|
||||
*/
|
||||
|
||||
import { defineProps, defineEmits, ref, reactive, watch, nextTick } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import { medicinalApi } from "@/api";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
id: { type: Number, required: true },
|
||||
medicinalName: { type: String, default: "药材" }
|
||||
});
|
||||
const emit = defineEmits(["update:visible", "close", "refreshList"]);
|
||||
|
||||
// proTable 引用(用于 refresh)
|
||||
const proTableRef = ref<any | null>(null);
|
||||
|
||||
// 当前正在编辑的行 id(单行)
|
||||
const editingId = ref<number | null>(null);
|
||||
|
||||
// 编辑模型(只存一行):注意 totalPrice
|
||||
const editModel = reactive({
|
||||
addWeight: 0,
|
||||
totalPrice: 0
|
||||
});
|
||||
|
||||
// 保存中标记,避免重复提交
|
||||
const saving = ref(false);
|
||||
|
||||
// 列定义,slotName 使用 prop 名称(与 ProTable slot 对应)
|
||||
const columns = [
|
||||
{ prop: "addWeight", label: "添加量(g)", minWidth: 120, slotName: "addWeight" },
|
||||
{ prop: "unitPrice", label: "单价(元/g)", minWidth: 120, slotName: "unitPrice" },
|
||||
{ prop: "totalPrice", label: "总价(元)", minWidth: 120, slotName: "totalPrice" },
|
||||
{ prop: "addTime", label: "添加时间", minWidth: 200, slotName: "addTime" },
|
||||
{ prop: "addUserName", label: "添加人员", minWidth: 150 },
|
||||
{ prop: "operation", label: "操作", width: 180, fixed: "right", slotName: "operation" }
|
||||
];
|
||||
|
||||
const rowKey = (row: any) => row.id;
|
||||
|
||||
// 打开弹窗时刷新表格
|
||||
watch(
|
||||
() => props.visible,
|
||||
async val => {
|
||||
if (val && props.id) {
|
||||
console.log("打开添加记录弹窗,药材ID=", props.id);
|
||||
await nextTick();
|
||||
proTableRef.value?.refresh?.();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 将 ProTable 的请求透传到后端(ProTable 会带上 pageNum/pageSize 等)
|
||||
const getAdditionRecordsApi = (params: any) => {
|
||||
return medicinalApi.getAdditionRecords({
|
||||
id: props.id,
|
||||
...params
|
||||
});
|
||||
};
|
||||
|
||||
// 开始编辑:把当前行复制到 editModel(addWeight 和 totalPrice)
|
||||
const startRowEdit = (row: any) => {
|
||||
if (editingId.value !== null && editingId.value !== row.id) {
|
||||
ElMessage.warning("请先保存或取消当前正在编辑的行");
|
||||
return;
|
||||
}
|
||||
editingId.value = row.id;
|
||||
editModel.addWeight = row.addWeight ?? 0;
|
||||
// 后端返回的是 unitPrice,前端要显示/编辑 totalPrice = unitPrice * addWeight
|
||||
editModel.totalPrice = row.totalPrice;
|
||||
};
|
||||
|
||||
// 取消编辑:清空 editingId(恢复显示)
|
||||
const cancelRowEdit = () => {
|
||||
editingId.value = null;
|
||||
editModel.addWeight = 0;
|
||||
editModel.totalPrice = 0;
|
||||
};
|
||||
|
||||
// 保存编辑:计算 unitPrice = totalPrice / addWeight -> 发送到后端
|
||||
const saveRowEdit = async (row: any) => {
|
||||
// 基本校验
|
||||
if (!editModel.addWeight || editModel.addWeight <= 0) {
|
||||
ElMessage.warning("添加量需大于 0");
|
||||
return;
|
||||
}
|
||||
if (editModel.totalPrice < 0) {
|
||||
ElMessage.warning("总价不能为负");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
saving.value = true;
|
||||
|
||||
await medicinalApi.updateAdditionRecord({
|
||||
id: row.id,
|
||||
addWeight: editModel.addWeight,
|
||||
totalPrice: editModel.totalPrice
|
||||
});
|
||||
|
||||
ElMessage.success("保存成功");
|
||||
// 刷新表格并退出编辑
|
||||
await proTableRef.value?.refresh?.();
|
||||
emit("refreshList");
|
||||
cancelRowEdit();
|
||||
} catch (err: any) {
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 删除记录
|
||||
const handleDeleteRecord = async (id: number) => {
|
||||
ElMessageBox.confirm("确定要删除这条添加记录吗?删除后不可恢复!", "确认删除", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await medicinalApi.deleteAdditionRecord({ id: id });
|
||||
ElMessage.success("删除成功");
|
||||
await proTableRef.value?.refresh?.();
|
||||
emit("refreshList");
|
||||
} catch (err: any) {
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
/* 用户取消删除 */
|
||||
});
|
||||
};
|
||||
|
||||
// 格式化时间
|
||||
const formatDate = (dateStr: string) => {
|
||||
const d = new Date(String(dateStr).replace(" ", "T"));
|
||||
return isNaN(d.getTime()) ? dateStr : d.toLocaleString();
|
||||
};
|
||||
|
||||
// 处理弹窗关闭
|
||||
const handleDialogClose = () => {
|
||||
editingId.value = null;
|
||||
editModel.addWeight = 0;
|
||||
editModel.totalPrice = 0;
|
||||
emit("update:visible", false);
|
||||
emit("close");
|
||||
};
|
||||
const handleUpdateVisible = (newVal: boolean) => {
|
||||
if (!newVal) handleDialogClose();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.el-dialog__body-new {
|
||||
height: 550px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<el-dialog :model-value="props.visible" :title="`${props.medicinalName} - 消耗记录`" width="800px"
|
||||
@close="handleDialogClose" @update:model-value="handleUpdateVisible" append-to-body
|
||||
:body-class="'el-dialog__body-new'" :close-on-click-modal="false">
|
||||
<!-- 统一使用ProTable实现列表(带分页),与AdditionRecordDialog风格保持一致 -->
|
||||
<ProTable ref="proTableRef" title="消耗记录列表" :columns="columns" :request-api="getConsumptionRecordsApi"
|
||||
:row-key="rowKey" :show-selection="false" :border="true">
|
||||
<!-- 人员列:包含家属标记的自定义渲染 -->
|
||||
<template #personName="{ row }">
|
||||
<span>{{ row.personName }}</span>
|
||||
<el-tag size="small" type="info" v-if="row.isRelative" style="margin-left: 8px">
|
||||
家属({{ row.employeeName || "未知员工" }})
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<!-- 使用时间:格式化渲染 -->
|
||||
<template #useTime="{ row }">
|
||||
{{ row.useTime ? formatDate(row.useTime) : "-" }}
|
||||
</template>
|
||||
</ProTable>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref, watch, nextTick } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import { medicinalApi } from "@/api";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
/** 1. 定义Props(与父组件传参匹配,参考AdditionRecordDialog) */
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
id: { // 对应父组件传的「currentMedicinalId」,与AdditionRecordDialog的id参数统一
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
medicinalName: {
|
||||
type: String,
|
||||
default: "药材"
|
||||
}
|
||||
});
|
||||
|
||||
/** 2. 定义Emits(与AdditionRecordDialog事件机制统一) */
|
||||
const emit = defineEmits(["update:visible", "close", "refreshList"]);
|
||||
|
||||
/** 3. 状态管理(ProTable引用 + 无编辑状态,仅列表) */
|
||||
const proTableRef = ref<any | null>(null); // ProTable实例引用,用于刷新列表
|
||||
|
||||
/** 4. 列配置(与消耗记录字段匹配,仅保留展示列) */
|
||||
const columns = [
|
||||
{
|
||||
prop: "amountG",
|
||||
label: "使用量(g)",
|
||||
minWidth: 100
|
||||
},
|
||||
{
|
||||
prop: "personName",
|
||||
label: "使用人员",
|
||||
minWidth: 250,
|
||||
slotName: "personName" // 关联自定义模板
|
||||
},
|
||||
{
|
||||
prop: "useTime",
|
||||
label: "使用时间",
|
||||
minWidth: 150,
|
||||
slotName: "useTime" // 关联时间格式化模板
|
||||
}
|
||||
];
|
||||
|
||||
/** 5. 行唯一标识(与后端返回的主键匹配) */
|
||||
const rowKey = (row: any) => row.id;
|
||||
|
||||
/** 6. 接口请求(透传ProTable分页参数,与AdditionRecordDialog逻辑统一) */
|
||||
const getConsumptionRecordsApi = (params: any) => {
|
||||
// 调用药材消耗记录接口,携带「药材ID」和「分页参数」
|
||||
return medicinalApi.getConsumptionRecords({
|
||||
id: props.id, // 药材ID(必传)
|
||||
...params // 分页参数(pageNum、pageSize等,从ProTable传入)
|
||||
});
|
||||
};
|
||||
|
||||
/** 7. 时间格式化工具(与AdditionRecordDialog格式统一) */
|
||||
const formatDate = (dateStr: string) => {
|
||||
const d = new Date(String(dateStr).replace(" ", "T"));
|
||||
return isNaN(d.getTime()) ? dateStr : d.toLocaleString();
|
||||
};
|
||||
|
||||
/** 8. 弹窗显示/隐藏监听(弹窗显示时刷新列表,与AdditionRecordDialog逻辑统一) */
|
||||
watch(
|
||||
() => props.visible,
|
||||
async (isVisible) => {
|
||||
if (isVisible && props.id) {
|
||||
await nextTick(); // 等待ProTable渲染完成
|
||||
proTableRef.value?.refresh?.(); // 刷新列表数据
|
||||
}
|
||||
},
|
||||
{ immediate: true } // 初始加载时触发
|
||||
);
|
||||
|
||||
/** 9. 弹窗关闭逻辑(与AdditionRecordDialog统一,清空状态+通知父组件) */
|
||||
const handleDialogClose = () => {
|
||||
emit("update:visible", false); // 通知父组件更新弹窗状态
|
||||
emit("close"); // 触发关闭事件(可选)
|
||||
};
|
||||
|
||||
/** 10. 弹窗状态更新回调(与Element Plus Dialog事件匹配) */
|
||||
const handleUpdateVisible = (newVal: boolean) => {
|
||||
if (!newVal) { // 仅当弹窗关闭时执行清理逻辑
|
||||
handleDialogClose();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.el-dialog__body-new {
|
||||
height: 550px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<div class="table-box">
|
||||
<ProTable ref="proTable" title="药材列表" :columns="columns" :request-api="medicinalApi.page">
|
||||
<template #tableHeader>
|
||||
<!-- 新增按钮:保持框架一致的 s-button 写法 -->
|
||||
<s-button suffix="药材" @click="onOpenAdd" />
|
||||
</template>
|
||||
|
||||
<template #operation="scope">
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" @click="handleViewConsumption(scope.row)"> 查看消耗记录
|
||||
</s-button>
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" class="ml-2" @click="handleViewAddition(scope.row)">
|
||||
查看添加记录 </s-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
<!-- 消耗记录弹窗 -->
|
||||
<consumption-record-dialog v-model:visible="showConsumptionDialog" :id="currentMedicinalId"
|
||||
:medicinal-name="currentMedicinalName" />
|
||||
|
||||
<!-- 添加记录弹窗 -->
|
||||
<addition-record-dialog :visible="showAdditionDialog" :id="currentMedicinalId"
|
||||
:medicinal-name="currentMedicinalName" @update:visible="val => (showAdditionDialog = val)"
|
||||
@refresh-list="handleRefresh" />
|
||||
|
||||
<!-- 新增药材弹窗 -->
|
||||
<add-medicinal-dialog v-model:visible="showAddMedicinalDialog" @refresh-list="handleRefresh" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx" name="sysModule">
|
||||
import { medicinalApi, MedicinalInfo } from "@/api";
|
||||
import { ref } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import type { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
|
||||
|
||||
import { FormOptEnum } from "@/enums";
|
||||
|
||||
// 子组件
|
||||
import ConsumptionRecordDialog from "./components/ConsumptionRecordDialog.vue";
|
||||
import AdditionRecordDialog from "./components/AdditionRecordDialog.vue";
|
||||
import AddMedicinalDialog from "./components/AddMedicinalDialog.vue";
|
||||
|
||||
const proTable = ref<ProTableInstance | null>(null);
|
||||
|
||||
const showConsumptionDialog = ref(false);
|
||||
const showAdditionDialog = ref(false);
|
||||
const showAddMedicinalDialog = ref(false);
|
||||
|
||||
const currentMedicinalId = ref<number | null>(null);
|
||||
const currentMedicinalName = ref<string>("");
|
||||
|
||||
const columns: ColumnProps<MedicinalInfo>[] = [
|
||||
{ type: "selection", fixed: "left", width: 80 },
|
||||
{ prop: "medicinalName", label: "药材名称", search: { el: "input" } },
|
||||
{ prop: "totalUsedWeight", label: "使用量(g)" },
|
||||
{ prop: "stock", label: "药材库存(g)" },
|
||||
{ prop: "usedCost", label: "预估使用成本" },
|
||||
{ prop: "remainingValue", label: "预估剩余价值" },
|
||||
{ prop: "operation", label: "操作", width: 240, fixed: "right" }
|
||||
];
|
||||
|
||||
// 打开新增药材弹窗
|
||||
function onOpenAdd() {
|
||||
showAddMedicinalDialog.value = true;
|
||||
}
|
||||
|
||||
// 查看消耗记录
|
||||
function handleViewConsumption(row: MedicinalInfo) {
|
||||
currentMedicinalId.value = row.Id ?? (row as any).id ?? null;
|
||||
currentMedicinalName.value = row.medicinalName ?? "";
|
||||
showConsumptionDialog.value = true;
|
||||
}
|
||||
|
||||
// 查看添加记录
|
||||
function handleViewAddition(row: MedicinalInfo) {
|
||||
console.log("查看添加记录", row);
|
||||
// 直接设置正确的ID和名称,然后显示弹窗
|
||||
currentMedicinalId.value = row.id ?? (row as any).id ?? null;
|
||||
currentMedicinalName.value = row.medicinalName ?? "";
|
||||
showAdditionDialog.value = true;
|
||||
}
|
||||
|
||||
// 刷新列表
|
||||
function handleRefresh() {
|
||||
proTable.value?.refresh?.();
|
||||
}
|
||||
</script>
|
||||
@@ -1,983 +0,0 @@
|
||||
<template>
|
||||
<el-dialog :model-value="visible" :title="dialogTitle" width="1000px" destroy-on-close @close="handleClose"
|
||||
:body-class="'modal-class'" @update:model-value="handleVisibleChange" :close-on-click-modal="false">
|
||||
<!-- 表单根节点:查看模式禁用,新增/编辑模式可交互 -->
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" class="prescription-form"
|
||||
:disabled="isViewMode">
|
||||
<!-- 1. 人员信息 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">人员信息</div>
|
||||
</template>
|
||||
|
||||
<!-- 人员类型 -->
|
||||
<el-form-item label="人员类型" prop="personType">
|
||||
<el-radio-group v-model="formData.personType" @change="handlePersonTypeChange" :disabled="isViewMode">
|
||||
<el-radio :label="1">公司员工</el-radio>
|
||||
<el-radio :label="2">员工家属</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 公司员工模式 -->
|
||||
<template v-if="formData.personType === 1">
|
||||
<!-- 员工姓名 -->
|
||||
<el-form-item label="员工姓名" prop="employeeInfo">
|
||||
<div class="flex items-center gap-2">
|
||||
<el-select v-if="showEmployeeSelect" v-model="formData.employeeId" placeholder="请选择员工" filterable
|
||||
:loading="employeeLoading" class="flex-1" @change="handleEmployeeChange" @clear="handleEmployeeClear"
|
||||
:disabled="isViewMode">
|
||||
<el-option v-for="item in employeeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button v-if="!isViewMode" type="primary" size="small" @click="handleOpenAddEmployeeDialog">
|
||||
新增员工
|
||||
</el-button>
|
||||
</div>
|
||||
<el-input v-if="!showEmployeeSelect && !formData.employeeId" v-model="formData.newEmployeeName"
|
||||
placeholder="请输入员工姓名" class="mt-2" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
<!-- 员工性质 -->
|
||||
<el-form-item label="员工性质" prop="type">
|
||||
<el-radio-group v-model="formData.type" :disabled="isViewMode">
|
||||
<el-radio :label="1">领导</el-radio>
|
||||
<el-radio :label="2">普通员工</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 员工家属模式 -->
|
||||
<template v-if="formData.personType === 2">
|
||||
<!-- 关联员工 -->
|
||||
<el-form-item label="关联员工" prop="relatedEmployeeInfo">
|
||||
<div class="flex items-center gap-2">
|
||||
<el-select v-if="showRelatedEmployeeSelect" v-model="formData.relatedEmployeeId" placeholder="请选择关联员工"
|
||||
filterable :loading="employeeLoading" class="flex-1" @change="handleRelatedEmployeeChange"
|
||||
@clear="handleRelatedEmployeeClear" :disabled="isViewMode">
|
||||
<el-option v-for="item in employeeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<!-- 新增/编辑模式显示"新增关联员工"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" size="small" @click="handleOpenAddRelatedEmployeeDialog">
|
||||
新增员工
|
||||
</el-button>
|
||||
</div>
|
||||
<el-input v-if="!showRelatedEmployeeSelect && !formData.relatedEmployeeId"
|
||||
v-model="formData.newRelatedEmployeeName" placeholder="请输入关联员工姓名" class="mt-2" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 家属姓名 -->
|
||||
<el-form-item label="家属姓名" prop="relativeInfo">
|
||||
<div class="flex items-center gap-2">
|
||||
<el-select v-if="showRelativeSelect && (formData.relatedEmployeeId || formData.newRelatedEmployeeName)"
|
||||
v-model="formData.relativeId" placeholder="请选择家属" filterable :loading="relativeLoading" class="flex-1"
|
||||
@change="handleRelativeChange" @clear="handleRelativeClear" :disabled="isViewMode">
|
||||
<el-option v-for="item in relativeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input v-else v-model="formData.newRelativeName" placeholder="请输入家属姓名" class="flex-1"
|
||||
:disabled="!formData.relatedEmployeeId && !formData.newRelatedEmployeeName || isViewMode" />
|
||||
<!-- 新增/编辑模式显示"新增家属"按钮 -->
|
||||
<el-button
|
||||
v-if="!isViewMode && showRelativeSelect && formData.relatedEmployeeId && !formData.newRelatedEmployeeName"
|
||||
type="primary" size="small" @click="handleOpenAddRelativeDialog">
|
||||
新增家属
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 亲属关系 -->
|
||||
<el-form-item label="亲属关系" prop="relationShip">
|
||||
<el-select v-model="formData.relationShip" placeholder="请选择亲属关系" :disabled="isViewMode">
|
||||
<el-option v-for="item in relationTypes" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 出生日期、体重、身高 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker v-model="formData.birthday" type="date" placeholder="请选择出生日期" format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD" class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="当前体重(kg)" prop="weight">
|
||||
<el-input-number v-model="formData.weight" :min="0" :max="500" :precision="1" placeholder="请输入体重"
|
||||
class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="身高(cm)" prop="height">
|
||||
<el-input-number v-model="formData.height" :min="0" :max="300" :precision="1" placeholder="请输入身高"
|
||||
class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 2. 药材消耗 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">
|
||||
药材消耗
|
||||
<!-- 新增/编辑模式显示"添加药材"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" size="small" class="ml-4" @click="addHerb">
|
||||
添加药材
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="formData.herbs" border>
|
||||
<el-table-column label="药材名称--剩余量" width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-select v-model="row.id" placeholder="请选择药材" filterable :loading="medicinalLoading"
|
||||
@change="handleMedicinalChange($index)" :disabled="isViewMode">
|
||||
<el-option v-for="item in medicinalOptions" :key="item.id"
|
||||
:label="`${item.medicinalName}--${item.stock}g`" :value="item.id" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消耗(g)" width="200">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.amountG" :min="0" :precision="2" placeholder="消耗量" class="w-full"
|
||||
:disabled="isViewMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.note" placeholder="请输入备注" :disabled="isViewMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<!-- 新增/编辑模式显示"移除"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="danger" size="small" @click="removeHerb($index)">
|
||||
移除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 3. 诊断信息 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">诊断信息</div>
|
||||
</template>
|
||||
|
||||
<el-form-item label="诊断结果" prop="diagnosisResult">
|
||||
<el-input v-model="formData.diagnosisResult" type="textarea" :rows="3" placeholder="请输入诊断结果"
|
||||
:disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用药建议" prop="userMedicinaAdvice">
|
||||
<el-input v-model="formData.userMedicinaAdvice" type="textarea" :rows="3" placeholder="请输入用药建议"
|
||||
:disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
|
||||
<!-- 4. 就诊信息 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">就诊信息</div>
|
||||
</template>
|
||||
|
||||
<el-form-item label="就诊时间" prop="visitDate">
|
||||
<el-date-picker v-model="formData.visitDate" type="datetime" placeholder="请选择就诊时间" format="YYYY-MM-DD HH:mm"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
</el-form>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<!-- 新增/编辑模式显示提交按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" :loading="submitLoading" @click="handleSubmit">
|
||||
{{ isEdit ? '更新' : '保存' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 新增员工弹窗(仅在新增/编辑模式显示) -->
|
||||
<el-dialog v-if="!isViewMode" v-model="showAddEmployeeDialog" title="新增员工" width="400px">
|
||||
<el-form :model="newEmployeeForm" label-width="80px" ref="newEmployeeFormRef">
|
||||
<el-form-item label="员工姓名" prop="name">
|
||||
<el-input v-model="newEmployeeForm.name" placeholder="请输入员工姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAddEmployeeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddEmployee">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增关联员工弹窗(仅在新增/编辑模式显示) -->
|
||||
<el-dialog v-if="!isViewMode" v-model="showAddRelatedEmployeeDialog" title="新增关联员工" width="400px">
|
||||
<el-form :model="newRelatedEmployeeForm" label-width="80px" ref="newRelatedEmployeeFormRef">
|
||||
<el-form-item label="员工姓名" prop="name">
|
||||
<el-input v-model="newRelatedEmployeeForm.name" placeholder="请输入员工姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAddRelatedEmployeeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddRelatedEmployee">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增家属弹窗(仅在新增/编辑模式显示) -->
|
||||
<el-dialog v-if="!isViewMode" v-model="showAddRelativeDialog" title="新增家属" width="400px">
|
||||
<el-form :model="newRelativeForm" label-width="80px" ref="newRelativeFormRef">
|
||||
<el-form-item label="家属姓名" prop="name">
|
||||
<el-input v-model="newRelativeForm.name" placeholder="请输入家属姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAddRelativeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddRelative">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
|
||||
import { prescriptionApi } from '@/api'
|
||||
import { medicinalApi } from '@/api/modules/biz/WeiBingJu/medicinal'
|
||||
|
||||
// 接口定义
|
||||
interface Employee {
|
||||
id: string | number;
|
||||
name: string;
|
||||
birthday?: string;
|
||||
height?: number;
|
||||
type?: number;
|
||||
}
|
||||
interface Relative {
|
||||
id: string | number;
|
||||
name: string;
|
||||
employeeId?: string | number;
|
||||
birthday?: string;
|
||||
height?: number;
|
||||
relationShip?: number;
|
||||
}
|
||||
interface Medicinal { id: number | string; medicinalName: string; stock: number }
|
||||
interface Herb { id?: number | string; medicinalName: string; amountG: number; note: string }
|
||||
|
||||
// Props定义:区分新增(无id)、编辑(有id且isEdit=true)、查看(有id且isEdit=false)
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
prescriptionId?: number;
|
||||
isEdit: boolean
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
prescriptionId: undefined,
|
||||
isEdit: false
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
"update:visible": [value: boolean];
|
||||
"refresh-list": [];
|
||||
}>()
|
||||
|
||||
// 核心模式判断:查看模式 = 有处方ID且非编辑
|
||||
const isViewMode = computed(() => !!props.prescriptionId && !props.isEdit)
|
||||
// 弹窗标题:根据模式动态显示
|
||||
const dialogTitle = computed(() => {
|
||||
if (isViewMode.value) return '查看就诊处方'
|
||||
return props.isEdit ? '编辑就诊处方' : '新增就诊处方'
|
||||
})
|
||||
|
||||
// 表单引用 & 状态
|
||||
const formRef = ref<FormInstance>()
|
||||
const newEmployeeFormRef = ref<FormInstance>()
|
||||
const newRelatedEmployeeFormRef = ref<FormInstance>()
|
||||
const newRelativeFormRef = ref<FormInstance>()
|
||||
const submitLoading = ref(false)
|
||||
const isEdit = computed(() => props.isEdit)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
personType: 1,
|
||||
type: undefined as number | undefined,
|
||||
employeeId: undefined as string | number | undefined,
|
||||
newEmployeeName: '',
|
||||
relatedEmployeeId: undefined as string | number | undefined,
|
||||
newRelatedEmployeeName: '',
|
||||
relativeId: undefined as string | number | undefined,
|
||||
newRelativeName: '',
|
||||
relationShip: undefined as number | undefined,
|
||||
birthday: undefined as string | undefined,
|
||||
weight: undefined as number | undefined,
|
||||
height: undefined as number | undefined,
|
||||
herbs: [] as Herb[],
|
||||
diagnosisResult: '',
|
||||
userMedicinaAdvice: '',
|
||||
visitDate: ''
|
||||
})
|
||||
|
||||
// 表单校验规则
|
||||
const formRules: FormRules = {
|
||||
personType: [{ required: true, message: '请选择人员类型', trigger: 'change' }],
|
||||
type: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 1 && !formData.value.type) {
|
||||
callback(new Error('请选择员工性质'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'change'
|
||||
}],
|
||||
employeeInfo: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 1) {
|
||||
if (!formData.value.employeeId && !formData.value.newEmployeeName) {
|
||||
callback(new Error('请选择或输入员工姓名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ['change', 'blur']
|
||||
}],
|
||||
relatedEmployeeInfo: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 2) {
|
||||
if (!formData.value.relatedEmployeeId && !formData.value.newRelatedEmployeeName) {
|
||||
callback(new Error('请选择或输入关联员工姓名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ['change', 'blur']
|
||||
}],
|
||||
relativeInfo: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 2) {
|
||||
if (!formData.value.relativeId && !formData.value.newRelativeName) {
|
||||
callback(new Error('请选择或输入家属姓名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ['change', 'blur']
|
||||
}],
|
||||
relationShip: [{
|
||||
required: formData.value.personType === 2,
|
||||
message: '请选择亲属关系',
|
||||
trigger: 'change'
|
||||
}],
|
||||
visitDate: [{ required: true, message: '请选择就诊时间', trigger: 'change' }],
|
||||
diagnosisResult: [{ required: true, message: '请输入诊断结果', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
// 数据源 & 弹窗状态
|
||||
const employeeOptions = ref<Employee[]>([])
|
||||
const employeeLoading = ref(false)
|
||||
const showEmployeeSelect = ref(true)
|
||||
const showRelatedEmployeeSelect = ref(true)
|
||||
|
||||
const relativeOptions = ref<Relative[]>([])
|
||||
const relativeLoading = ref(false)
|
||||
const showRelativeSelect = ref(true)
|
||||
|
||||
const relationTypes = ref<{ id: number; name: string }[]>([])
|
||||
const medicinalOptions = ref<Medicinal[]>([])
|
||||
const medicinalLoading = ref(false)
|
||||
|
||||
const showAddEmployeeDialog = ref(false)
|
||||
const showAddRelatedEmployeeDialog = ref(false)
|
||||
const showAddRelativeDialog = ref(false)
|
||||
const newEmployeeForm = ref({ name: '' })
|
||||
const newRelatedEmployeeForm = ref({ name: '' })
|
||||
const newRelativeForm = ref({ name: '' })
|
||||
|
||||
// 本地临时人员集合
|
||||
const localCreatedPersons = ref<Array<{
|
||||
tempId: string
|
||||
name: string
|
||||
isEmployee: boolean
|
||||
employeeTempId?: string
|
||||
employeeId?: number
|
||||
relationShip?: number
|
||||
}>>([])
|
||||
|
||||
// 生成临时ID
|
||||
const genTempId = (prefix = 'tmp') => `${prefix}_${Date.now()}_${Math.floor(Math.random() * 1000)}`
|
||||
|
||||
// 检查名称重复
|
||||
const checkNameDuplicate = (name: string, isEmployee: boolean) => {
|
||||
const normalizedName = name.trim()
|
||||
if (isEmployee) {
|
||||
return employeeOptions.value.some(item =>
|
||||
(item.name || '').trim() === normalizedName ||
|
||||
localCreatedPersons.value.some(p => p.isEmployee && p.name.trim() === normalizedName)
|
||||
)
|
||||
} else {
|
||||
return relativeOptions.value.some(item =>
|
||||
(item.name || '').trim() === normalizedName ||
|
||||
localCreatedPersons.value.some(p => !p.isEmployee && p.name.trim() === normalizedName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载数据接口
|
||||
const fetchEmployees = async (keyword?: string) => {
|
||||
try {
|
||||
employeeLoading.value = true
|
||||
const params: any = { type: 1 }
|
||||
if (keyword) params.keyword = keyword
|
||||
const res: any = await prescriptionApi.getPersonList(params)
|
||||
employeeOptions.value = (res && res.data) ? res.data : []
|
||||
} catch (err) {
|
||||
console.error('获取员工列表失败', err)
|
||||
employeeOptions.value = []
|
||||
} finally {
|
||||
employeeLoading.value = false
|
||||
}
|
||||
}
|
||||
const loadRelatives = async (employeeId: number | string) => {
|
||||
try {
|
||||
relativeLoading.value = true
|
||||
if (typeof employeeId === 'string' && employeeId.startsWith('tmp_')) {
|
||||
relativeOptions.value = []
|
||||
showRelativeSelect.value = false
|
||||
ElMessage.info('该员工为本地新增,暂无家属数据,请手动输入家属姓名')
|
||||
} else {
|
||||
const res: any = await prescriptionApi.getPersonList({ type: 2, employeeId: Number(employeeId) })
|
||||
relativeOptions.value = (res && res.data) ? res.data : []
|
||||
showRelativeSelect.value = relativeOptions.value.length > 0
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载家属失败', err)
|
||||
relativeOptions.value = []
|
||||
showRelativeSelect.value = false
|
||||
} finally {
|
||||
relativeLoading.value = false
|
||||
}
|
||||
}
|
||||
const fetchRelationTypes = async () => {
|
||||
try {
|
||||
const res: any = await prescriptionApi.getRelationTypes()
|
||||
relationTypes.value = (res && res.data) ? res.data : []
|
||||
} catch (err) {
|
||||
relationTypes.value = [
|
||||
{ id: 1, name: '配偶' },
|
||||
{ id: 2, name: '子女' },
|
||||
{ id: 3, name: '父母' },
|
||||
{ id: 4, name: '兄弟姐妹' },
|
||||
{ id: 5, name: '其他' }
|
||||
]
|
||||
console.error('获取关系类型失败', err)
|
||||
}
|
||||
}
|
||||
const loadAllMedicinals = async () => {
|
||||
try {
|
||||
medicinalLoading.value = true
|
||||
const res: any = await medicinalApi.getDictList()
|
||||
medicinalOptions.value = (res && res.data) ? res.data : []
|
||||
} catch (err) {
|
||||
console.error('加载药材失败', err)
|
||||
medicinalOptions.value = []
|
||||
} finally {
|
||||
medicinalLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 选择回调
|
||||
const handleEmployeeChange = (selectedId: string | number | undefined) => {
|
||||
if (selectedId && !isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newEmployeeName = ''
|
||||
showEmployeeSelect.value = true
|
||||
const selectedEmployee = employeeOptions.value.find(item => item.id === selectedId)
|
||||
if (selectedEmployee) {
|
||||
formData.value.birthday = selectedEmployee.birthday
|
||||
formData.value.height = selectedEmployee.height
|
||||
formData.value.type = selectedEmployee.type
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleEmployeeClear = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.type = undefined
|
||||
}
|
||||
}
|
||||
const handleRelatedEmployeeChange = (selectedId: string | number | undefined) => {
|
||||
if (selectedId && !isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
showRelatedEmployeeSelect.value = true
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
loadRelatives(selectedId)
|
||||
}
|
||||
}
|
||||
const handleRelatedEmployeeClear = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
relativeOptions.value = []
|
||||
}
|
||||
}
|
||||
const handleRelativeChange = (selectedId: string | number | undefined) => {
|
||||
if (selectedId && !isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelativeName = ''
|
||||
showRelativeSelect.value = true
|
||||
const selectedRelative = relativeOptions.value.find(item => item.id === selectedId)
|
||||
if (selectedRelative) {
|
||||
formData.value.birthday = selectedRelative.birthday
|
||||
formData.value.height = selectedRelative.height
|
||||
formData.value.relationShip = selectedRelative.relationShip
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleRelativeClear = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
}
|
||||
}
|
||||
const handleMedicinalChange = (index: number) => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
const selectedMedicinalId = formData.value.herbs[index].id;
|
||||
if (selectedMedicinalId) {
|
||||
const sel = medicinalOptions.value.find(m => m.id === selectedMedicinalId);
|
||||
formData.value.herbs[index].medicinalName = sel ? sel.medicinalName : '';
|
||||
} else {
|
||||
formData.value.herbs[index].medicinalName = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
const handlePersonTypeChange = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.employeeId = undefined
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.relatedEmployeeId = undefined
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.relationShip = undefined
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
showEmployeeSelect.value = true
|
||||
showRelatedEmployeeSelect.value = true
|
||||
showRelativeSelect.value = true
|
||||
}
|
||||
}
|
||||
const addHerb = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.herbs.push({ id: undefined, medicinalName: '', amountG: 0, note: '' })
|
||||
}
|
||||
}
|
||||
const removeHerb = (index: number) => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.herbs.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 新增员工相关
|
||||
const handleOpenAddEmployeeDialog = () => {
|
||||
if (!isViewMode.value) {
|
||||
formData.value.employeeId = undefined
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
newEmployeeForm.value.name = ''
|
||||
showAddEmployeeDialog.value = true
|
||||
}
|
||||
}
|
||||
const confirmAddEmployee = async () => {
|
||||
if (!newEmployeeFormRef.value || isViewMode.value) return
|
||||
try {
|
||||
await newEmployeeFormRef.value.validate()
|
||||
const name = newEmployeeForm.value.name.trim()
|
||||
if (checkNameDuplicate(name, true)) {
|
||||
ElMessage.warning('该员工姓名已存在,请更换姓名')
|
||||
return
|
||||
}
|
||||
const tempId = genTempId('tmp_emp')
|
||||
employeeOptions.value.unshift({ id: tempId, name })
|
||||
localCreatedPersons.value.push({ tempId, name, isEmployee: true })
|
||||
formData.value.employeeId = tempId
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
showEmployeeSelect.value = true
|
||||
showAddEmployeeDialog.value = false
|
||||
newEmployeeForm.value.name = ''
|
||||
ElMessage.success('员工已添加')
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
// 新增关联员工相关
|
||||
const handleOpenAddRelatedEmployeeDialog = () => {
|
||||
if (!isViewMode.value) {
|
||||
formData.value.relatedEmployeeId = undefined
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
newRelatedEmployeeForm.value.name = ''
|
||||
showAddRelatedEmployeeDialog.value = true
|
||||
}
|
||||
}
|
||||
const confirmAddRelatedEmployee = async () => {
|
||||
if (!newRelatedEmployeeFormRef.value || isViewMode.value) return
|
||||
try {
|
||||
await newRelatedEmployeeFormRef.value.validate()
|
||||
const name = newRelatedEmployeeForm.value.name.trim()
|
||||
if (checkNameDuplicate(name, true)) {
|
||||
ElMessage.warning('该员工姓名已存在,请更换姓名')
|
||||
return
|
||||
}
|
||||
const tempId = genTempId('tmp_emp')
|
||||
employeeOptions.value.unshift({ id: tempId, name })
|
||||
localCreatedPersons.value.push({ tempId, name, isEmployee: true })
|
||||
formData.value.relatedEmployeeId = tempId
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
showRelatedEmployeeSelect.value = true
|
||||
showAddRelatedEmployeeDialog.value = false
|
||||
newRelatedEmployeeForm.value.name = ''
|
||||
loadRelatives(tempId)
|
||||
ElMessage.success('关联员工已添加')
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
// 新增家属相关
|
||||
const handleOpenAddRelativeDialog = () => {
|
||||
if (!isViewMode.value) {
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
newRelativeForm.value.name = ''
|
||||
showAddRelativeDialog.value = true
|
||||
}
|
||||
}
|
||||
const confirmAddRelative = async () => {
|
||||
if (!newRelativeFormRef.value || isViewMode.value) return
|
||||
try {
|
||||
await newRelativeFormRef.value.validate()
|
||||
const name = newRelativeForm.value.name.trim()
|
||||
const employeeId = formData.value.relatedEmployeeId
|
||||
if (!employeeId) {
|
||||
ElMessage.warning('请先选择关联员工')
|
||||
return
|
||||
}
|
||||
if (checkNameDuplicate(name, false)) {
|
||||
ElMessage.warning('该家属姓名已存在,请更换姓名')
|
||||
return
|
||||
}
|
||||
const tempId = genTempId('tmp_rel')
|
||||
relativeOptions.value.unshift({ id: tempId, name, employeeId })
|
||||
localCreatedPersons.value.push({
|
||||
tempId,
|
||||
name,
|
||||
isEmployee: false,
|
||||
employeeTempId: typeof employeeId === 'string' && employeeId.startsWith('tmp_') ? employeeId : undefined,
|
||||
employeeId: typeof employeeId === 'number' ? employeeId : undefined,
|
||||
relationShip: formData.value.relationShip
|
||||
})
|
||||
formData.value.relativeId = tempId
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
showRelativeSelect.value = true
|
||||
showAddRelativeDialog.value = false
|
||||
newRelativeForm.value.name = ''
|
||||
ElMessage.success('家属已添加')
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
// 重置/关闭/提交
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
resetForm()
|
||||
}
|
||||
const handleVisibleChange = (value: boolean) => {
|
||||
emit('update:visible', value)
|
||||
if (!value) resetForm()
|
||||
}
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
personType: 1,
|
||||
type: undefined,
|
||||
employeeId: undefined,
|
||||
newEmployeeName: '',
|
||||
relatedEmployeeId: undefined,
|
||||
newRelatedEmployeeName: '',
|
||||
relativeId: undefined,
|
||||
newRelativeName: '',
|
||||
relationShip: undefined,
|
||||
birthday: undefined,
|
||||
weight: undefined,
|
||||
height: undefined,
|
||||
herbs: [],
|
||||
diagnosisResult: '',
|
||||
userMedicinaAdvice: '',
|
||||
visitDate: ''
|
||||
}
|
||||
localCreatedPersons.value = []
|
||||
showEmployeeSelect.value = true
|
||||
showRelatedEmployeeSelect.value = true
|
||||
showRelativeSelect.value = true
|
||||
newEmployeeForm.value.name = ''
|
||||
newRelatedEmployeeForm.value.name = ''
|
||||
newRelativeForm.value.name = ''
|
||||
showAddEmployeeDialog.value = false
|
||||
showAddRelatedEmployeeDialog.value = false
|
||||
showAddRelativeDialog.value = false
|
||||
}
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value || isViewMode.value) return
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const personObj: any = {}
|
||||
const isPatientEmployee = formData.value.personType === 1
|
||||
personObj.isEmployee = isPatientEmployee
|
||||
personObj.type = isPatientEmployee ? formData.value.type : undefined
|
||||
|
||||
if (isPatientEmployee) {
|
||||
if (formData.value.employeeId) {
|
||||
if (typeof formData.value.employeeId === 'string' && String(formData.value.employeeId).startsWith('tmp_')) {
|
||||
const tmpEmp = localCreatedPersons.value.find(p => p.tempId === formData.value.employeeId && p.isEmployee)
|
||||
const name = tmpEmp ? tmpEmp.name : undefined
|
||||
if (name) {
|
||||
personObj.name = name
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = name
|
||||
} else {
|
||||
personObj.name = employeeOptions.value.find(e => e.id === formData.value.employeeId)?.name
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = personObj.name
|
||||
}
|
||||
} else {
|
||||
personObj.id = Number(formData.value.employeeId)
|
||||
personObj.name = employeeOptions.value.find(e => e.id === formData.value.employeeId)?.name
|
||||
}
|
||||
} else if (formData.value.newEmployeeName) {
|
||||
personObj.name = formData.value.newEmployeeName.trim()
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = personObj.name
|
||||
}
|
||||
} else {
|
||||
if (formData.value.relativeId) {
|
||||
if (typeof formData.value.relativeId === 'string' && String(formData.value.relativeId).startsWith('tmp_')) {
|
||||
const tmpRel = localCreatedPersons.value.find(p => p.tempId === formData.value.relativeId && !p.isEmployee)
|
||||
personObj.name = tmpRel ? tmpRel.name : relativeOptions.value.find(r => r.id === formData.value.relativeId)?.name
|
||||
personObj.tempId = formData.value.relativeId
|
||||
} else {
|
||||
personObj.id = Number(formData.value.relativeId)
|
||||
personObj.name = relativeOptions.value.find(r => r.id === formData.value.relativeId)?.name
|
||||
}
|
||||
} else if (formData.value.newRelativeName) {
|
||||
personObj.name = formData.value.newRelativeName.trim()
|
||||
}
|
||||
|
||||
if (formData.value.relatedEmployeeId) {
|
||||
if (typeof formData.value.relatedEmployeeId === 'string' && String(formData.value.relatedEmployeeId).startsWith('tmp_')) {
|
||||
const tmpEmp = localCreatedPersons.value.find(p => p.tempId === formData.value.relatedEmployeeId && p.isEmployee)
|
||||
const name = tmpEmp ? tmpEmp.name : employeeOptions.value.find(e => e.id === formData.value.relatedEmployeeId)?.name
|
||||
if (name) {
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = name
|
||||
} else {
|
||||
personObj.employeeId = formData.value.relatedEmployeeId
|
||||
}
|
||||
} else {
|
||||
personObj.employeeId = Number(formData.value.relatedEmployeeId)
|
||||
}
|
||||
} else if (formData.value.newRelatedEmployeeName) {
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = formData.value.newRelatedEmployeeName.trim()
|
||||
}
|
||||
|
||||
personObj.relationShip = formData.value.relationShip
|
||||
}
|
||||
|
||||
if ((!personObj.name || personObj.name === undefined) && personObj.id && typeof personObj.id === 'string' && String(personObj.id).startsWith('tmp_')) {
|
||||
const tmp = localCreatedPersons.value.find(p => p.tempId === personObj.id)
|
||||
if (tmp) personObj.name = tmp.name
|
||||
}
|
||||
|
||||
personObj.birthday = formData.value.birthday
|
||||
personObj.weight = formData.value.weight
|
||||
personObj.height = formData.value.height
|
||||
|
||||
const herbsPayload = formData.value.herbs.map(h => ({
|
||||
id: h.id || 0,
|
||||
amountG: h.amountG,
|
||||
note: h.note
|
||||
}))
|
||||
|
||||
const payload: any = {
|
||||
id: props.prescriptionId ?? undefined,
|
||||
person: personObj,
|
||||
diagnosisResult: formData.value.diagnosisResult,
|
||||
userMedicinaAdvice: formData.value.userMedicinaAdvice,
|
||||
visitDate: formData.value.visitDate,
|
||||
herbs: herbsPayload
|
||||
}
|
||||
|
||||
const res: any = await prescriptionApi.save(payload)
|
||||
|
||||
if (res && (res.code === 0 || res.data !== undefined)) {
|
||||
ElMessage.success(props.isEdit ? '处方更新成功' : '处方保存成功')
|
||||
emit('refresh-list')
|
||||
handleClose()
|
||||
} else {
|
||||
ElMessage.success('保存成功')
|
||||
emit('refresh-list')
|
||||
handleClose()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('保存处方失败', err)
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 监听弹窗显示
|
||||
watch(() => props.visible, async (newVal) => {
|
||||
if (newVal) {
|
||||
resetForm()
|
||||
await Promise.all([
|
||||
fetchEmployees(),
|
||||
fetchRelationTypes(),
|
||||
loadAllMedicinals()
|
||||
])
|
||||
|
||||
// 编辑/查看模式:加载详情
|
||||
if ((props.isEdit || isViewMode.value) && props.prescriptionId) {
|
||||
try {
|
||||
const res: any = await prescriptionApi.getDetail(props.prescriptionId)
|
||||
const detail = res?.data ?? null
|
||||
|
||||
if (detail) {
|
||||
const person = detail.person || {}
|
||||
formData.value.personType = person.isEmployee ? 1 : 2
|
||||
|
||||
if (formData.value.personType === 1) {
|
||||
formData.value.employeeId = person.id ?? undefined
|
||||
formData.value.birthday = person.birthday ?? undefined
|
||||
formData.value.height = person.height ?? undefined
|
||||
formData.value.type = person.type ?? undefined
|
||||
} else {
|
||||
formData.value.relatedEmployeeId = person.employeeId ?? undefined
|
||||
formData.value.relativeId = person.id ?? undefined
|
||||
formData.value.birthday = person.birthday ?? undefined
|
||||
formData.value.height = person.height ?? undefined
|
||||
formData.value.relationShip = person.relationShip ?? undefined
|
||||
if (formData.value.relatedEmployeeId) {
|
||||
loadRelatives(formData.value.relatedEmployeeId)
|
||||
}
|
||||
}
|
||||
|
||||
formData.value.weight = person.weight ?? undefined
|
||||
formData.value.diagnosisResult = detail.diagnosisResult ?? ''
|
||||
formData.value.userMedicinaAdvice = detail.userMedicinaAdvice ?? ''
|
||||
formData.value.visitDate = detail.visitDate ?? ''
|
||||
formData.value.herbs = (detail.herbs || []).map((h: any) => ({
|
||||
id: h.medicinalId,
|
||||
medicinalName: h.medicinalName,
|
||||
amountG: h.amountG,
|
||||
note: h.note || ''
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.modal-class {
|
||||
max-height: 60vh !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.prescription-form {
|
||||
.form-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ml-4 {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,375 +0,0 @@
|
||||
<template>
|
||||
<el-dialog v-model="visibleRef" title="处方报告" width="1500px" :body-class="'report-modal-body'" :show-close="false"
|
||||
:top="'0'" append-to-body>
|
||||
<!-- 报告核心内容 -->
|
||||
<div class="report-content">
|
||||
<!-- 3.1 就诊人基本信息 -->
|
||||
<div class="report-section">
|
||||
<h3 class="section-heading">一、就诊人基本信息</h3>
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="info-label">就诊人姓名:</span>
|
||||
<span class="info-value">{{ reportData.patientName || "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">出生日期:</span>
|
||||
<span class="info-value">{{ reportData.birthday || "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">身高:</span>
|
||||
<span class="info-value">{{ reportData.height ? `${reportData.height} cm` : "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">体重:</span>
|
||||
<span class="info-value">{{ reportData.weight ? `${reportData.weight} kg` : "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">就诊时间:</span>
|
||||
<span class="info-value">{{ reportData.visitDate || "暂无数据" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3.2 药材消耗明细(超紧凑卡片布局) -->
|
||||
<div class="report-section mt-16">
|
||||
<h3 class="section-heading">二、药材消耗明细</h3>
|
||||
<div class="herbs-grid-container">
|
||||
<!-- 单个药材卡片(更小尺寸) -->
|
||||
<div class="herb-card" v-for="(herb, index) in reportData.herbs" :key="index">
|
||||
<div class="herb-name">
|
||||
<span class="herb-label">名称:</span>
|
||||
{{ herb.medicinalName || "未命名药材" }}
|
||||
</div>
|
||||
<div class="herb-amount">
|
||||
<span class="herb-label">用量:</span>
|
||||
{{ herb.amountG !== undefined ? `${herb.amountG} g` : "0 g" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无药材空状态 -->
|
||||
<div v-if="reportData.herbs.length === 0" class="empty-herbs">
|
||||
<el-icon size="24" color="#9ca3af" class="empty-icon">
|
||||
<DocumentEmpty />
|
||||
</el-icon>
|
||||
<p class="empty-text">当前处方暂无药材消耗记录</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3.3 诊断与用药建议 -->
|
||||
<div class="report-section mt-16">
|
||||
<h3 class="section-heading">三、诊断与用药建议</h3>
|
||||
<div class="advice-container">
|
||||
<div class="advice-item">
|
||||
<span class="advice-label">诊断结果:</span>
|
||||
<div class="advice-content">
|
||||
{{ reportData.diagnosisResult || "暂无诊断结果描述" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="advice-item mt-8">
|
||||
<span class="advice-label">用药建议:</span>
|
||||
<div class="advice-content">
|
||||
{{ reportData.userMedicinaAdvice || "暂无用药建议描述" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">关闭报告</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { prescriptionApi } from "@/api";
|
||||
|
||||
// Props定义
|
||||
interface Props {
|
||||
modelValue: boolean;
|
||||
prescriptionId?: number;
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
prescriptionId: undefined,
|
||||
});
|
||||
|
||||
// 弹窗显隐控制
|
||||
const visibleRef = ref(props.modelValue);
|
||||
const emit = defineEmits<{
|
||||
"update:modelValue": [value: boolean];
|
||||
}>();
|
||||
|
||||
// 监听父组件传值,同步弹窗状态
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
visibleRef.value = newVal;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 数据状态
|
||||
const loading = ref(false);
|
||||
const error = ref(false);
|
||||
const errorMsg = ref("");
|
||||
const reportData = ref({
|
||||
patientName: "",
|
||||
birthday: "",
|
||||
height: undefined,
|
||||
weight: undefined,
|
||||
visitDate: "",
|
||||
herbs: [] as Array<{ medicinalName: string; amountG: number; note: string }>,
|
||||
diagnosisResult: "",
|
||||
userMedicinaAdvice: "",
|
||||
});
|
||||
|
||||
// 加载报告数据
|
||||
const fetchReportData = async () => {
|
||||
if (!props.prescriptionId) return;
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = false;
|
||||
const res: any = await prescriptionApi.getDetail(props.prescriptionId);
|
||||
const detail = res?.data || {};
|
||||
const person = detail.person || {};
|
||||
reportData.value = {
|
||||
patientName: person.name || "",
|
||||
birthday: person.birthday || "",
|
||||
height: person.height,
|
||||
weight: person.weight,
|
||||
visitDate: detail.visitDate || "",
|
||||
herbs: (detail.herbs || []).map((h: any) => ({
|
||||
medicinalName: h.medicinalName || "未命名药材",
|
||||
amountG: h.amountG || 0,
|
||||
note: h.note || "",
|
||||
})),
|
||||
diagnosisResult: detail.diagnosisResult || "",
|
||||
userMedicinaAdvice: detail.userMedicinaAdvice || "",
|
||||
};
|
||||
} catch (err: any) {
|
||||
error.value = true;
|
||||
errorMsg.value = err.message || "加载报告失败,请检查网络";
|
||||
ElMessage.error(errorMsg.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
emit("update:modelValue", false);
|
||||
};
|
||||
|
||||
// 弹窗关闭前重置数据
|
||||
const handleBeforeClose = () => {
|
||||
reportData.value = {
|
||||
patientName: "",
|
||||
birthday: "",
|
||||
height: undefined,
|
||||
weight: undefined,
|
||||
visitDate: "",
|
||||
herbs: [],
|
||||
diagnosisResult: "",
|
||||
userMedicinaAdvice: "",
|
||||
};
|
||||
error.value = false;
|
||||
errorMsg.value = "";
|
||||
};
|
||||
|
||||
// 监听处方ID变化,重新加载数据
|
||||
watch(
|
||||
() => props.prescriptionId,
|
||||
(newId) => {
|
||||
if (props.modelValue && newId) {
|
||||
fetchReportData();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.report-modal-body {
|
||||
// padding: 20px !important;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
background: #fff;
|
||||
overflow-y: auto !important;
|
||||
max-height: 100vh !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 报告通用样式 */
|
||||
.report-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.report-section {
|
||||
padding: 15px;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin: 0 0 12px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #409eff;
|
||||
}
|
||||
|
||||
/* 就诊人基本信息样式 */
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 药材消耗明细样式(超紧凑设计) */
|
||||
.herbs-grid-container {
|
||||
// display: grid;
|
||||
// /* 核心:每列最小宽度缩小到150px,可根据需要进一步减小到120px */
|
||||
// grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||
// gap: 8px;
|
||||
/* 卡片间距缩小 */
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
|
||||
}
|
||||
|
||||
/* 单个药材卡片(更小尺寸) */
|
||||
.herb-card {
|
||||
padding: 8px;
|
||||
/* 内边距大幅缩小 */
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 4px;
|
||||
background: #f9fafb;
|
||||
line-height: 1.3;
|
||||
/* 行高压缩 */
|
||||
font-size: 12px;
|
||||
/* 字体缩小 */
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
/* 卡片内标签样式 */
|
||||
.herb-label {
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
font-size: 13px;
|
||||
/* 标签字体更小 */
|
||||
}
|
||||
|
||||
/* 药材空状态样式 */
|
||||
.empty-herbs {
|
||||
grid-column: 1 / -1;
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
color: #9ca3af;
|
||||
background: #f9fafb;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 诊断与用药建议样式 */
|
||||
.advice-container {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.advice-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.advice-label {
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.advice-content {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 4px;
|
||||
min-height: 60px;
|
||||
line-height: 1.5;
|
||||
background: #f9fafb;
|
||||
word-break: break-all;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 间距工具类 */
|
||||
.mt-8 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mt-16 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* 加载/错误样式 */
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 16px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.error-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 300px;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
min-width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,150 +0,0 @@
|
||||
<template>
|
||||
<div class="table-box">
|
||||
<!-- 原有:处方列表(仅操作列新增“查看报告”按钮) -->
|
||||
<ProTable ref="proTable" title="处方列表" :columns="columns" :request-api="getPrescriptionListApi" :row-key="rowKey">
|
||||
<!-- 原有:表格头部按钮(不变) -->
|
||||
<template #tableHeader>
|
||||
<s-button suffix="处方" type="success" @click="handleAddPrescription" />
|
||||
<el-button type="primary" @click="handleViewTotalCost">查看处方总价</el-button>
|
||||
</template>
|
||||
|
||||
<!-- 原有:就诊人类型自定义插槽(不变) -->
|
||||
<template #personType="scope">
|
||||
<el-space>
|
||||
<div v-if="scope.row.personType === 1" class="flex items-center">
|
||||
<span>公司员工</span>
|
||||
<el-tag v-if="scope.row.type == 1" type="success" size="small" class="ml-2">领导</el-tag>
|
||||
<el-tag v-if="scope.row.type == 2" type="info" size="small" class="ml-2">普通员工</el-tag>
|
||||
</div>
|
||||
<span v-else-if="scope.row.personType === 2">
|
||||
员工家属,所属员工:{{ scope.row.employeeName || "未知" }}
|
||||
</span>
|
||||
<span v-else>未知类型</span>
|
||||
</el-space>
|
||||
</template>
|
||||
|
||||
<!-- 关键改动:操作列新增“查看报告”按钮 -->
|
||||
<template #operation="{ row }">
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" @click="handleViewDetail(row.id)">
|
||||
查看详情
|
||||
</s-button>
|
||||
<s-button v-if="row.canEdit" link :opt="FormOptEnum.EDIT" size="small" class="ml-2" @click="handleEdit(row.id)">
|
||||
编辑
|
||||
</s-button>
|
||||
<!-- 新增:触发报告弹窗 -->
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" class="ml-2" @click="handleOpenReport(row.id)">
|
||||
查看报告
|
||||
</s-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<!--处方详情/编辑弹窗 -->
|
||||
<PrescriptionDetailDialog v-model:visible="showDetailDialog" :prescription-id="currentPrescriptionId"
|
||||
:is-edit="isEdit" @refresh-list="handleRefresh" />
|
||||
|
||||
<!-- 报告弹窗组件 -->
|
||||
<PrescriptionReportDialog v-model="showReportDialog" :prescription-id="currentReportId" />
|
||||
|
||||
<!-- 处方总价弹窗 -->
|
||||
<el-dialog v-model="showTotalCostDialog" title="查看处方总价" width="400px" :close-on-click-modal="false">
|
||||
<div style="padding: 20px; text-align: center;">
|
||||
<div style="font-size: 16px; color: #606266; margin-bottom: 10px;">预估总药材成本</div>
|
||||
<div style="color: #f56c6c; font-size: 32px; font-weight: bold;">
|
||||
¥{{ totalCostData || 0 }}
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="showTotalCostDialog = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PrescriptionModule">
|
||||
import { ref } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
|
||||
import { prescriptionApi } from "@/api";
|
||||
// 原有:引入详情弹窗组件(不变)
|
||||
import PrescriptionDetailDialog from "./components/PrescriptionDetailDialog.vue";
|
||||
// 关键改动:引入独立的报告弹窗组件
|
||||
import PrescriptionReportDialog from "./components/PrescriptionReportDialog.vue";
|
||||
import { FormOptEnum } from "@/enums";
|
||||
|
||||
// 原有:表格ref、详情弹窗状态(不变)
|
||||
const proTable = ref<ProTableInstance | null>(null);
|
||||
const showDetailDialog = ref(false);
|
||||
const currentPrescriptionId = ref<number | undefined>(undefined);
|
||||
const isEdit = ref(false);
|
||||
|
||||
// 关键改动:新增报告弹窗相关状态
|
||||
const showReportDialog = ref(false); // 报告弹窗显隐
|
||||
const currentReportId = ref<number | undefined>(undefined); // 当前报告对应的处方ID
|
||||
|
||||
// 新增:处方总价弹窗相关状态
|
||||
const showTotalCostDialog = ref(false); // 总价弹窗显隐
|
||||
const totalCostData = ref<number>(0); // 总价数据
|
||||
|
||||
// 原有:就诊人类型选项、表格列配置(不变)
|
||||
const personTypeOptions = [
|
||||
{ label: "公司员工", value: 1 },
|
||||
{ label: "员工家属", value: 2 }
|
||||
];
|
||||
const columns: ColumnProps<any>[] = [
|
||||
{ type: "selection", fixed: "left", width: 80 },
|
||||
{ prop: "personName", label: "就诊人", search: { el: "input" } },
|
||||
{
|
||||
prop: "personType",
|
||||
label: "就诊人类型",
|
||||
sortable: false,
|
||||
enum: personTypeOptions,
|
||||
search: { el: "select" }
|
||||
},
|
||||
{ prop: "visitDate", label: "就诊时间" },
|
||||
{ prop: "createTime", label: "添加时间" },
|
||||
{ prop: "totalMedicineCost", label: "预估药材成本" },
|
||||
{ prop: "operation", label: "操作", width: 280, fixed: "right" }
|
||||
];
|
||||
const rowKey = "id";
|
||||
const getPrescriptionListApi = (params: any) => {
|
||||
return prescriptionApi.getList(params);
|
||||
};
|
||||
|
||||
//新增、查看详情、编辑、刷新
|
||||
const handleAddPrescription = () => {
|
||||
currentPrescriptionId.value = undefined;
|
||||
isEdit.value = false;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
const handleViewDetail = (id: number) => {
|
||||
currentPrescriptionId.value = id;
|
||||
isEdit.value = false;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
const handleEdit = (id: number) => {
|
||||
currentPrescriptionId.value = id;
|
||||
isEdit.value = true;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
const handleRefresh = () => {
|
||||
proTable.value?.refresh?.();
|
||||
};
|
||||
|
||||
// 打开报告弹窗
|
||||
const handleOpenReport = (id: number) => {
|
||||
currentReportId.value = id; // 传递当前处方ID给报告组件
|
||||
showReportDialog.value = true; // 显示报告弹窗
|
||||
};
|
||||
|
||||
// 新增:查看处方总价
|
||||
const handleViewTotalCost = async () => {
|
||||
showTotalCostDialog.value = true;
|
||||
try {
|
||||
const { data } = await prescriptionApi.getTotalCost();
|
||||
totalCostData.value = data || 0;
|
||||
} catch (error) {
|
||||
console.error("获取处方总价失败:", error);
|
||||
totalCostData.value = 0;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user